From: Christian Marangi <[email protected]> Add support for Ethernet controller present in Airoha AN7583. This follow the same implementation of Airoha AN7581 with the only difference of having a different reset number and a different logic to reach the SCU node.
Generalize the driver for these 2 part to account for these minor difference. The switch init part also required some care as the Switch Internal PHY enable BMCR_PDOWN by default and tweak to GEPHY_CONN_CFG is also needed. Signed-off-by: Christian Marangi <[email protected]> --- drivers/net/airoha_eth.c | 94 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c index e5d39b95cc5..d552b9e9de9 100644 --- a/drivers/net/airoha_eth.c +++ b/drivers/net/airoha_eth.c @@ -24,6 +24,7 @@ #include <linux/ethtool.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/mii.h> #include <linux/time.h> #include <asm/arch/scu-regmap.h> @@ -34,6 +35,11 @@ #define AIROHA_MAX_NUM_RSTS 3 #define AIROHA_MAX_NUM_XSI_RSTS 4 +#define AIROHA_MAX_NUM_SWITCH_PORT 4 +#define AIROHA_MAX_PBUS_TRY 10 +#define AIROHA_PBUS_SLEEP 100 +#define AIROHA_PBUS_C22_MASK 0x800000 + #define AIROHA_MAX_PACKET_SIZE 2048 #define AIROHA_NUM_TX_RING 1 #define AIROHA_NUM_RX_RING 1 @@ -86,6 +92,19 @@ #define SWITCH_PHY_PRE_EN BIT(15) #define SWITCH_PHY_END_ADDR GENMASK(12, 8) #define SWITCH_PHY_ST_ADDR GENMASK(4, 0) +#define SWITCH_GEPHY_CONN_CFG 0x7c14 +#define SWITCH_DPHY_CKIN_SEL BIT(31) +#define SWITCH_PHY_CORE_REG_CLK_SEL BIT(30) +#define SWITCH_ETHER_AFE_PWD GENMASK(28, 24) +#define SWITCH_PBUS_PHY_IAC 0x7c20 +#define SWITCH_PBUS_PHY_START BIT(31) +#define SWITCH_PBUS_PHY_CMD BIT(30) +#define SWITCH_PBUS_PHY_CMD_READ FIELD_PREP(SWITCH_PBUS_PHY_CMD, 0x0) +#define SWITCH_PBUS_PHY_CMD_WRITE FIELD_PREP(SWITCH_PBUS_PHY_CMD, 0x1) +#define SWITCH_PBUS_PHY_PORTADDR GENMASK(28, 24) +#define SWITCH_PBUS_PHY_REGADDR GENMASK(23, 0) +#define SWITCH_PBUS_PHY_IAWD 0x7c24 +#define SWITCH_PBUS_PHY_IARD 0x7c28 /* FE */ #define PSE_BASE 0x0100 @@ -365,6 +384,12 @@ static const char * const en7581_xsi_rsts_names[] = { "xfp-mac", }; +static const char * const an7583_xsi_rsts_names[] = { + "hsi0-mac", + "hsi1-mac", + "xfp-mac", +}; + static u32 airoha_rr(void __iomem *base, u32 offset) { return readl(base + offset); @@ -405,8 +430,12 @@ static u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) #define airoha_qdma_clear(qdma, offset, val) \ airoha_rmw((qdma)->regs, (offset), (val), 0) +#define airoha_switch_rr(eth, offset) \ + airoha_rr((eth)->switch_regs, (offset)) #define airoha_switch_wr(eth, offset, val) \ airoha_wr((eth)->switch_regs, (offset), (val)) +#define airoha_switch_rmw(eth, offset, mask, val) \ + airoha_rmw((eth)->switch_regs, (offset), (mask), (val)) static inline dma_addr_t dma_map_unaligned(void *vaddr, size_t len, enum dma_data_direction dir) @@ -438,6 +467,8 @@ static int airoha_get_fe_port(struct airoha_gdm_port *port) case 0x7523: /* FIXME: GDM1 is the only supported port */ return FE_PSE_PORT_GDM1; + case 0x7583: + return port->id == 3 ? FE_PSE_PORT_GDM3 : port->id; case 0x7581: default: return port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; @@ -809,6 +840,59 @@ static int airoha_switch_init(struct udevice *dev, struct airoha_eth *eth) FIELD_PREP(SWITCH_PHY_END_ADDR, 0xc) | FIELD_PREP(SWITCH_PHY_ST_ADDR, 0x8)); + /* AN7583 require tweak to GEPHY_CONN_CFG and clear PHY BMCR_PDOWN */ + if (!strcmp(data->switch_compatible, "airoha,an7583-switch")) { + int i; + + airoha_switch_rmw(eth, SWITCH_GEPHY_CONN_CFG, + SWITCH_DPHY_CKIN_SEL | + SWITCH_PHY_CORE_REG_CLK_SEL | + SWITCH_ETHER_AFE_PWD, + SWITCH_DPHY_CKIN_SEL | + SWITCH_PHY_CORE_REG_CLK_SEL | + FIELD_PREP(SWITCH_ETHER_AFE_PWD, 0)); + + /* Disable BMCR_PDOWN for every PHY */ + for (i = 0; i < AIROHA_MAX_NUM_SWITCH_PORT; i++) { + int try; + u32 val; + + airoha_switch_wr(eth, SWITCH_PBUS_PHY_IAC, + SWITCH_PBUS_PHY_START | + SWITCH_PBUS_PHY_CMD_READ | + FIELD_PREP(SWITCH_PBUS_PHY_PORTADDR, i) | + FIELD_PREP(SWITCH_PBUS_PHY_REGADDR, + AIROHA_PBUS_C22_MASK | MII_BMCR)); + + for (try = 0; try < AIROHA_MAX_PBUS_TRY; try++) { + val = airoha_switch_rr(eth, SWITCH_PBUS_PHY_IAC); + if (!(val & SWITCH_PBUS_PHY_START)) + break; + + udelay(AIROHA_PBUS_SLEEP); + } + + val = airoha_switch_rr(eth, SWITCH_PBUS_PHY_IARD); + val &= ~BMCR_PDOWN; + + airoha_switch_wr(eth, SWITCH_PBUS_PHY_IAWD, val); + airoha_switch_wr(eth, SWITCH_PBUS_PHY_IAC, + SWITCH_PBUS_PHY_START | + SWITCH_PBUS_PHY_CMD_WRITE | + FIELD_PREP(SWITCH_PBUS_PHY_PORTADDR, i) | + FIELD_PREP(SWITCH_PBUS_PHY_REGADDR, + AIROHA_PBUS_C22_MASK | MII_BMCR)); + + for (try = 0; try < AIROHA_MAX_PBUS_TRY; try++) { + val = airoha_switch_rr(eth, SWITCH_PBUS_PHY_IAC); + if (!(val & SWITCH_PBUS_PHY_START)) + break; + + udelay(AIROHA_PBUS_SLEEP); + } + } + } + return 0; } @@ -1269,6 +1353,13 @@ static const struct airoha_eth_soc_data en7581_data = { .switch_compatible = "airoha,en7581-switch", }; +static const struct airoha_eth_soc_data an7583_data = { + .version = 0x7583, + .xsi_rsts_names = an7583_xsi_rsts_names, + .num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names), + .switch_compatible = "airoha,an7583-switch", +}; + static const struct udevice_id airoha_eth_ids[] = { { .compatible = "airoha,en7523-eth", .data = (ulong)&en7523_data, @@ -1276,6 +1367,9 @@ static const struct udevice_id airoha_eth_ids[] = { { .compatible = "airoha,en7581-eth", .data = (ulong)&en7581_data, }, + { .compatible = "airoha,an7583-eth", + .data = (ulong)&an7583_data, + }, { } }; -- 2.53.0
