aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2016-08-15 17:19:00 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-15 19:43:55 -0400
commite57e5e7769408b3899c2ef81422ab202dee7139d (patch)
treeac5f8e5ddf53ad1ee50df6fde4733c5f9483052c /drivers/net/dsa
parent57c67cf57a3898d234f029ca674f82d5bd2c080a (diff)
net: dsa: mv88e6xxx: abstract PHY ops
Old chips use a direct access to the PHY devices registers. Next chips have a PHY Polling Unit (PPU) which needs to be disabled before accessing PHY registers. Newer chips have an indirect access to the PHY devices so that disabling the PPU is not necessary. Introduce a new phy_ops structure in the chip to describe the required PHY access routines. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c131
-rw-r--r--drivers/net/dsa/mv88e6xxx/mv88e6xxx.h1
2 files changed, 81 insertions, 51 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 924a2af5ac6d..3b0bc88a3feb 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -216,6 +216,28 @@ static int mv88e6xxx_write(struct mv88e6xxx_chip *chip,
216 return 0; 216 return 0;
217} 217}
218 218
219static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
220 int reg, u16 *val)
221{
222 int addr = phy; /* PHY devices addresses start at 0x0 */
223
224 if (!chip->phy_ops)
225 return -EOPNOTSUPP;
226
227 return chip->phy_ops->read(chip, addr, reg, val);
228}
229
230static int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy,
231 int reg, u16 val)
232{
233 int addr = phy; /* PHY devices addresses start at 0x0 */
234
235 if (!chip->phy_ops)
236 return -EOPNOTSUPP;
237
238 return chip->phy_ops->write(chip, addr, reg, val);
239}
240
219static int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, 241static int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg,
220 u16 mask) 242 u16 mask)
221{ 243{
@@ -422,34 +444,39 @@ static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_chip *chip)
422 chip->ppu_timer.function = mv88e6xxx_ppu_reenable_timer; 444 chip->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
423} 445}
424 446
425static int mv88e6xxx_mdio_read_ppu(struct mv88e6xxx_chip *chip, int addr, 447static int mv88e6xxx_phy_ppu_read(struct mv88e6xxx_chip *chip, int addr,
426 int regnum) 448 int reg, u16 *val)
427{ 449{
428 int ret; 450 int err;
429 451
430 ret = mv88e6xxx_ppu_access_get(chip); 452 err = mv88e6xxx_ppu_access_get(chip);
431 if (ret >= 0) { 453 if (!err) {
432 ret = _mv88e6xxx_reg_read(chip, addr, regnum); 454 err = mv88e6xxx_read(chip, addr, reg, val);
433 mv88e6xxx_ppu_access_put(chip); 455 mv88e6xxx_ppu_access_put(chip);
434 } 456 }
435 457
436 return ret; 458 return err;
437} 459}
438 460
439static int mv88e6xxx_mdio_write_ppu(struct mv88e6xxx_chip *chip, int addr, 461static int mv88e6xxx_phy_ppu_write(struct mv88e6xxx_chip *chip, int addr,
440 int regnum, u16 val) 462 int reg, u16 val)
441{ 463{
442 int ret; 464 int err;
443 465
444 ret = mv88e6xxx_ppu_access_get(chip); 466 err = mv88e6xxx_ppu_access_get(chip);
445 if (ret >= 0) { 467 if (!err) {
446 ret = _mv88e6xxx_reg_write(chip, addr, regnum, val); 468 err = mv88e6xxx_write(chip, addr, reg, val);
447 mv88e6xxx_ppu_access_put(chip); 469 mv88e6xxx_ppu_access_put(chip);
448 } 470 }
449 471
450 return ret; 472 return err;
451} 473}
452 474
475static const struct mv88e6xxx_ops mv88e6xxx_phy_ppu_ops = {
476 .read = mv88e6xxx_phy_ppu_read,
477 .write = mv88e6xxx_phy_ppu_write,
478};
479
453static bool mv88e6xxx_6065_family(struct mv88e6xxx_chip *chip) 480static bool mv88e6xxx_6065_family(struct mv88e6xxx_chip *chip)
454{ 481{
455 return chip->info->family == MV88E6XXX_FAMILY_6065; 482 return chip->info->family == MV88E6XXX_FAMILY_6065;
@@ -3090,6 +3117,11 @@ static int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr,
3090 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd); 3117 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
3091} 3118}
3092 3119
3120static const struct mv88e6xxx_ops mv88e6xxx_g2_smi_phy_ops = {
3121 .read = mv88e6xxx_g2_smi_phy_read,
3122 .write = mv88e6xxx_g2_smi_phy_write,
3123};
3124
3093static int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) 3125static int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
3094{ 3126{
3095 u16 reg; 3127 u16 reg;
@@ -3249,56 +3281,35 @@ static int mv88e6xxx_mdio_page_write(struct dsa_switch *ds, int port, int page,
3249 return ret; 3281 return ret;
3250} 3282}
3251 3283
3252static int mv88e6xxx_port_to_mdio_addr(struct mv88e6xxx_chip *chip, int port) 3284static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
3253{
3254 if (port >= 0 && port < chip->info->num_ports)
3255 return port;
3256 return -EINVAL;
3257}
3258
3259static int mv88e6xxx_mdio_read(struct mii_bus *bus, int port, int regnum)
3260{ 3285{
3261 struct mv88e6xxx_chip *chip = bus->priv; 3286 struct mv88e6xxx_chip *chip = bus->priv;
3262 int addr = mv88e6xxx_port_to_mdio_addr(chip, port); 3287 u16 val;
3263 int ret; 3288 int err;
3264 3289
3265 if (addr < 0) 3290 if (phy >= chip->info->num_ports)
3266 return 0xffff; 3291 return 0xffff;
3267 3292
3268 mutex_lock(&chip->reg_lock); 3293 mutex_lock(&chip->reg_lock);
3269 3294 err = mv88e6xxx_phy_read(chip, phy, reg, &val);
3270 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
3271 ret = mv88e6xxx_mdio_read_ppu(chip, addr, regnum);
3272 else if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_SMI_PHY))
3273 ret = mv88e6xxx_mdio_read_indirect(chip, addr, regnum);
3274 else
3275 ret = mv88e6xxx_mdio_read_direct(chip, addr, regnum);
3276
3277 mutex_unlock(&chip->reg_lock); 3295 mutex_unlock(&chip->reg_lock);
3278 return ret; 3296
3297 return err ? err : val;
3279} 3298}
3280 3299
3281static int mv88e6xxx_mdio_write(struct mii_bus *bus, int port, int regnum, 3300static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
3282 u16 val)
3283{ 3301{
3284 struct mv88e6xxx_chip *chip = bus->priv; 3302 struct mv88e6xxx_chip *chip = bus->priv;
3285 int addr = mv88e6xxx_port_to_mdio_addr(chip, port); 3303 int err;
3286 int ret;
3287 3304
3288 if (addr < 0) 3305 if (phy >= chip->info->num_ports)
3289 return 0xffff; 3306 return 0xffff;
3290 3307
3291 mutex_lock(&chip->reg_lock); 3308 mutex_lock(&chip->reg_lock);
3292 3309 err = mv88e6xxx_phy_write(chip, phy, reg, val);
3293 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
3294 ret = mv88e6xxx_mdio_write_ppu(chip, addr, regnum, val);
3295 else if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_SMI_PHY))
3296 ret = mv88e6xxx_mdio_write_indirect(chip, addr, regnum, val);
3297 else
3298 ret = mv88e6xxx_mdio_write_direct(chip, addr, regnum, val);
3299
3300 mutex_unlock(&chip->reg_lock); 3310 mutex_unlock(&chip->reg_lock);
3301 return ret; 3311
3312 return err;
3302} 3313}
3303 3314
3304static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, 3315static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
@@ -3308,9 +3319,6 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
3308 struct mii_bus *bus; 3319 struct mii_bus *bus;
3309 int err; 3320 int err;
3310 3321
3311 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
3312 mv88e6xxx_ppu_state_init(chip);
3313
3314 if (np) 3322 if (np)
3315 chip->mdio_np = of_get_child_by_name(np, "mdio"); 3323 chip->mdio_np = of_get_child_by_name(np, "mdio");
3316 3324
@@ -3907,6 +3915,23 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
3907 return chip; 3915 return chip;
3908} 3916}
3909 3917
3918static const struct mv88e6xxx_ops mv88e6xxx_phy_ops = {
3919 .read = mv88e6xxx_read,
3920 .write = mv88e6xxx_write,
3921};
3922
3923static void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip)
3924{
3925 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_SMI_PHY)) {
3926 chip->phy_ops = &mv88e6xxx_g2_smi_phy_ops;
3927 } else if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU)) {
3928 chip->phy_ops = &mv88e6xxx_phy_ppu_ops;
3929 mv88e6xxx_ppu_state_init(chip);
3930 } else {
3931 chip->phy_ops = &mv88e6xxx_phy_ops;
3932 }
3933}
3934
3910static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, 3935static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
3911 struct mii_bus *bus, int sw_addr) 3936 struct mii_bus *bus, int sw_addr)
3912{ 3937{
@@ -3954,6 +3979,8 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
3954 if (err) 3979 if (err)
3955 goto free; 3980 goto free;
3956 3981
3982 mv88e6xxx_phy_init(chip);
3983
3957 err = mv88e6xxx_mdio_register(chip, NULL); 3984 err = mv88e6xxx_mdio_register(chip, NULL);
3958 if (err) 3985 if (err)
3959 goto free; 3986 goto free;
@@ -4055,6 +4082,8 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
4055 if (err) 4082 if (err)
4056 return err; 4083 return err;
4057 4084
4085 mv88e6xxx_phy_init(chip);
4086
4058 chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS); 4087 chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
4059 if (IS_ERR(chip->reset)) 4088 if (IS_ERR(chip->reset))
4060 return PTR_ERR(chip->reset); 4089 return PTR_ERR(chip->reset);
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 8be0f3681c66..1dd96e712342 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -634,6 +634,7 @@ struct mv88e6xxx_chip {
634 /* Handles automatic disabling and re-enabling of the PHY 634 /* Handles automatic disabling and re-enabling of the PHY
635 * polling unit. 635 * polling unit.
636 */ 636 */
637 const struct mv88e6xxx_ops *phy_ops;
637 struct mutex ppu_mutex; 638 struct mutex ppu_mutex;
638 int ppu_disabled; 639 int ppu_disabled;
639 struct work_struct ppu_work; 640 struct work_struct ppu_work;