aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Michel <luc.michel@amd.com>2023-10-17 21:44:21 +0200
committerPeter Maydell <peter.maydell@linaro.org>2023-10-27 15:27:06 +0100
commit71a082a3fa9845360224c66029eea8d972b8b8bd (patch)
tree001ffb0820a83eb3100c0d402ad9b2596782b80e
parent1b09eeb122aaf1666a9c5aa789eb219443772685 (diff)
hw/net/cadence_gem: perform PHY access on write only
The MDIO access is done only on a write to the PHYMNTNC register. A subsequent read is used to retrieve the result but does not trigger an MDIO access by itself. Refactor the PHY access logic to perform all accesses (MDIO reads and writes) at PHYMNTNC write time. Signed-off-by: Luc Michel <luc.michel@amd.com> Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-11-luc.michel@amd.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/net/cadence_gem.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 373d3ee071..06a101bfcd 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1521,6 +1521,38 @@ static void gem_phy_write(CadenceGEMState *s, unsigned reg_num, uint16_t val)
s->phy_regs[reg_num] = val;
}
+static void gem_handle_phy_access(CadenceGEMState *s)
+{
+ uint32_t val = s->regs[R_PHYMNTNC];
+ uint32_t phy_addr, reg_num;
+
+ phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR);
+
+ if (phy_addr != s->phy_addr) {
+ /* no phy at this address */
+ if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_READ) {
+ s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA, 0xffff);
+ }
+ return;
+ }
+
+ reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR);
+
+ switch (FIELD_EX32(val, PHYMNTNC, OP)) {
+ case MDIO_OP_READ:
+ s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA,
+ gem_phy_read(s, reg_num));
+ break;
+
+ case MDIO_OP_WRITE:
+ gem_phy_write(s, reg_num, val);
+ break;
+
+ default:
+ break; /* only clause 22 operations are supported */
+ }
+}
+
/*
* gem_read32:
* Read a GEM register.
@@ -1541,20 +1573,6 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
DB_PRINT("lowering irqs on ISR read\n");
/* The interrupts get updated at the end of the function. */
break;
- case R_PHYMNTNC:
- if (FIELD_EX32(retval, PHYMNTNC, OP) == MDIO_OP_READ) {
- uint32_t phy_addr, reg_num;
-
- phy_addr = FIELD_EX32(retval, PHYMNTNC, PHY_ADDR);
- if (phy_addr == s->phy_addr) {
- reg_num = FIELD_EX32(retval, PHYMNTNC, REG_ADDR);
- retval &= 0xFFFF0000;
- retval |= gem_phy_read(s, reg_num);
- } else {
- retval |= 0xFFFF; /* No device at this address */
- }
- }
- break;
}
/* Squash read to clear bits */
@@ -1665,15 +1683,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
s->sar_active[(offset - R_SPADDR1HI) / 2] = true;
break;
case R_PHYMNTNC:
- if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_WRITE) {
- uint32_t phy_addr, reg_num;
-
- phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR);
- if (phy_addr == s->phy_addr) {
- reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR);
- gem_phy_write(s, reg_num, val);
- }
- }
+ gem_handle_phy_access(s);
break;
}