diff --git a/drivers/ethernet/Kconfig.dsa b/drivers/ethernet/Kconfig.dsa index faa2112b7ce..56d0109b0eb 100644 --- a/drivers/ethernet/Kconfig.dsa +++ b/drivers/ethernet/Kconfig.dsa @@ -39,23 +39,38 @@ config DSA_KSZ8863 help Add support for KSZ8863 DSA device driver. +config DSA_KSZ8463 + bool "Support for KSZ8463" + default y + depends on DT_HAS_MICROCHIP_KSZ8463_ENABLED + select DSA_KSZ8XXX + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_MICROCHIP_KSZ8463),spi) + help + Add support for KSZ8463 DSA device driver. + config DSA_KSZ_TAIL_TAGGING bool "Support for tail tagging" - depends on DSA_KSZ8794 || DSA_KSZ8863 + depends on DSA_KSZ8794 || DSA_KSZ8863 || DSA_KSZ8463 help Add support for tail tagging on DSA device. config DSA_TAG_SIZE int "DSA tag size in bytes" - default 1 if DSA_KSZ8794 || DSA_KSZ8863 + default 1 if DSA_KSZ8794 || DSA_KSZ8863 || DSA_KSZ8463 default 0 depends on DSA_KSZ_TAIL_TAGGING help Set the DSA tag length in bytes. +config DSA_KSZ_PORT_ISOLATING + bool "Support for ports isolating" + depends on DSA_KSZ8794 || DSA_KSZ8863 || DSA_KSZ8463 + help + Add support for traffic isolation on DSA slave ports + config DSA_SPI bool "Support for PHY SPI interface" - depends on SPI && (DSA_KSZ8794 || DSA_KSZ8863) + depends on SPI && (DSA_KSZ8794 || DSA_KSZ8863 || DSA_KSZ8463) help Use SPI bus to communicate with PHY diff --git a/drivers/ethernet/dsa_ksz8463.h b/drivers/ethernet/dsa_ksz8463.h new file mode 100644 index 00000000000..b57096cbac3 --- /dev/null +++ b/drivers/ethernet/dsa_ksz8463.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 Meshium + * Aleksandr Senin + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DSA_KSZ8463_H__ +#define __DSA_KSZ8463_H__ + +/* SPI commands */ +#define KSZ8463_SPI_CMD_WR (BIT(7)) +#define KSZ8463_SPI_CMD_RD (0) + +#define KSZ8463_REG_ADDR_HI_PART(x) (((x) & 0x7FF) >> 4) +#define KSZ8463_REG_ADDR_LO_PART(x) (((x) & 0x00C) << 4) +#define KSZ8463_SPI_BYTE_ENABLE(x) (BIT(((x) & 0x3) + 2)) + +/* PHY registers */ +#define KSZ8463_BMCR 0x00 +#define KSZ8463_BMSR 0x01 +#define KSZ8463_PHYID1 0x02 +#define KSZ8463_PHYID2 0x03 +#define KSZ8463_ANAR 0x04 +#define KSZ8463_ANLPAR 0x05 +#define KSZ8463_LINKMD 0x1D +#define KSZ8463_PHYSCS 0x1F + +/* SWITCH registers */ +#define KSZ8463_CHIP_ID0 0x01 +#define KSZ8463_CHIP_ID1 0x00 +#define KSZ8463_GLOBAL_CTRL_1L 0x02 +#define KSZ8463_GLOBAL_CTRL_1H 0x03 +#define KSZ8463_GLOBAL_CTRL_2L 0x04 +#define KSZ8463_GLOBAL_CTRL_2H 0x05 +#define KSZ8463_GLOBAL_CTRL_3L 0x06 +#define KSZ8463_GLOBAL_CTRL_3H 0x07 +#define KSZ8463_GLOBAL_CTRL_6L 0x0C +#define KSZ8463_GLOBAL_CTRL_6H 0x0D +#define KSZ8463_GLOBAL_CTRL_7L 0x0E +#define KSZ8463_GLOBAL_CTRL_7H 0x0F +#define KSZ8463_GLOBAL_CTRL_8L 0xAC +#define KSZ8463_GLOBAL_CTRL_8H 0xAD +#define KSZ8463_GLOBAL_CTRL_9L 0xAE +#define KSZ8463_GLOBAL_CTRL_9H 0xAF + +#define KSZ8463_CFGR_L 0xD8 + +#define KSZ8463_DSP_CNTRL_6L 0x734 +#define KSZ8463_DSP_CNTRL_6H 0x735 + +#define KSZ8463_GLOBAL_CTRL1_TAIL_TAG_EN BIT(0) +#define KSZ8463_GLOBAL_CTRL2_LEG_MAX_PKT_SIZ_CHK_ENA BIT(1) + +#define KSZ8463_CTRL2L_PORTn(n) (0x6E + ((n) * 0x18)) +#define KSZ8463_CTRL2L_VLAN_PORTS_MASK 0xF8 +#define KSZ8463_CTRL2H_PORTn(n) (0x6F + ((n) * 0x18)) +#define KSZ8463_CTRL2_TRANSMIT_EN BIT(2) +#define KSZ8463_CTRL2_RECEIVE_EN BIT(1) +#define KSZ8463_CTRL2_LEARNING_DIS BIT(0) + +#define KSZ8463_STAT2_PORTn(n) (0x80 + ((n) * 0x18)) +#define KSZ8463_STAT2_LINK_GOOD BIT(5) + +#define KSZ8463_CHIP_ID0_ID_DEFAULT 0x84 +#define KSZ8463_CHIP_ID1_ID_DEFAULT 0x43 +#define KSZ8463F_CHIP_ID1_ID_DEFAULT 0x53 +#define KSZ8463_RESET_REG 0x127 +#define KSZ8463_SOFTWARE_RESET_SET BIT(0) +#define KSZ8463_SOFTWARE_RESET_CLEAR 0 + +#define KSZ8463_P2_COPPER_MODE BIT(7) +#define KSZ8463_P1_COPPER_MODE BIT(6) +#define KSZ8463_RECV_ADJ BIT(5) + +enum { + /* LAN ports for the ksz8463 switch */ + KSZ8463_PORT1 = 0, + KSZ8463_PORT2, + /* SWITCH <-> CPU port */ + KSZ8463_PORT3, +}; + +#define KSZ8463_REG_IND_CTRL_0 0x31 +#define KSZ8463_REG_IND_CTRL_1 0x30 +#define KSZ8463_REG_IND_DATA_8 0x26 +#define KSZ8463_REG_IND_DATA_7 0x2B +#define KSZ8463_REG_IND_DATA_6 0x2A +#define KSZ8463_REG_IND_DATA_5 0x29 +#define KSZ8463_REG_IND_DATA_4 0x28 +#define KSZ8463_REG_IND_DATA_3 0x2F +#define KSZ8463_REG_IND_DATA_2 0x2E +#define KSZ8463_REG_IND_DATA_1 0x2D +#define KSZ8463_REG_IND_DATA_0 0x2C + +#define KSZ8463_STATIC_MAC_TABLE_VALID BIT(3) +#define KSZ8463_STATIC_MAC_TABLE_OVRD BIT(4) +#define KSZ8463_STATIC_MAC_TABLE_USE_FID BIT(5) + +#define KSZ8XXX_CHIP_ID0 KSZ8463_CHIP_ID0 +#define KSZ8XXX_CHIP_ID1 KSZ8463_CHIP_ID1 +#define KSZ8XXX_CHIP_ID0_ID_DEFAULT KSZ8463_CHIP_ID0_ID_DEFAULT +#define KSZ8XXX_CHIP_ID1_ID_DEFAULT KSZ8463F_CHIP_ID1_ID_DEFAULT +#define KSZ8XXX_FIRST_PORT KSZ8463_PORT1 +#define KSZ8XXX_LAST_PORT KSZ8463_PORT3 +#define KSZ8XXX_CPU_PORT KSZ8463_PORT3 +#define KSZ8XXX_REG_IND_CTRL_0 KSZ8463_REG_IND_CTRL_0 +#define KSZ8XXX_REG_IND_CTRL_1 KSZ8463_REG_IND_CTRL_1 +#define KSZ8XXX_REG_IND_DATA_8 KSZ8463_REG_IND_DATA_8 +#define KSZ8XXX_REG_IND_DATA_7 KSZ8463_REG_IND_DATA_7 +#define KSZ8XXX_REG_IND_DATA_6 KSZ8463_REG_IND_DATA_6 +#define KSZ8XXX_REG_IND_DATA_5 KSZ8463_REG_IND_DATA_5 +#define KSZ8XXX_REG_IND_DATA_4 KSZ8463_REG_IND_DATA_4 +#define KSZ8XXX_REG_IND_DATA_3 KSZ8463_REG_IND_DATA_3 +#define KSZ8XXX_REG_IND_DATA_2 KSZ8463_REG_IND_DATA_2 +#define KSZ8XXX_REG_IND_DATA_1 KSZ8463_REG_IND_DATA_1 +#define KSZ8XXX_REG_IND_DATA_0 KSZ8463_REG_IND_DATA_0 +#define KSZ8XXX_STATIC_MAC_TABLE_VALID KSZ8463_STATIC_MAC_TABLE_VALID +#define KSZ8XXX_STATIC_MAC_TABLE_OVRD KSZ8463_STATIC_MAC_TABLE_OVRD +#define KSZ8XXX_STAT2_LINK_GOOD KSZ8463_STAT2_LINK_GOOD +#define KSZ8XXX_RESET_REG KSZ8463_RESET_REG +#define KSZ8XXX_RESET_SET KSZ8463_SOFTWARE_RESET_SET +#define KSZ8XXX_RESET_CLEAR KSZ8463_SOFTWARE_RESET_CLEAR +#define KSZ8XXX_STAT2_PORTn KSZ8463_STAT2_PORTn +#define KSZ8XXX_CTRL1_PORTn KSZ8463_CTRL2L_PORTn +#define KSZ8XXX_CTRL1_VLAN_PORTS_MASK KSZ8463_CTRL2L_VLAN_PORTS_MASK +#define KSZ8XXX_SPI_CMD_RD KSZ8463_SPI_CMD_RD +#define KSZ8XXX_SPI_CMD_WR KSZ8463_SPI_CMD_WR +#define KSZ8XXX_SOFT_RESET_DURATION 1000 +#define KSZ8XXX_HARD_RESET_WAIT 10000 + +#endif /* __DSA_KSZ8463_H__ */ diff --git a/drivers/ethernet/dsa_ksz8794.h b/drivers/ethernet/dsa_ksz8794.h index 93ed81e5bac..d4a1c2f578b 100644 --- a/drivers/ethernet/dsa_ksz8794.h +++ b/drivers/ethernet/dsa_ksz8794.h @@ -234,6 +234,8 @@ #define KSZ8794_GLOBAL_CTRL10_TAIL_TAG_EN BIT(1) #define KSZ8794_GLOBAL_CTRL2_LEG_MAX_PKT_SIZ_CHK_DIS BIT(1) +#define KSZ8794_CTRL1_PORTn(n) (0x11 + ((n) * 0x10)) +#define KSZ8794_CTRL1_VLAN_PORTS_MASK 0xE0 #define KSZ8794_CTRL2_PORTn(n) (0x12 + ((n) * 0x10)) #define KSZ8794_CTRL2_TRANSMIT_EN BIT(2) #define KSZ8794_CTRL2_RECEIVE_EN BIT(1) @@ -321,6 +323,8 @@ enum { #define KSZ8XXX_RESET_SET KSZ8794_PWR_MGNT_MODE_SOFT_DOWN #define KSZ8XXX_RESET_CLEAR 0 #define KSZ8XXX_STAT2_PORTn KSZ8794_STAT2_PORTn +#define KSZ8XXX_CTRL1_PORTn KSZ8794_CTRL1_PORTn +#define KSZ8XXX_CTRL1_VLAN_PORTS_MASK KSZ8794_CTRL1_VLAN_PORTS_MASK #define KSZ8XXX_SPI_CMD_RD KSZ8794_SPI_CMD_RD #define KSZ8XXX_SPI_CMD_WR KSZ8794_SPI_CMD_WR #define KSZ8XXX_SOFT_RESET_DURATION 1000 diff --git a/drivers/ethernet/dsa_ksz8863.h b/drivers/ethernet/dsa_ksz8863.h index 602662ee1eb..d523da92615 100644 --- a/drivers/ethernet/dsa_ksz8863.h +++ b/drivers/ethernet/dsa_ksz8863.h @@ -94,6 +94,8 @@ #define KSZ8863_GLOBAL_CTRL1_TAIL_TAG_EN BIT(6) #define KSZ8863_GLOBAL_CTRL2_LEG_MAX_PKT_SIZ_CHK_ENA BIT(1) +#define KSZ8863_CTRL1_PORTn(n) (0x11 + ((n) * 0x10)) +#define KSZ8863_CTRL1_VLAN_PORTS_MASK 0xF8 #define KSZ8863_CTRL2_PORTn(n) (0x12 + ((n) * 0x10)) #define KSZ8863_CTRL2_TRANSMIT_EN BIT(2) #define KSZ8863_CTRL2_RECEIVE_EN BIT(1) @@ -157,6 +159,8 @@ enum { #define KSZ8XXX_RESET_SET KSZ8863_SOFTWARE_RESET_SET #define KSZ8XXX_RESET_CLEAR KSZ8863_SOFTWARE_RESET_CLEAR #define KSZ8XXX_STAT2_PORTn KSZ8863_STAT2_PORTn +#define KSZ8XXX_CTRL1_PORTn KSZ8863_CTRL1_PORTn +#define KSZ8XXX_CTRL1_VLAN_PORTS_MASK KSZ8863_CTRL1_VLAN_PORTS_MASK #define KSZ8XXX_SPI_CMD_RD KSZ8863_SPI_CMD_RD #define KSZ8XXX_SPI_CMD_WR KSZ8863_SPI_CMD_WR #define KSZ8XXX_SOFT_RESET_DURATION 1000 diff --git a/drivers/ethernet/dsa_ksz8xxx.c b/drivers/ethernet/dsa_ksz8xxx.c index 9cf136f7b01..3a81546a91f 100644 --- a/drivers/ethernet/dsa_ksz8xxx.c +++ b/drivers/ethernet/dsa_ksz8xxx.c @@ -30,6 +30,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_ETHERNET_LOG_LEVEL); #elif CONFIG_DSA_KSZ8794 #define DT_DRV_COMPAT microchip_ksz8794 #include "dsa_ksz8794.h" +#elif CONFIG_DSA_KSZ8463 +#define DT_DRV_COMPAT microchip_ksz8463 +#include "dsa_ksz8463.h" #else #error "Unsupported KSZ chipset" #endif @@ -59,9 +62,15 @@ static void dsa_ksz8xxx_write_reg(const struct ksz8xxx_data *pdev, .count = 1 }; +#if CONFIG_DSA_KSZ8463 + buf[0] = KSZ8XXX_SPI_CMD_WR | KSZ8463_REG_ADDR_HI_PART(reg_addr); + buf[1] = KSZ8463_REG_ADDR_LO_PART(reg_addr) | KSZ8463_SPI_BYTE_ENABLE(reg_addr); + buf[2] = value; +#else buf[0] = KSZ8XXX_SPI_CMD_WR | ((reg_addr >> 7) & 0x1F); buf[1] = (reg_addr << 1) & 0xFE; buf[2] = value; +#endif spi_write_dt(&pdev->spi, &tx); #endif @@ -91,9 +100,15 @@ static void dsa_ksz8xxx_read_reg(const struct ksz8xxx_data *pdev, .count = 1 }; +#if CONFIG_DSA_KSZ8463 + buf[0] = KSZ8XXX_SPI_CMD_RD | KSZ8463_REG_ADDR_HI_PART(reg_addr); + buf[1] = KSZ8463_REG_ADDR_LO_PART(reg_addr) | KSZ8463_SPI_BYTE_ENABLE(reg_addr); + buf[2] = 0; +#else buf[0] = KSZ8XXX_SPI_CMD_RD | ((reg_addr >> 7) & 0x1F); buf[1] = (reg_addr << 1) & 0xFE; buf[2] = 0x0; +#endif if (!spi_transceive_dt(&pdev->spi, &tx, &rx)) { *value = buf[2]; @@ -153,7 +168,12 @@ static int dsa_ksz8xxx_probe(struct ksz8xxx_data *pdev) dsa_ksz8xxx_read_reg(pdev, KSZ8XXX_CHIP_ID1, &val[1]); if (val[0] != KSZ8XXX_CHIP_ID0_ID_DEFAULT || +#if CONFIG_DSA_KSZ8463 + (val[1] != KSZ8463_CHIP_ID1_ID_DEFAULT && + val[1] != KSZ8463F_CHIP_ID1_ID_DEFAULT)) { +#else val[1] != KSZ8XXX_CHIP_ID1_ID_DEFAULT) { +#endif LOG_ERR("Chip ID mismatch. " "Expected %02x%02x but found %02x%02x", KSZ8XXX_CHIP_ID0_ID_DEFAULT, @@ -163,7 +183,7 @@ static int dsa_ksz8xxx_probe(struct ksz8xxx_data *pdev) return -ENODEV; } - LOG_DBG("KSZ8794: ID0: 0x%x ID1: 0x%x timeout: %d", val[1], val[0], + LOG_DBG("KSZ8794: ID0: 0x%x ID1: 0x%x timeout: %d", val[0], val[1], timeout); return 0; @@ -260,6 +280,79 @@ static int dsa_ksz8xxx_read_static_mac_table(struct ksz8xxx_data *pdev, return 0; } +#if defined(CONFIG_DSA_KSZ_PORT_ISOLATING) +static int dsa_ksz8xxx_port_isolate(const struct ksz8xxx_data *pdev) +{ + uint8_t tmp, i; + + for (i = KSZ8XXX_FIRST_PORT; i < KSZ8XXX_LAST_PORT; i++) { + dsa_ksz8xxx_read_reg(pdev, KSZ8XXX_CTRL1_PORTn(i), &tmp); + tmp &= KSZ8XXX_CTRL1_VLAN_PORTS_MASK; + tmp |= 1 << KSZ8XXX_CPU_PORT | 1 << i; + dsa_ksz8xxx_write_reg(pdev, KSZ8XXX_CTRL1_PORTn(i), tmp); + } + + dsa_ksz8xxx_read_reg(pdev, KSZ8XXX_CTRL1_PORTn(KSZ8XXX_CPU_PORT), + &tmp); + tmp |= ~KSZ8XXX_CTRL1_VLAN_PORTS_MASK; + dsa_ksz8xxx_write_reg(pdev, KSZ8XXX_CTRL1_PORTn(KSZ8XXX_CPU_PORT), + tmp); + + return 0; +} +#endif + +#if CONFIG_DSA_KSZ8463 +static int dsa_ksz8xxx_switch_setup(struct ksz8xxx_data *pdev) +{ + uint8_t tmp, i; + + dsa_ksz8xxx_read_reg(pdev, KSZ8XXX_CHIP_ID1, &tmp); + + if (tmp == KSZ8463F_CHIP_ID1_ID_DEFAULT) { + dsa_ksz8xxx_read_reg(pdev, KSZ8463_CFGR_L, &tmp); + tmp &= ~KSZ8463_P1_COPPER_MODE; + tmp &= ~KSZ8463_P2_COPPER_MODE; + dsa_ksz8xxx_write_reg(pdev, KSZ8463_CFGR_L, tmp); + dsa_ksz8xxx_read_reg(pdev, KSZ8463_DSP_CNTRL_6H, &tmp); + tmp &= ~KSZ8463_RECV_ADJ; + dsa_ksz8xxx_write_reg(pdev, KSZ8463_DSP_CNTRL_6H, tmp); + } + + /* + * Loop through ports - The same setup when tail tagging is enabled or + * disabled. + */ + for (i = KSZ8XXX_FIRST_PORT; i <= KSZ8XXX_LAST_PORT; i++) { + + /* Enable transmission, reception and switch address learning */ + dsa_ksz8xxx_read_reg(pdev, KSZ8463_CTRL2H_PORTn(i), &tmp); + tmp |= KSZ8463_CTRL2_TRANSMIT_EN; + tmp |= KSZ8463_CTRL2_RECEIVE_EN; + tmp &= ~KSZ8463_CTRL2_LEARNING_DIS; + dsa_ksz8xxx_write_reg(pdev, KSZ8463_CTRL2H_PORTn(i), tmp); + } + +#if defined(CONFIG_DSA_KSZ_TAIL_TAGGING) + /* Enable tail tag feature */ + dsa_ksz8xxx_read_reg(pdev, KSZ8463_GLOBAL_CTRL_8H, &tmp); + tmp |= KSZ8463_GLOBAL_CTRL1_TAIL_TAG_EN; + dsa_ksz8xxx_write_reg(pdev, KSZ8463_GLOBAL_CTRL_8H, tmp); +#else + /* Disable tail tag feature */ + dsa_ksz8xxx_read_reg(pdev, KSZ8463_GLOBAL_CTRL_8H, &tmp); + tmp &= ~KSZ8463_GLOBAL_CTRL1_TAIL_TAG_EN; + dsa_ksz8xxx_write_reg(pdev, KSZ8463_GLOBAL_CTRL_8H, tmp); +#endif + + dsa_ksz8xxx_read_reg(pdev, KSZ8463_GLOBAL_CTRL_2L, &tmp); + tmp &= ~KSZ8463_GLOBAL_CTRL2_LEG_MAX_PKT_SIZ_CHK_ENA; + dsa_ksz8xxx_write_reg(pdev, KSZ8463_GLOBAL_CTRL_2L, tmp); + + return 0; +} +#endif + #if CONFIG_DSA_KSZ8863 static int dsa_ksz8xxx_switch_setup(const struct ksz8xxx_data *pdev) { @@ -697,6 +790,10 @@ int dsa_hw_init(struct ksz8xxx_data *pdev) /* Setup KSZ8794 */ dsa_ksz8xxx_switch_setup(pdev); +#if defined(CONFIG_DSA_KSZ_PORT_ISOLATING) + dsa_ksz8xxx_port_isolate(pdev); +#endif + #if DT_INST_NODE_HAS_PROP(0, mii_lowspeed_drivestrength) dsa_ksz8794_set_lowspeed_drivestrength(pdev); #endif @@ -885,7 +982,7 @@ struct net_pkt *dsa_ksz8xxx_xmit_pkt(struct net_if *iface, struct net_pkt *pkt) port_idx = (1 << (ctx->dsa_port_idx)); } - NET_DBG("TT - port: 0x%x[%p] LEN: %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + LOG_DBG("TT - port: 0x%x[%p] LEN: %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", port_idx, iface, len, lladst.addr[0], lladst.addr[1], lladst.addr[2], lladst.addr[3], lladst.addr[4], lladst.addr[5]); @@ -948,7 +1045,7 @@ static struct net_if *dsa_ksz8xxx_get_iface(struct net_if *iface, iface_sw = net_if_get_by_index(pnum + 2); ctx = net_if_l2_data(iface); - NET_DBG("TT - plen: %d pnum: %d pos: 0x%p dsa_port_idx: %d", + LOG_DBG("TT - plen: %d pnum: %d pos: 0x%p dsa_port_idx: %d", plen - DSA_KSZ8794_EGRESS_TAG_LEN, pnum, net_pkt_cursor_get_pos(pkt), ctx->dsa_port_idx); @@ -1112,5 +1209,4 @@ static struct dsa_api dsa_api_f = { }; \ DT_INST_FOREACH_CHILD_VARGS(n, NET_SLAVE_DEVICE_INIT_INSTANCE, n); - DT_INST_FOREACH_STATUS_OKAY(DSA_DEVICE); diff --git a/dts/bindings/dsa/microchip,ksz8463.yaml b/dts/bindings/dsa/microchip,ksz8463.yaml new file mode 100644 index 00000000000..06df462ad4c --- /dev/null +++ b/dts/bindings/dsa/microchip,ksz8463.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Aleksandr Senin +# SPDX-License-Identifier: Apache-2.0 + +description: | + KSZ8463 ethernet switch + +compatible: "microchip,ksz8463" + +include: [microchip_dsa.yaml]