Message ID | 20190304125933.5653-1-rasmus.villemoes@prevas.dk |
---|---|
State | RFC |
Delegated to: | David Miller |
Headers | show |
Series | [RFC] net: dsa: mv88e6xxx: support single chip sw_addr offset | expand |
On Mon, Mar 04, 2019 at 12:59:42PM +0000, Rasmus Villemoes wrote: > From: Per Noergaard Christensen <pnc@deif.com> > > The 88e6250 does not support multi-chip addressing. However, one can > still have two of them on the same mdio bus, since the device only > uses 16 of the 32 possible addresses, either addresses 0x00-0x0F or > 0x10-0x1F depending on the ADDR4 pin at reset [since ADDR4 is > internally pulled high, the latter is the default]. > > In order to prepare for supporting the 88e6250, change > mv88e6xxx_smi_init and the single_chip_{read,write} functions to allow > and honour a non-zero sw_addr in single chip mode. Since this only > changes the behaviour in the sw_addr!=0 && !chip->info->multi_chip > case from returning -EINVAL, it should not break existing setups. Hi Rasmus We have the nice abstraction of mv88e6xxx_smi_multi_chip_ops and mv88e6xxx_smi_single_chip_ops. I think we should extend this abstraction and implement mv88e6xxx_smi_dual_chip_ops. Also, add a chip->info->dual_chip flag, so we know when it can be used. Andrew
On 04/03/2019 14.45, Andrew Lunn wrote: > On Mon, Mar 04, 2019 at 12:59:42PM +0000, Rasmus Villemoes wrote: >> From: Per Noergaard Christensen <pnc@deif.com> >> >> The 88e6250 does not support multi-chip addressing. However, one can >> still have two of them on the same mdio bus, since the device only >> uses 16 of the 32 possible addresses, either addresses 0x00-0x0F or >> 0x10-0x1F depending on the ADDR4 pin at reset [since ADDR4 is >> internally pulled high, the latter is the default]. >> >> In order to prepare for supporting the 88e6250, change >> mv88e6xxx_smi_init and the single_chip_{read,write} functions to allow >> and honour a non-zero sw_addr in single chip mode. Since this only >> changes the behaviour in the sw_addr!=0 && !chip->info->multi_chip >> case from returning -EINVAL, it should not break existing setups. > > Hi Rasmus > > We have the nice abstraction of mv88e6xxx_smi_multi_chip_ops and > mv88e6xxx_smi_single_chip_ops. I think we should extend this > abstraction and implement mv88e6xxx_smi_dual_chip_ops. Also, add a > chip->info->dual_chip flag, so we know when it can be used. > Hi Andrew I should probably give a little more context, and mention that I don't actually have a board with two 88e6250 sitting on the same bus, so I can't test that such a setup will actually work (but I assume that's the whole point of the reset behaviour). But I do have a single 88e6250, at addresses 0x10-0x1f, and for that to get recognized I need to get mv88e6xxx_detect to look at smi address 0x10+0x8 (i.e., I also need to add another family to mv88e6xxx_of_match with port_base_addr = 0x08, and then somehow have mv88e6xxx_smi_read add a 0x10 offset). I can certainly do as you suggest instead, but I'm not sure what that buys us? Especially given that I can't test an actual dual chip setup, I think it's more natural to use a "single chip ops with an addr offset". Thanks, Rasmus
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9588a5f8719b..b482058d11dc 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -87,7 +87,7 @@ static int mv88e6xxx_smi_single_chip_read(struct mv88e6xxx_chip *chip, { int ret; - ret = mdiobus_read_nested(chip->bus, addr, reg); + ret = mdiobus_read_nested(chip->bus, addr + chip->sw_addr, reg); if (ret < 0) return ret; @@ -101,7 +101,7 @@ static int mv88e6xxx_smi_single_chip_write(struct mv88e6xxx_chip *chip, { int ret; - ret = mdiobus_write_nested(chip->bus, addr, reg, val); + ret = mdiobus_write_nested(chip->bus, addr + chip->sw_addr, reg, val); if (ret < 0) return ret; @@ -4601,11 +4601,12 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev) static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, struct mii_bus *bus, int sw_addr) { - if (sw_addr == 0) - chip->smi_ops = &mv88e6xxx_smi_single_chip_ops; - else if (chip->info->multi_chip) - chip->smi_ops = &mv88e6xxx_smi_multi_chip_ops; - else + if (sw_addr >= 0 && sw_addr <= 31) { + if (chip->info->multi_chip && sw_addr) + chip->smi_ops = &mv88e6xxx_smi_multi_chip_ops; + else + chip->smi_ops = &mv88e6xxx_smi_single_chip_ops; + } else return -EINVAL; chip->bus = bus;