Commit 2c340898 authored by Egil Hjelmeland's avatar Egil Hjelmeland Committed by David S. Miller

net: dsa: lan9303: MDIO access phy registers directly

Indirect access (PMI) to phy register only work in I2C mode. In
MDIO mode phy registers must be accessed directly. Introduced
struct lan9303_phy_ops to handle the two modes.
Signed-off-by: default avatarEgil Hjelmeland <privat@egil-hjelmeland.no>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9e866e5d
...@@ -334,6 +334,12 @@ static int lan9303_indirect_phy_write(struct lan9303 *chip, int addr, ...@@ -334,6 +334,12 @@ static int lan9303_indirect_phy_write(struct lan9303 *chip, int addr,
return ret; return ret;
} }
const struct lan9303_phy_ops lan9303_indirect_phy_ops = {
.phy_read = lan9303_indirect_phy_read,
.phy_write = lan9303_indirect_phy_write,
};
EXPORT_SYMBOL_GPL(lan9303_indirect_phy_ops);
static int lan9303_switch_wait_for_completion(struct lan9303 *chip) static int lan9303_switch_wait_for_completion(struct lan9303 *chip)
{ {
int ret, i; int ret, i;
...@@ -435,7 +441,7 @@ static int lan9303_detect_phy_setup(struct lan9303 *chip) ...@@ -435,7 +441,7 @@ static int lan9303_detect_phy_setup(struct lan9303 *chip)
* 0x0000, which means 'phy_addr_sel_strap' is 1 and the IDs are 1-2-3. * 0x0000, which means 'phy_addr_sel_strap' is 1 and the IDs are 1-2-3.
* 0xffff is returned on MDIO read with no response. * 0xffff is returned on MDIO read with no response.
*/ */
reg = lan9303_indirect_phy_read(chip, 3, MII_LAN911X_SPECIAL_MODES); reg = chip->ops->phy_read(chip, 3, MII_LAN911X_SPECIAL_MODES);
if (reg < 0) { if (reg < 0) {
dev_err(chip->dev, "Failed to detect phy config: %d\n", reg); dev_err(chip->dev, "Failed to detect phy config: %d\n", reg);
return reg; return reg;
...@@ -726,7 +732,7 @@ static int lan9303_phy_read(struct dsa_switch *ds, int phy, int regnum) ...@@ -726,7 +732,7 @@ static int lan9303_phy_read(struct dsa_switch *ds, int phy, int regnum)
if (phy > phy_base + 2) if (phy > phy_base + 2)
return -ENODEV; return -ENODEV;
return lan9303_indirect_phy_read(chip, phy, regnum); return chip->ops->phy_read(chip, phy, regnum);
} }
static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum, static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
...@@ -740,7 +746,7 @@ static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum, ...@@ -740,7 +746,7 @@ static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
if (phy > phy_base + 2) if (phy > phy_base + 2)
return -ENODEV; return -ENODEV;
return lan9303_indirect_phy_write(chip, phy, regnum, val); return chip->ops->phy_write(chip, phy, regnum, val);
} }
static int lan9303_port_enable(struct dsa_switch *ds, int port, static int lan9303_port_enable(struct dsa_switch *ds, int port,
...@@ -773,13 +779,13 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port, ...@@ -773,13 +779,13 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port,
switch (port) { switch (port) {
case 1: case 1:
lan9303_disable_packet_processing(chip, LAN9303_PORT_1_OFFSET); lan9303_disable_packet_processing(chip, LAN9303_PORT_1_OFFSET);
lan9303_indirect_phy_write(chip, chip->phy_addr_sel_strap + 1, lan9303_phy_write(ds, chip->phy_addr_sel_strap + 1,
MII_BMCR, BMCR_PDOWN); MII_BMCR, BMCR_PDOWN);
break; break;
case 2: case 2:
lan9303_disable_packet_processing(chip, LAN9303_PORT_2_OFFSET); lan9303_disable_packet_processing(chip, LAN9303_PORT_2_OFFSET);
lan9303_indirect_phy_write(chip, chip->phy_addr_sel_strap + 2, lan9303_phy_write(ds, chip->phy_addr_sel_strap + 2,
MII_BMCR, BMCR_PDOWN); MII_BMCR, BMCR_PDOWN);
break; break;
default: default:
dev_dbg(chip->dev, dev_dbg(chip->dev,
......
...@@ -2,6 +2,15 @@ ...@@ -2,6 +2,15 @@
#include <linux/device.h> #include <linux/device.h>
#include <net/dsa.h> #include <net/dsa.h>
struct lan9303;
struct lan9303_phy_ops {
/* PHY 1 and 2 access*/
int (*phy_read)(struct lan9303 *chip, int port, int regnum);
int (*phy_write)(struct lan9303 *chip, int port,
int regnum, u16 val);
};
struct lan9303 { struct lan9303 {
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
...@@ -11,9 +20,11 @@ struct lan9303 { ...@@ -11,9 +20,11 @@ struct lan9303 {
bool phy_addr_sel_strap; bool phy_addr_sel_strap;
struct dsa_switch *ds; struct dsa_switch *ds;
struct mutex indirect_mutex; /* protect indexed register access */ struct mutex indirect_mutex; /* protect indexed register access */
const struct lan9303_phy_ops *ops;
}; };
extern const struct regmap_access_table lan9303_register_set; extern const struct regmap_access_table lan9303_register_set;
extern const struct lan9303_phy_ops lan9303_indirect_phy_ops;
int lan9303_probe(struct lan9303 *chip, struct device_node *np); int lan9303_probe(struct lan9303 *chip, struct device_node *np);
int lan9303_remove(struct lan9303 *chip); int lan9303_remove(struct lan9303 *chip);
...@@ -63,6 +63,8 @@ static int lan9303_i2c_probe(struct i2c_client *client, ...@@ -63,6 +63,8 @@ static int lan9303_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, sw_dev); i2c_set_clientdata(client, sw_dev);
sw_dev->chip.dev = &client->dev; sw_dev->chip.dev = &client->dev;
sw_dev->chip.ops = &lan9303_indirect_phy_ops;
ret = lan9303_probe(&sw_dev->chip, client->dev.of_node); ret = lan9303_probe(&sw_dev->chip, client->dev.of_node);
if (ret != 0) if (ret != 0)
return ret; return ret;
......
...@@ -67,6 +67,25 @@ static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val) ...@@ -67,6 +67,25 @@ static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
return 0; return 0;
} }
int lan9303_mdio_phy_write(struct lan9303 *chip, int phy, int reg, u16 val)
{
struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);
return mdiobus_write_nested(sw_dev->device->bus, phy, reg, val);
}
int lan9303_mdio_phy_read(struct lan9303 *chip, int phy, int reg)
{
struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);
return mdiobus_read_nested(sw_dev->device->bus, phy, reg);
}
static const struct lan9303_phy_ops lan9303_mdio_phy_ops = {
.phy_read = lan9303_mdio_phy_read,
.phy_write = lan9303_mdio_phy_write,
};
static const struct regmap_config lan9303_mdio_regmap_config = { static const struct regmap_config lan9303_mdio_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 32, .val_bits = 32,
...@@ -108,6 +127,8 @@ static int lan9303_mdio_probe(struct mdio_device *mdiodev) ...@@ -108,6 +127,8 @@ static int lan9303_mdio_probe(struct mdio_device *mdiodev)
dev_set_drvdata(&mdiodev->dev, sw_dev); dev_set_drvdata(&mdiodev->dev, sw_dev);
sw_dev->chip.dev = &mdiodev->dev; sw_dev->chip.dev = &mdiodev->dev;
sw_dev->chip.ops = &lan9303_mdio_phy_ops;
ret = lan9303_probe(&sw_dev->chip, mdiodev->dev.of_node); ret = lan9303_probe(&sw_dev->chip, mdiodev->dev.of_node);
if (ret != 0) if (ret != 0)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment