|
@@ -20,6 +20,9 @@
|
|
|
|
|
|
#include "lan9303.h"
|
|
|
|
|
|
+/* 13.2 System Control and Status Registers
|
|
|
+ * Multiply register number by 4 to get address offset.
|
|
|
+ */
|
|
|
#define LAN9303_CHIP_REV 0x14
|
|
|
# define LAN9303_CHIP_ID 0x9303
|
|
|
#define LAN9303_IRQ_CFG 0x15
|
|
@@ -53,6 +56,9 @@
|
|
|
#define LAN9303_VIRT_PHY_BASE 0x70
|
|
|
#define LAN9303_VIRT_SPECIAL_CTRL 0x77
|
|
|
|
|
|
+/*13.4 Switch Fabric Control and Status Registers
|
|
|
+ * Accessed indirectly via SWITCH_CSR_CMD, SWITCH_CSR_DATA.
|
|
|
+ */
|
|
|
#define LAN9303_SW_DEV_ID 0x0000
|
|
|
#define LAN9303_SW_RESET 0x0001
|
|
|
#define LAN9303_SW_RESET_RESET BIT(0)
|
|
@@ -242,7 +248,7 @@ static int lan9303_virt_phy_reg_write(struct lan9303 *chip, int regnum, u16 val)
|
|
|
return regmap_write(chip->regmap, LAN9303_VIRT_PHY_BASE + regnum, val);
|
|
|
}
|
|
|
|
|
|
-static int lan9303_port_phy_reg_wait_for_completion(struct lan9303 *chip)
|
|
|
+static int lan9303_indirect_phy_wait_for_completion(struct lan9303 *chip)
|
|
|
{
|
|
|
int ret, i;
|
|
|
u32 reg;
|
|
@@ -262,7 +268,7 @@ static int lan9303_port_phy_reg_wait_for_completion(struct lan9303 *chip)
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
-static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
|
|
|
+static int lan9303_indirect_phy_read(struct lan9303 *chip, int addr, int regnum)
|
|
|
{
|
|
|
int ret;
|
|
|
u32 val;
|
|
@@ -272,7 +278,7 @@ static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
|
|
|
|
|
|
mutex_lock(&chip->indirect_mutex);
|
|
|
|
|
|
- ret = lan9303_port_phy_reg_wait_for_completion(chip);
|
|
|
+ ret = lan9303_indirect_phy_wait_for_completion(chip);
|
|
|
if (ret)
|
|
|
goto on_error;
|
|
|
|
|
@@ -281,7 +287,7 @@ static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
|
|
|
if (ret)
|
|
|
goto on_error;
|
|
|
|
|
|
- ret = lan9303_port_phy_reg_wait_for_completion(chip);
|
|
|
+ ret = lan9303_indirect_phy_wait_for_completion(chip);
|
|
|
if (ret)
|
|
|
goto on_error;
|
|
|
|
|
@@ -299,8 +305,8 @@ on_error:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int lan9303_phy_reg_write(struct lan9303 *chip, int addr, int regnum,
|
|
|
- unsigned int val)
|
|
|
+static int lan9303_indirect_phy_write(struct lan9303 *chip, int addr,
|
|
|
+ int regnum, u16 val)
|
|
|
{
|
|
|
int ret;
|
|
|
u32 reg;
|
|
@@ -311,7 +317,7 @@ static int lan9303_phy_reg_write(struct lan9303 *chip, int addr, int regnum,
|
|
|
|
|
|
mutex_lock(&chip->indirect_mutex);
|
|
|
|
|
|
- ret = lan9303_port_phy_reg_wait_for_completion(chip);
|
|
|
+ ret = lan9303_indirect_phy_wait_for_completion(chip);
|
|
|
if (ret)
|
|
|
goto on_error;
|
|
|
|
|
@@ -328,6 +334,12 @@ on_error:
|
|
|
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)
|
|
|
{
|
|
|
int ret, i;
|
|
@@ -427,14 +439,15 @@ static int lan9303_detect_phy_setup(struct lan9303 *chip)
|
|
|
* Special reg 18 of phy 3 reads as 0x0000, if 'phy_addr_sel_strap' is 0
|
|
|
* and the IDs are 0-1-2, else it contains something different from
|
|
|
* 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.
|
|
|
*/
|
|
|
- reg = lan9303_port_phy_reg_read(chip, 3, MII_LAN911X_SPECIAL_MODES);
|
|
|
+ reg = chip->ops->phy_read(chip, 3, MII_LAN911X_SPECIAL_MODES);
|
|
|
if (reg < 0) {
|
|
|
dev_err(chip->dev, "Failed to detect phy config: %d\n", reg);
|
|
|
return reg;
|
|
|
}
|
|
|
|
|
|
- if (reg != 0)
|
|
|
+ if ((reg != 0) && (reg != 0xffff))
|
|
|
chip->phy_addr_sel_strap = 1;
|
|
|
else
|
|
|
chip->phy_addr_sel_strap = 0;
|
|
@@ -719,7 +732,7 @@ static int lan9303_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
|
|
if (phy > phy_base + 2)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- return lan9303_port_phy_reg_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,
|
|
@@ -733,7 +746,7 @@ static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
|
|
|
if (phy > phy_base + 2)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- return lan9303_phy_reg_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,
|
|
@@ -766,13 +779,13 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port,
|
|
|
switch (port) {
|
|
|
case 1:
|
|
|
lan9303_disable_packet_processing(chip, LAN9303_PORT_1_OFFSET);
|
|
|
- lan9303_phy_reg_write(chip, chip->phy_addr_sel_strap + 1,
|
|
|
- MII_BMCR, BMCR_PDOWN);
|
|
|
+ lan9303_phy_write(ds, chip->phy_addr_sel_strap + 1,
|
|
|
+ MII_BMCR, BMCR_PDOWN);
|
|
|
break;
|
|
|
case 2:
|
|
|
lan9303_disable_packet_processing(chip, LAN9303_PORT_2_OFFSET);
|
|
|
- lan9303_phy_reg_write(chip, chip->phy_addr_sel_strap + 2,
|
|
|
- MII_BMCR, BMCR_PDOWN);
|
|
|
+ lan9303_phy_write(ds, chip->phy_addr_sel_strap + 2,
|
|
|
+ MII_BMCR, BMCR_PDOWN);
|
|
|
break;
|
|
|
default:
|
|
|
dev_dbg(chip->dev,
|