160cbe71fSLinus Walleij // SPDX-License-Identifier: GPL-2.0 260cbe71fSLinus Walleij /* 360cbe71fSLinus Walleij * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches 460cbe71fSLinus Walleij * 560cbe71fSLinus Walleij * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org> 6*a7fe8b26SLinus Walleij * Copyright (C) 2025 Linus Walleij <linus.walleij@linaro.org> 760cbe71fSLinus Walleij * 860cbe71fSLinus Walleij * This file was based on: drivers/spi/at25.c 960cbe71fSLinus Walleij * Copyright (C) 2006 David Brownell 1060cbe71fSLinus Walleij */ 1160cbe71fSLinus Walleij 1260cbe71fSLinus Walleij #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1360cbe71fSLinus Walleij 14*a7fe8b26SLinus Walleij #include <linux/bits.h> 15*a7fe8b26SLinus Walleij #include <linux/if_bridge.h> 16*a7fe8b26SLinus Walleij #include <linux/if_vlan.h> 1760cbe71fSLinus Walleij #include <linux/types.h> 1860cbe71fSLinus Walleij #include <linux/kernel.h> 1960cbe71fSLinus Walleij #include <linux/module.h> 2060cbe71fSLinus Walleij #include <linux/delay.h> 2160cbe71fSLinus Walleij #include <linux/device.h> 2260cbe71fSLinus Walleij #include <linux/gpio/consumer.h> 2360cbe71fSLinus Walleij #include <linux/of.h> 2460cbe71fSLinus Walleij #include <linux/spi/spi.h> 25*a7fe8b26SLinus Walleij #include <net/dsa.h> 2660cbe71fSLinus Walleij 2760cbe71fSLinus Walleij #define DRV_VERSION "0.1.1" 2860cbe71fSLinus Walleij #define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" 2960cbe71fSLinus Walleij 3060cbe71fSLinus Walleij /* ------------------------------------------------------------------------ */ 3160cbe71fSLinus Walleij 3260cbe71fSLinus Walleij #define KS8995_REG_ID0 0x00 /* Chip ID0 */ 3360cbe71fSLinus Walleij #define KS8995_REG_ID1 0x01 /* Chip ID1 */ 3460cbe71fSLinus Walleij 3560cbe71fSLinus Walleij #define KS8995_REG_GC0 0x02 /* Global Control 0 */ 36*a7fe8b26SLinus Walleij 37*a7fe8b26SLinus Walleij #define KS8995_GC0_P5_PHY BIT(3) /* Port 5 PHY enabled */ 38*a7fe8b26SLinus Walleij 3960cbe71fSLinus Walleij #define KS8995_REG_GC1 0x03 /* Global Control 1 */ 4060cbe71fSLinus Walleij #define KS8995_REG_GC2 0x04 /* Global Control 2 */ 41*a7fe8b26SLinus Walleij 42*a7fe8b26SLinus Walleij #define KS8995_GC2_HUGE BIT(2) /* Huge packet support */ 43*a7fe8b26SLinus Walleij #define KS8995_GC2_LEGAL BIT(1) /* Legal size override */ 44*a7fe8b26SLinus Walleij 4560cbe71fSLinus Walleij #define KS8995_REG_GC3 0x05 /* Global Control 3 */ 4660cbe71fSLinus Walleij #define KS8995_REG_GC4 0x06 /* Global Control 4 */ 47*a7fe8b26SLinus Walleij 48*a7fe8b26SLinus Walleij #define KS8995_GC4_10BT BIT(4) /* Force switch to 10Mbit */ 49*a7fe8b26SLinus Walleij #define KS8995_GC4_MII_FLOW BIT(5) /* MII full-duplex flow control enable */ 50*a7fe8b26SLinus Walleij #define KS8995_GC4_MII_HD BIT(6) /* MII half-duplex mode enable */ 51*a7fe8b26SLinus Walleij 5260cbe71fSLinus Walleij #define KS8995_REG_GC5 0x07 /* Global Control 5 */ 5360cbe71fSLinus Walleij #define KS8995_REG_GC6 0x08 /* Global Control 6 */ 5460cbe71fSLinus Walleij #define KS8995_REG_GC7 0x09 /* Global Control 7 */ 5560cbe71fSLinus Walleij #define KS8995_REG_GC8 0x0a /* Global Control 8 */ 5660cbe71fSLinus Walleij #define KS8995_REG_GC9 0x0b /* Global Control 9 */ 5760cbe71fSLinus Walleij 58*a7fe8b26SLinus Walleij #define KS8995_GC9_SPECIAL BIT(0) /* Special tagging mode (DSA) */ 59*a7fe8b26SLinus Walleij 60*a7fe8b26SLinus Walleij /* In DSA the ports 1-4 are numbered 0-3 and the CPU port is port 4 */ 61*a7fe8b26SLinus Walleij #define KS8995_REG_PC(p, r) (0x10 + (0x10 * (p)) + (r)) /* Port Control */ 62*a7fe8b26SLinus Walleij #define KS8995_REG_PS(p, r) (0x1e + (0x10 * (p)) + (r)) /* Port Status */ 63*a7fe8b26SLinus Walleij 64*a7fe8b26SLinus Walleij #define KS8995_REG_PC0 0x00 /* Port Control 0 */ 65*a7fe8b26SLinus Walleij #define KS8995_REG_PC1 0x01 /* Port Control 1 */ 66*a7fe8b26SLinus Walleij #define KS8995_REG_PC2 0x02 /* Port Control 2 */ 67*a7fe8b26SLinus Walleij #define KS8995_REG_PC3 0x03 /* Port Control 3 */ 68*a7fe8b26SLinus Walleij #define KS8995_REG_PC4 0x04 /* Port Control 4 */ 69*a7fe8b26SLinus Walleij #define KS8995_REG_PC5 0x05 /* Port Control 5 */ 70*a7fe8b26SLinus Walleij #define KS8995_REG_PC6 0x06 /* Port Control 6 */ 71*a7fe8b26SLinus Walleij #define KS8995_REG_PC7 0x07 /* Port Control 7 */ 72*a7fe8b26SLinus Walleij #define KS8995_REG_PC8 0x08 /* Port Control 8 */ 73*a7fe8b26SLinus Walleij #define KS8995_REG_PC9 0x09 /* Port Control 9 */ 74*a7fe8b26SLinus Walleij #define KS8995_REG_PC10 0x0a /* Port Control 10 */ 75*a7fe8b26SLinus Walleij #define KS8995_REG_PC11 0x0b /* Port Control 11 */ 76*a7fe8b26SLinus Walleij #define KS8995_REG_PC12 0x0c /* Port Control 12 */ 77*a7fe8b26SLinus Walleij #define KS8995_REG_PC13 0x0d /* Port Control 13 */ 78*a7fe8b26SLinus Walleij 79*a7fe8b26SLinus Walleij #define KS8995_PC0_TAG_INS BIT(2) /* Enable tag insertion on port */ 80*a7fe8b26SLinus Walleij #define KS8995_PC0_TAG_REM BIT(1) /* Enable tag removal on port */ 81*a7fe8b26SLinus Walleij #define KS8995_PC0_PRIO_EN BIT(0) /* Enable priority handling */ 82*a7fe8b26SLinus Walleij 83*a7fe8b26SLinus Walleij #define KS8995_PC2_TXEN BIT(2) /* Enable TX on port */ 84*a7fe8b26SLinus Walleij #define KS8995_PC2_RXEN BIT(1) /* Enable RX on port */ 85*a7fe8b26SLinus Walleij #define KS8995_PC2_LEARN_DIS BIT(0) /* Disable learning on port */ 86*a7fe8b26SLinus Walleij 87*a7fe8b26SLinus Walleij #define KS8995_PC13_TXDIS BIT(6) /* Disable transmitter */ 88*a7fe8b26SLinus Walleij #define KS8995_PC13_PWDN BIT(3) /* Power down */ 8960cbe71fSLinus Walleij 9060cbe71fSLinus Walleij #define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ 9160cbe71fSLinus Walleij #define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ 9260cbe71fSLinus Walleij #define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */ 9360cbe71fSLinus Walleij #define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */ 9460cbe71fSLinus Walleij #define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */ 9560cbe71fSLinus Walleij #define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */ 9660cbe71fSLinus Walleij #define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */ 9760cbe71fSLinus Walleij #define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */ 9860cbe71fSLinus Walleij 9960cbe71fSLinus Walleij #define KS8995_REG_MAC0 0x68 /* MAC address 0 */ 10060cbe71fSLinus Walleij #define KS8995_REG_MAC1 0x69 /* MAC address 1 */ 10160cbe71fSLinus Walleij #define KS8995_REG_MAC2 0x6a /* MAC address 2 */ 10260cbe71fSLinus Walleij #define KS8995_REG_MAC3 0x6b /* MAC address 3 */ 10360cbe71fSLinus Walleij #define KS8995_REG_MAC4 0x6c /* MAC address 4 */ 10460cbe71fSLinus Walleij #define KS8995_REG_MAC5 0x6d /* MAC address 5 */ 10560cbe71fSLinus Walleij 10660cbe71fSLinus Walleij #define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */ 10760cbe71fSLinus Walleij #define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */ 10860cbe71fSLinus Walleij #define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */ 10960cbe71fSLinus Walleij #define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */ 11060cbe71fSLinus Walleij #define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */ 11160cbe71fSLinus Walleij #define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */ 11260cbe71fSLinus Walleij #define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */ 11360cbe71fSLinus Walleij #define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */ 11460cbe71fSLinus Walleij #define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ 11560cbe71fSLinus Walleij #define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ 11660cbe71fSLinus Walleij 11760cbe71fSLinus Walleij #define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */ 11860cbe71fSLinus Walleij 11960cbe71fSLinus Walleij #define KS8995_REGS_SIZE 0x80 12060cbe71fSLinus Walleij #define KSZ8864_REGS_SIZE 0x100 12160cbe71fSLinus Walleij #define KSZ8795_REGS_SIZE 0x100 12260cbe71fSLinus Walleij 12360cbe71fSLinus Walleij #define ID1_CHIPID_M 0xf 12460cbe71fSLinus Walleij #define ID1_CHIPID_S 4 12560cbe71fSLinus Walleij #define ID1_REVISION_M 0x7 12660cbe71fSLinus Walleij #define ID1_REVISION_S 1 12760cbe71fSLinus Walleij #define ID1_START_SW 1 /* start the switch */ 12860cbe71fSLinus Walleij 12960cbe71fSLinus Walleij #define FAMILY_KS8995 0x95 13060cbe71fSLinus Walleij #define FAMILY_KSZ8795 0x87 13160cbe71fSLinus Walleij #define CHIPID_M 0 13260cbe71fSLinus Walleij #define KS8995_CHIP_ID 0x00 13360cbe71fSLinus Walleij #define KSZ8864_CHIP_ID 0x01 13460cbe71fSLinus Walleij #define KSZ8795_CHIP_ID 0x09 13560cbe71fSLinus Walleij 13660cbe71fSLinus Walleij #define KS8995_CMD_WRITE 0x02U 13760cbe71fSLinus Walleij #define KS8995_CMD_READ 0x03U 13860cbe71fSLinus Walleij 139*a7fe8b26SLinus Walleij #define KS8995_CPU_PORT 4 140*a7fe8b26SLinus Walleij #define KS8995_NUM_PORTS 5 /* 5 ports including the CPU port */ 14160cbe71fSLinus Walleij #define KS8995_RESET_DELAY 10 /* usec */ 14260cbe71fSLinus Walleij 14360cbe71fSLinus Walleij enum ks8995_chip_variant { 14460cbe71fSLinus Walleij ks8995, 14560cbe71fSLinus Walleij ksz8864, 14660cbe71fSLinus Walleij ksz8795, 14760cbe71fSLinus Walleij max_variant 14860cbe71fSLinus Walleij }; 14960cbe71fSLinus Walleij 15060cbe71fSLinus Walleij struct ks8995_chip_params { 15160cbe71fSLinus Walleij char *name; 15260cbe71fSLinus Walleij int family_id; 15360cbe71fSLinus Walleij int chip_id; 15460cbe71fSLinus Walleij int regs_size; 15560cbe71fSLinus Walleij int addr_width; 15660cbe71fSLinus Walleij int addr_shift; 15760cbe71fSLinus Walleij }; 15860cbe71fSLinus Walleij 15960cbe71fSLinus Walleij static const struct ks8995_chip_params ks8995_chip[] = { 16060cbe71fSLinus Walleij [ks8995] = { 16160cbe71fSLinus Walleij .name = "KS8995MA", 16260cbe71fSLinus Walleij .family_id = FAMILY_KS8995, 16360cbe71fSLinus Walleij .chip_id = KS8995_CHIP_ID, 16460cbe71fSLinus Walleij .regs_size = KS8995_REGS_SIZE, 16560cbe71fSLinus Walleij .addr_width = 8, 16660cbe71fSLinus Walleij .addr_shift = 0, 16760cbe71fSLinus Walleij }, 16860cbe71fSLinus Walleij [ksz8864] = { 16960cbe71fSLinus Walleij .name = "KSZ8864RMN", 17060cbe71fSLinus Walleij .family_id = FAMILY_KS8995, 17160cbe71fSLinus Walleij .chip_id = KSZ8864_CHIP_ID, 17260cbe71fSLinus Walleij .regs_size = KSZ8864_REGS_SIZE, 17360cbe71fSLinus Walleij .addr_width = 8, 17460cbe71fSLinus Walleij .addr_shift = 0, 17560cbe71fSLinus Walleij }, 17660cbe71fSLinus Walleij [ksz8795] = { 17760cbe71fSLinus Walleij .name = "KSZ8795CLX", 17860cbe71fSLinus Walleij .family_id = FAMILY_KSZ8795, 17960cbe71fSLinus Walleij .chip_id = KSZ8795_CHIP_ID, 18060cbe71fSLinus Walleij .regs_size = KSZ8795_REGS_SIZE, 18160cbe71fSLinus Walleij .addr_width = 12, 18260cbe71fSLinus Walleij .addr_shift = 1, 18360cbe71fSLinus Walleij }, 18460cbe71fSLinus Walleij }; 18560cbe71fSLinus Walleij 18660cbe71fSLinus Walleij struct ks8995_switch { 18760cbe71fSLinus Walleij struct spi_device *spi; 188*a7fe8b26SLinus Walleij struct device *dev; 189*a7fe8b26SLinus Walleij struct dsa_switch *ds; 19060cbe71fSLinus Walleij struct mutex lock; 19160cbe71fSLinus Walleij struct gpio_desc *reset_gpio; 19260cbe71fSLinus Walleij struct bin_attribute regs_attr; 19360cbe71fSLinus Walleij const struct ks8995_chip_params *chip; 19460cbe71fSLinus Walleij int revision_id; 195*a7fe8b26SLinus Walleij unsigned int max_mtu[KS8995_NUM_PORTS]; 19660cbe71fSLinus Walleij }; 19760cbe71fSLinus Walleij 19860cbe71fSLinus Walleij static const struct spi_device_id ks8995_id[] = { 19960cbe71fSLinus Walleij {"ks8995", ks8995}, 20060cbe71fSLinus Walleij {"ksz8864", ksz8864}, 20160cbe71fSLinus Walleij {"ksz8795", ksz8795}, 20260cbe71fSLinus Walleij { } 20360cbe71fSLinus Walleij }; 20460cbe71fSLinus Walleij MODULE_DEVICE_TABLE(spi, ks8995_id); 20560cbe71fSLinus Walleij 20660cbe71fSLinus Walleij static const struct of_device_id ks8895_spi_of_match[] = { 20760cbe71fSLinus Walleij { .compatible = "micrel,ks8995" }, 20860cbe71fSLinus Walleij { .compatible = "micrel,ksz8864" }, 20960cbe71fSLinus Walleij { .compatible = "micrel,ksz8795" }, 21060cbe71fSLinus Walleij { }, 21160cbe71fSLinus Walleij }; 21260cbe71fSLinus Walleij MODULE_DEVICE_TABLE(of, ks8895_spi_of_match); 21360cbe71fSLinus Walleij 21460cbe71fSLinus Walleij static inline u8 get_chip_id(u8 val) 21560cbe71fSLinus Walleij { 21660cbe71fSLinus Walleij return (val >> ID1_CHIPID_S) & ID1_CHIPID_M; 21760cbe71fSLinus Walleij } 21860cbe71fSLinus Walleij 21960cbe71fSLinus Walleij static inline u8 get_chip_rev(u8 val) 22060cbe71fSLinus Walleij { 22160cbe71fSLinus Walleij return (val >> ID1_REVISION_S) & ID1_REVISION_M; 22260cbe71fSLinus Walleij } 22360cbe71fSLinus Walleij 22460cbe71fSLinus Walleij /* create_spi_cmd - create a chip specific SPI command header 22560cbe71fSLinus Walleij * @ks: pointer to switch instance 22660cbe71fSLinus Walleij * @cmd: SPI command for switch 22760cbe71fSLinus Walleij * @address: register address for command 22860cbe71fSLinus Walleij * 22960cbe71fSLinus Walleij * Different chip families use different bit pattern to address the switches 23060cbe71fSLinus Walleij * registers: 23160cbe71fSLinus Walleij * 23260cbe71fSLinus Walleij * KS8995: 8bit command + 8bit address 23360cbe71fSLinus Walleij * KSZ8795: 3bit command + 12bit address + 1bit TR (?) 23460cbe71fSLinus Walleij */ 23560cbe71fSLinus Walleij static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd, 23660cbe71fSLinus Walleij unsigned address) 23760cbe71fSLinus Walleij { 23860cbe71fSLinus Walleij u16 result = cmd; 23960cbe71fSLinus Walleij 24060cbe71fSLinus Walleij /* make room for address (incl. address shift) */ 24160cbe71fSLinus Walleij result <<= ks->chip->addr_width + ks->chip->addr_shift; 24260cbe71fSLinus Walleij /* add address */ 24360cbe71fSLinus Walleij result |= address << ks->chip->addr_shift; 24460cbe71fSLinus Walleij /* SPI protocol needs big endian */ 24560cbe71fSLinus Walleij return cpu_to_be16(result); 24660cbe71fSLinus Walleij } 24760cbe71fSLinus Walleij /* ------------------------------------------------------------------------ */ 24860cbe71fSLinus Walleij static int ks8995_read(struct ks8995_switch *ks, char *buf, 24960cbe71fSLinus Walleij unsigned offset, size_t count) 25060cbe71fSLinus Walleij { 25160cbe71fSLinus Walleij __be16 cmd; 25260cbe71fSLinus Walleij struct spi_transfer t[2]; 25360cbe71fSLinus Walleij struct spi_message m; 25460cbe71fSLinus Walleij int err; 25560cbe71fSLinus Walleij 25660cbe71fSLinus Walleij cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset); 25760cbe71fSLinus Walleij spi_message_init(&m); 25860cbe71fSLinus Walleij 25960cbe71fSLinus Walleij memset(&t, 0, sizeof(t)); 26060cbe71fSLinus Walleij 26160cbe71fSLinus Walleij t[0].tx_buf = &cmd; 26260cbe71fSLinus Walleij t[0].len = sizeof(cmd); 26360cbe71fSLinus Walleij spi_message_add_tail(&t[0], &m); 26460cbe71fSLinus Walleij 26560cbe71fSLinus Walleij t[1].rx_buf = buf; 26660cbe71fSLinus Walleij t[1].len = count; 26760cbe71fSLinus Walleij spi_message_add_tail(&t[1], &m); 26860cbe71fSLinus Walleij 26960cbe71fSLinus Walleij mutex_lock(&ks->lock); 27060cbe71fSLinus Walleij err = spi_sync(ks->spi, &m); 27160cbe71fSLinus Walleij mutex_unlock(&ks->lock); 27260cbe71fSLinus Walleij 27360cbe71fSLinus Walleij return err ? err : count; 27460cbe71fSLinus Walleij } 27560cbe71fSLinus Walleij 27660cbe71fSLinus Walleij static int ks8995_write(struct ks8995_switch *ks, char *buf, 27760cbe71fSLinus Walleij unsigned offset, size_t count) 27860cbe71fSLinus Walleij { 27960cbe71fSLinus Walleij __be16 cmd; 28060cbe71fSLinus Walleij struct spi_transfer t[2]; 28160cbe71fSLinus Walleij struct spi_message m; 28260cbe71fSLinus Walleij int err; 28360cbe71fSLinus Walleij 28460cbe71fSLinus Walleij cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset); 28560cbe71fSLinus Walleij spi_message_init(&m); 28660cbe71fSLinus Walleij 28760cbe71fSLinus Walleij memset(&t, 0, sizeof(t)); 28860cbe71fSLinus Walleij 28960cbe71fSLinus Walleij t[0].tx_buf = &cmd; 29060cbe71fSLinus Walleij t[0].len = sizeof(cmd); 29160cbe71fSLinus Walleij spi_message_add_tail(&t[0], &m); 29260cbe71fSLinus Walleij 29360cbe71fSLinus Walleij t[1].tx_buf = buf; 29460cbe71fSLinus Walleij t[1].len = count; 29560cbe71fSLinus Walleij spi_message_add_tail(&t[1], &m); 29660cbe71fSLinus Walleij 29760cbe71fSLinus Walleij mutex_lock(&ks->lock); 29860cbe71fSLinus Walleij err = spi_sync(ks->spi, &m); 29960cbe71fSLinus Walleij mutex_unlock(&ks->lock); 30060cbe71fSLinus Walleij 30160cbe71fSLinus Walleij return err ? err : count; 30260cbe71fSLinus Walleij } 30360cbe71fSLinus Walleij 30460cbe71fSLinus Walleij static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) 30560cbe71fSLinus Walleij { 30660cbe71fSLinus Walleij return ks8995_read(ks, buf, addr, 1) != 1; 30760cbe71fSLinus Walleij } 30860cbe71fSLinus Walleij 30960cbe71fSLinus Walleij static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) 31060cbe71fSLinus Walleij { 31160cbe71fSLinus Walleij char buf = val; 31260cbe71fSLinus Walleij 31360cbe71fSLinus Walleij return ks8995_write(ks, &buf, addr, 1) != 1; 31460cbe71fSLinus Walleij } 31560cbe71fSLinus Walleij 31660cbe71fSLinus Walleij /* ------------------------------------------------------------------------ */ 31760cbe71fSLinus Walleij 31860cbe71fSLinus Walleij static int ks8995_stop(struct ks8995_switch *ks) 31960cbe71fSLinus Walleij { 32060cbe71fSLinus Walleij return ks8995_write_reg(ks, KS8995_REG_ID1, 0); 32160cbe71fSLinus Walleij } 32260cbe71fSLinus Walleij 32360cbe71fSLinus Walleij static int ks8995_start(struct ks8995_switch *ks) 32460cbe71fSLinus Walleij { 32560cbe71fSLinus Walleij return ks8995_write_reg(ks, KS8995_REG_ID1, 1); 32660cbe71fSLinus Walleij } 32760cbe71fSLinus Walleij 32860cbe71fSLinus Walleij static int ks8995_reset(struct ks8995_switch *ks) 32960cbe71fSLinus Walleij { 33060cbe71fSLinus Walleij int err; 33160cbe71fSLinus Walleij 33260cbe71fSLinus Walleij err = ks8995_stop(ks); 33360cbe71fSLinus Walleij if (err) 33460cbe71fSLinus Walleij return err; 33560cbe71fSLinus Walleij 33660cbe71fSLinus Walleij udelay(KS8995_RESET_DELAY); 33760cbe71fSLinus Walleij 33860cbe71fSLinus Walleij return ks8995_start(ks); 33960cbe71fSLinus Walleij } 34060cbe71fSLinus Walleij 34160cbe71fSLinus Walleij /* ks8995_get_revision - get chip revision 34260cbe71fSLinus Walleij * @ks: pointer to switch instance 34360cbe71fSLinus Walleij * 34460cbe71fSLinus Walleij * Verify chip family and id and get chip revision. 34560cbe71fSLinus Walleij */ 34660cbe71fSLinus Walleij static int ks8995_get_revision(struct ks8995_switch *ks) 34760cbe71fSLinus Walleij { 34860cbe71fSLinus Walleij int err; 34960cbe71fSLinus Walleij u8 id0, id1, ksz8864_id; 35060cbe71fSLinus Walleij 35160cbe71fSLinus Walleij /* read family id */ 35260cbe71fSLinus Walleij err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0); 35360cbe71fSLinus Walleij if (err) { 35460cbe71fSLinus Walleij err = -EIO; 35560cbe71fSLinus Walleij goto err_out; 35660cbe71fSLinus Walleij } 35760cbe71fSLinus Walleij 35860cbe71fSLinus Walleij /* verify family id */ 35960cbe71fSLinus Walleij if (id0 != ks->chip->family_id) { 36060cbe71fSLinus Walleij dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n", 36160cbe71fSLinus Walleij ks->chip->family_id, id0); 36260cbe71fSLinus Walleij err = -ENODEV; 36360cbe71fSLinus Walleij goto err_out; 36460cbe71fSLinus Walleij } 36560cbe71fSLinus Walleij 36660cbe71fSLinus Walleij switch (ks->chip->family_id) { 36760cbe71fSLinus Walleij case FAMILY_KS8995: 36860cbe71fSLinus Walleij /* try reading chip id at CHIP ID1 */ 36960cbe71fSLinus Walleij err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); 37060cbe71fSLinus Walleij if (err) { 37160cbe71fSLinus Walleij err = -EIO; 37260cbe71fSLinus Walleij goto err_out; 37360cbe71fSLinus Walleij } 37460cbe71fSLinus Walleij 37560cbe71fSLinus Walleij /* verify chip id */ 37660cbe71fSLinus Walleij if ((get_chip_id(id1) == CHIPID_M) && 37760cbe71fSLinus Walleij (get_chip_id(id1) == ks->chip->chip_id)) { 37860cbe71fSLinus Walleij /* KS8995MA */ 37960cbe71fSLinus Walleij ks->revision_id = get_chip_rev(id1); 38060cbe71fSLinus Walleij } else if (get_chip_id(id1) != CHIPID_M) { 38160cbe71fSLinus Walleij /* KSZ8864RMN */ 38260cbe71fSLinus Walleij err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id); 38360cbe71fSLinus Walleij if (err) { 38460cbe71fSLinus Walleij err = -EIO; 38560cbe71fSLinus Walleij goto err_out; 38660cbe71fSLinus Walleij } 38760cbe71fSLinus Walleij 38860cbe71fSLinus Walleij if ((ksz8864_id & 0x80) && 38960cbe71fSLinus Walleij (ks->chip->chip_id == KSZ8864_CHIP_ID)) { 39060cbe71fSLinus Walleij ks->revision_id = get_chip_rev(id1); 39160cbe71fSLinus Walleij } 39260cbe71fSLinus Walleij 39360cbe71fSLinus Walleij } else { 39460cbe71fSLinus Walleij dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n", 39560cbe71fSLinus Walleij id1); 39660cbe71fSLinus Walleij err = -ENODEV; 39760cbe71fSLinus Walleij } 39860cbe71fSLinus Walleij break; 39960cbe71fSLinus Walleij case FAMILY_KSZ8795: 40060cbe71fSLinus Walleij /* try reading chip id at CHIP ID1 */ 40160cbe71fSLinus Walleij err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); 40260cbe71fSLinus Walleij if (err) { 40360cbe71fSLinus Walleij err = -EIO; 40460cbe71fSLinus Walleij goto err_out; 40560cbe71fSLinus Walleij } 40660cbe71fSLinus Walleij 40760cbe71fSLinus Walleij if (get_chip_id(id1) == ks->chip->chip_id) { 40860cbe71fSLinus Walleij ks->revision_id = get_chip_rev(id1); 40960cbe71fSLinus Walleij } else { 41060cbe71fSLinus Walleij dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n", 41160cbe71fSLinus Walleij id1); 41260cbe71fSLinus Walleij err = -ENODEV; 41360cbe71fSLinus Walleij } 41460cbe71fSLinus Walleij break; 41560cbe71fSLinus Walleij default: 41660cbe71fSLinus Walleij dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); 41760cbe71fSLinus Walleij err = -ENODEV; 41860cbe71fSLinus Walleij break; 41960cbe71fSLinus Walleij } 42060cbe71fSLinus Walleij err_out: 42160cbe71fSLinus Walleij return err; 42260cbe71fSLinus Walleij } 42360cbe71fSLinus Walleij 424*a7fe8b26SLinus Walleij static int ks8995_check_config(struct ks8995_switch *ks) 425*a7fe8b26SLinus Walleij { 426*a7fe8b26SLinus Walleij int ret; 427*a7fe8b26SLinus Walleij u8 val; 428*a7fe8b26SLinus Walleij 429*a7fe8b26SLinus Walleij ret = ks8995_read_reg(ks, KS8995_REG_GC0, &val); 430*a7fe8b26SLinus Walleij if (ret) { 431*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to read KS8995_REG_GC0\n"); 432*a7fe8b26SLinus Walleij return ret; 433*a7fe8b26SLinus Walleij } 434*a7fe8b26SLinus Walleij 435*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "port 5 PHY %senabled\n", 436*a7fe8b26SLinus Walleij (val & KS8995_GC0_P5_PHY) ? "" : "not "); 437*a7fe8b26SLinus Walleij 438*a7fe8b26SLinus Walleij val |= KS8995_GC0_P5_PHY; 439*a7fe8b26SLinus Walleij ret = ks8995_write_reg(ks, KS8995_REG_GC0, val); 440*a7fe8b26SLinus Walleij if (ret) 441*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to set KS8995_REG_GC0\n"); 442*a7fe8b26SLinus Walleij 443*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set KS8995_REG_GC0 to 0x%02x\n", val); 444*a7fe8b26SLinus Walleij 445*a7fe8b26SLinus Walleij return 0; 446*a7fe8b26SLinus Walleij } 447*a7fe8b26SLinus Walleij 448*a7fe8b26SLinus Walleij static void 449*a7fe8b26SLinus Walleij ks8995_mac_config(struct phylink_config *config, unsigned int mode, 450*a7fe8b26SLinus Walleij const struct phylink_link_state *state) 451*a7fe8b26SLinus Walleij { 452*a7fe8b26SLinus Walleij } 453*a7fe8b26SLinus Walleij 454*a7fe8b26SLinus Walleij static void 455*a7fe8b26SLinus Walleij ks8995_mac_link_up(struct phylink_config *config, struct phy_device *phydev, 456*a7fe8b26SLinus Walleij unsigned int mode, phy_interface_t interface, 457*a7fe8b26SLinus Walleij int speed, int duplex, bool tx_pause, bool rx_pause) 458*a7fe8b26SLinus Walleij { 459*a7fe8b26SLinus Walleij struct dsa_port *dp = dsa_phylink_to_port(config); 460*a7fe8b26SLinus Walleij struct ks8995_switch *ks = dp->ds->priv; 461*a7fe8b26SLinus Walleij int port = dp->index; 462*a7fe8b26SLinus Walleij int ret; 463*a7fe8b26SLinus Walleij u8 val; 464*a7fe8b26SLinus Walleij 465*a7fe8b26SLinus Walleij /* Allow forcing the mode on the fixed CPU port, no autonegotiation. 466*a7fe8b26SLinus Walleij * We assume autonegotiation works on the PHY-facing ports. 467*a7fe8b26SLinus Walleij */ 468*a7fe8b26SLinus Walleij if (port != KS8995_CPU_PORT) 469*a7fe8b26SLinus Walleij return; 470*a7fe8b26SLinus Walleij 471*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "MAC link up on CPU port (%d)\n", port); 472*a7fe8b26SLinus Walleij 473*a7fe8b26SLinus Walleij ret = ks8995_read_reg(ks, KS8995_REG_GC4, &val); 474*a7fe8b26SLinus Walleij if (ret) { 475*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to read KS8995_REG_GC4\n"); 476*a7fe8b26SLinus Walleij return; 477*a7fe8b26SLinus Walleij } 478*a7fe8b26SLinus Walleij 479*a7fe8b26SLinus Walleij /* Conjure port config */ 480*a7fe8b26SLinus Walleij switch (speed) { 481*a7fe8b26SLinus Walleij case SPEED_10: 482*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set switch MII to 100Mbit mode\n"); 483*a7fe8b26SLinus Walleij val |= KS8995_GC4_10BT; 484*a7fe8b26SLinus Walleij break; 485*a7fe8b26SLinus Walleij case SPEED_100: 486*a7fe8b26SLinus Walleij default: 487*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set switch MII to 100Mbit mode\n"); 488*a7fe8b26SLinus Walleij val &= ~KS8995_GC4_10BT; 489*a7fe8b26SLinus Walleij break; 490*a7fe8b26SLinus Walleij } 491*a7fe8b26SLinus Walleij 492*a7fe8b26SLinus Walleij if (duplex == DUPLEX_HALF) { 493*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set switch MII to half duplex\n"); 494*a7fe8b26SLinus Walleij val |= KS8995_GC4_MII_HD; 495*a7fe8b26SLinus Walleij } else { 496*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set switch MII to full duplex\n"); 497*a7fe8b26SLinus Walleij val &= ~KS8995_GC4_MII_HD; 498*a7fe8b26SLinus Walleij } 499*a7fe8b26SLinus Walleij 500*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set KS8995_REG_GC4 to %02x\n", val); 501*a7fe8b26SLinus Walleij 502*a7fe8b26SLinus Walleij /* Enable the CPU port */ 503*a7fe8b26SLinus Walleij ret = ks8995_write_reg(ks, KS8995_REG_GC4, val); 504*a7fe8b26SLinus Walleij if (ret) 505*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to set KS8995_REG_GC4\n"); 506*a7fe8b26SLinus Walleij } 507*a7fe8b26SLinus Walleij 508*a7fe8b26SLinus Walleij static void 509*a7fe8b26SLinus Walleij ks8995_mac_link_down(struct phylink_config *config, unsigned int mode, 510*a7fe8b26SLinus Walleij phy_interface_t interface) 511*a7fe8b26SLinus Walleij { 512*a7fe8b26SLinus Walleij struct dsa_port *dp = dsa_phylink_to_port(config); 513*a7fe8b26SLinus Walleij struct ks8995_switch *ks = dp->ds->priv; 514*a7fe8b26SLinus Walleij int port = dp->index; 515*a7fe8b26SLinus Walleij 516*a7fe8b26SLinus Walleij if (port != KS8995_CPU_PORT) 517*a7fe8b26SLinus Walleij return; 518*a7fe8b26SLinus Walleij 519*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "MAC link down on CPU port (%d)\n", port); 520*a7fe8b26SLinus Walleij 521*a7fe8b26SLinus Walleij /* Disable the CPU port */ 522*a7fe8b26SLinus Walleij } 523*a7fe8b26SLinus Walleij 524*a7fe8b26SLinus Walleij static const struct phylink_mac_ops ks8995_phylink_mac_ops = { 525*a7fe8b26SLinus Walleij .mac_config = ks8995_mac_config, 526*a7fe8b26SLinus Walleij .mac_link_up = ks8995_mac_link_up, 527*a7fe8b26SLinus Walleij .mac_link_down = ks8995_mac_link_down, 528*a7fe8b26SLinus Walleij }; 529*a7fe8b26SLinus Walleij 530*a7fe8b26SLinus Walleij static enum 531*a7fe8b26SLinus Walleij dsa_tag_protocol ks8995_get_tag_protocol(struct dsa_switch *ds, 532*a7fe8b26SLinus Walleij int port, 533*a7fe8b26SLinus Walleij enum dsa_tag_protocol mp) 534*a7fe8b26SLinus Walleij { 535*a7fe8b26SLinus Walleij /* This switch actually uses the 6 byte KS8995 protocol */ 536*a7fe8b26SLinus Walleij return DSA_TAG_PROTO_NONE; 537*a7fe8b26SLinus Walleij } 538*a7fe8b26SLinus Walleij 539*a7fe8b26SLinus Walleij static int ks8995_setup(struct dsa_switch *ds) 540*a7fe8b26SLinus Walleij { 541*a7fe8b26SLinus Walleij return 0; 542*a7fe8b26SLinus Walleij } 543*a7fe8b26SLinus Walleij 544*a7fe8b26SLinus Walleij static int ks8995_port_enable(struct dsa_switch *ds, int port, 545*a7fe8b26SLinus Walleij struct phy_device *phy) 546*a7fe8b26SLinus Walleij { 547*a7fe8b26SLinus Walleij struct ks8995_switch *ks = ds->priv; 548*a7fe8b26SLinus Walleij 549*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "enable port %d\n", port); 550*a7fe8b26SLinus Walleij 551*a7fe8b26SLinus Walleij return 0; 552*a7fe8b26SLinus Walleij } 553*a7fe8b26SLinus Walleij 554*a7fe8b26SLinus Walleij static void ks8995_port_disable(struct dsa_switch *ds, int port) 555*a7fe8b26SLinus Walleij { 556*a7fe8b26SLinus Walleij struct ks8995_switch *ks = ds->priv; 557*a7fe8b26SLinus Walleij 558*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "disable port %d\n", port); 559*a7fe8b26SLinus Walleij } 560*a7fe8b26SLinus Walleij 561*a7fe8b26SLinus Walleij static int ks8995_port_pre_bridge_flags(struct dsa_switch *ds, int port, 562*a7fe8b26SLinus Walleij struct switchdev_brport_flags flags, 563*a7fe8b26SLinus Walleij struct netlink_ext_ack *extack) 564*a7fe8b26SLinus Walleij { 565*a7fe8b26SLinus Walleij /* We support enabling/disabling learning */ 566*a7fe8b26SLinus Walleij if (flags.mask & ~(BR_LEARNING)) 567*a7fe8b26SLinus Walleij return -EINVAL; 568*a7fe8b26SLinus Walleij 569*a7fe8b26SLinus Walleij return 0; 570*a7fe8b26SLinus Walleij } 571*a7fe8b26SLinus Walleij 572*a7fe8b26SLinus Walleij static int ks8995_port_bridge_flags(struct dsa_switch *ds, int port, 573*a7fe8b26SLinus Walleij struct switchdev_brport_flags flags, 574*a7fe8b26SLinus Walleij struct netlink_ext_ack *extack) 575*a7fe8b26SLinus Walleij { 576*a7fe8b26SLinus Walleij struct ks8995_switch *ks = ds->priv; 577*a7fe8b26SLinus Walleij int ret; 578*a7fe8b26SLinus Walleij u8 val; 579*a7fe8b26SLinus Walleij 580*a7fe8b26SLinus Walleij if (flags.mask & BR_LEARNING) { 581*a7fe8b26SLinus Walleij ret = ks8995_read_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), &val); 582*a7fe8b26SLinus Walleij if (ret) { 583*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to read KS8995_REG_PC2 on port %d\n", port); 584*a7fe8b26SLinus Walleij return ret; 585*a7fe8b26SLinus Walleij } 586*a7fe8b26SLinus Walleij 587*a7fe8b26SLinus Walleij if (flags.val & BR_LEARNING) 588*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_LEARN_DIS; 589*a7fe8b26SLinus Walleij else 590*a7fe8b26SLinus Walleij val |= KS8995_PC2_LEARN_DIS; 591*a7fe8b26SLinus Walleij 592*a7fe8b26SLinus Walleij ret = ks8995_write_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), val); 593*a7fe8b26SLinus Walleij if (ret) { 594*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to write KS8995_REG_PC2 on port %d\n", port); 595*a7fe8b26SLinus Walleij return ret; 596*a7fe8b26SLinus Walleij } 597*a7fe8b26SLinus Walleij } 598*a7fe8b26SLinus Walleij 599*a7fe8b26SLinus Walleij return 0; 600*a7fe8b26SLinus Walleij } 601*a7fe8b26SLinus Walleij 602*a7fe8b26SLinus Walleij static void ks8995_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) 603*a7fe8b26SLinus Walleij { 604*a7fe8b26SLinus Walleij struct ks8995_switch *ks = ds->priv; 605*a7fe8b26SLinus Walleij int ret; 606*a7fe8b26SLinus Walleij u8 val; 607*a7fe8b26SLinus Walleij 608*a7fe8b26SLinus Walleij ret = ks8995_read_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), &val); 609*a7fe8b26SLinus Walleij if (ret) { 610*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to read KS8995_REG_PC2 on port %d\n", port); 611*a7fe8b26SLinus Walleij return; 612*a7fe8b26SLinus Walleij } 613*a7fe8b26SLinus Walleij 614*a7fe8b26SLinus Walleij /* Set the bits for the different STP states in accordance with 615*a7fe8b26SLinus Walleij * the datasheet, pages 36-37 "Spanning tree support". 616*a7fe8b26SLinus Walleij */ 617*a7fe8b26SLinus Walleij switch (state) { 618*a7fe8b26SLinus Walleij case BR_STATE_DISABLED: 619*a7fe8b26SLinus Walleij case BR_STATE_BLOCKING: 620*a7fe8b26SLinus Walleij case BR_STATE_LISTENING: 621*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_TXEN; 622*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_RXEN; 623*a7fe8b26SLinus Walleij val |= KS8995_PC2_LEARN_DIS; 624*a7fe8b26SLinus Walleij break; 625*a7fe8b26SLinus Walleij case BR_STATE_LEARNING: 626*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_TXEN; 627*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_RXEN; 628*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_LEARN_DIS; 629*a7fe8b26SLinus Walleij break; 630*a7fe8b26SLinus Walleij case BR_STATE_FORWARDING: 631*a7fe8b26SLinus Walleij val |= KS8995_PC2_TXEN; 632*a7fe8b26SLinus Walleij val |= KS8995_PC2_RXEN; 633*a7fe8b26SLinus Walleij val &= ~KS8995_PC2_LEARN_DIS; 634*a7fe8b26SLinus Walleij break; 635*a7fe8b26SLinus Walleij default: 636*a7fe8b26SLinus Walleij dev_err(ks->dev, "unknown bridge state requested\n"); 637*a7fe8b26SLinus Walleij return; 638*a7fe8b26SLinus Walleij } 639*a7fe8b26SLinus Walleij 640*a7fe8b26SLinus Walleij ret = ks8995_write_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), val); 641*a7fe8b26SLinus Walleij if (ret) { 642*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to write KS8995_REG_PC2 on port %d\n", port); 643*a7fe8b26SLinus Walleij return; 644*a7fe8b26SLinus Walleij } 645*a7fe8b26SLinus Walleij 646*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "set KS8995_REG_PC2 for port %d to %02x\n", port, val); 647*a7fe8b26SLinus Walleij } 648*a7fe8b26SLinus Walleij 649*a7fe8b26SLinus Walleij static void ks8995_phylink_get_caps(struct dsa_switch *dsa, int port, 650*a7fe8b26SLinus Walleij struct phylink_config *config) 651*a7fe8b26SLinus Walleij { 652*a7fe8b26SLinus Walleij unsigned long *interfaces = config->supported_interfaces; 653*a7fe8b26SLinus Walleij 654*a7fe8b26SLinus Walleij if (port == KS8995_CPU_PORT) 655*a7fe8b26SLinus Walleij __set_bit(PHY_INTERFACE_MODE_MII, interfaces); 656*a7fe8b26SLinus Walleij 657*a7fe8b26SLinus Walleij if (port <= 3) { 658*a7fe8b26SLinus Walleij /* Internal PHYs */ 659*a7fe8b26SLinus Walleij __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); 660*a7fe8b26SLinus Walleij /* phylib default */ 661*a7fe8b26SLinus Walleij __set_bit(PHY_INTERFACE_MODE_MII, interfaces); 662*a7fe8b26SLinus Walleij } 663*a7fe8b26SLinus Walleij 664*a7fe8b26SLinus Walleij config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; 665*a7fe8b26SLinus Walleij } 666*a7fe8b26SLinus Walleij 667*a7fe8b26SLinus Walleij /* Huge packet support up to 1916 byte packages "inclusive" 668*a7fe8b26SLinus Walleij * which means that tags are included. If the bit is not set 669*a7fe8b26SLinus Walleij * it is 1536 bytes "inclusive". We present the length without 670*a7fe8b26SLinus Walleij * tags or ethernet headers. The setting affects all ports. 671*a7fe8b26SLinus Walleij */ 672*a7fe8b26SLinus Walleij static int ks8995_change_mtu(struct dsa_switch *ds, int port, int new_mtu) 673*a7fe8b26SLinus Walleij { 674*a7fe8b26SLinus Walleij struct ks8995_switch *ks = ds->priv; 675*a7fe8b26SLinus Walleij unsigned int max_mtu; 676*a7fe8b26SLinus Walleij int ret; 677*a7fe8b26SLinus Walleij u8 val; 678*a7fe8b26SLinus Walleij int i; 679*a7fe8b26SLinus Walleij 680*a7fe8b26SLinus Walleij ks->max_mtu[port] = new_mtu; 681*a7fe8b26SLinus Walleij 682*a7fe8b26SLinus Walleij /* Roof out the MTU for the entire switch to the greatest 683*a7fe8b26SLinus Walleij * common denominator: the biggest set for any one port will 684*a7fe8b26SLinus Walleij * be the biggest MTU for the switch. 685*a7fe8b26SLinus Walleij */ 686*a7fe8b26SLinus Walleij max_mtu = ETH_DATA_LEN; 687*a7fe8b26SLinus Walleij for (i = 0; i < KS8995_NUM_PORTS; i++) { 688*a7fe8b26SLinus Walleij if (ks->max_mtu[i] > max_mtu) 689*a7fe8b26SLinus Walleij max_mtu = ks->max_mtu[i]; 690*a7fe8b26SLinus Walleij } 691*a7fe8b26SLinus Walleij 692*a7fe8b26SLinus Walleij /* Translate to layer 2 size. 693*a7fe8b26SLinus Walleij * Add ethernet and (possible) VLAN headers, and checksum to the size. 694*a7fe8b26SLinus Walleij * For ETH_DATA_LEN (1500 bytes) this will add up to 1522 bytes. 695*a7fe8b26SLinus Walleij */ 696*a7fe8b26SLinus Walleij max_mtu += VLAN_ETH_HLEN; 697*a7fe8b26SLinus Walleij max_mtu += ETH_FCS_LEN; 698*a7fe8b26SLinus Walleij 699*a7fe8b26SLinus Walleij ret = ks8995_read_reg(ks, KS8995_REG_GC2, &val); 700*a7fe8b26SLinus Walleij if (ret) { 701*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to read KS8995_REG_GC2\n"); 702*a7fe8b26SLinus Walleij return ret; 703*a7fe8b26SLinus Walleij } 704*a7fe8b26SLinus Walleij 705*a7fe8b26SLinus Walleij if (max_mtu <= 1522) { 706*a7fe8b26SLinus Walleij val &= ~KS8995_GC2_HUGE; 707*a7fe8b26SLinus Walleij val &= ~KS8995_GC2_LEGAL; 708*a7fe8b26SLinus Walleij } else if (max_mtu > 1522 && max_mtu <= 1536) { 709*a7fe8b26SLinus Walleij /* This accepts packets up to 1536 bytes */ 710*a7fe8b26SLinus Walleij val &= ~KS8995_GC2_HUGE; 711*a7fe8b26SLinus Walleij val |= KS8995_GC2_LEGAL; 712*a7fe8b26SLinus Walleij } else { 713*a7fe8b26SLinus Walleij /* This accepts packets up to 1916 bytes */ 714*a7fe8b26SLinus Walleij val |= KS8995_GC2_HUGE; 715*a7fe8b26SLinus Walleij val |= KS8995_GC2_LEGAL; 716*a7fe8b26SLinus Walleij } 717*a7fe8b26SLinus Walleij 718*a7fe8b26SLinus Walleij dev_dbg(ks->dev, "new max MTU %d bytes (inclusive)\n", max_mtu); 719*a7fe8b26SLinus Walleij 720*a7fe8b26SLinus Walleij ret = ks8995_write_reg(ks, KS8995_REG_GC2, val); 721*a7fe8b26SLinus Walleij if (ret) 722*a7fe8b26SLinus Walleij dev_err(ks->dev, "failed to set KS8995_REG_GC2\n"); 723*a7fe8b26SLinus Walleij 724*a7fe8b26SLinus Walleij return ret; 725*a7fe8b26SLinus Walleij } 726*a7fe8b26SLinus Walleij 727*a7fe8b26SLinus Walleij static int ks8995_get_max_mtu(struct dsa_switch *ds, int port) 728*a7fe8b26SLinus Walleij { 729*a7fe8b26SLinus Walleij return 1916 - ETH_HLEN - ETH_FCS_LEN; 730*a7fe8b26SLinus Walleij } 731*a7fe8b26SLinus Walleij 732*a7fe8b26SLinus Walleij static const struct dsa_switch_ops ks8995_ds_ops = { 733*a7fe8b26SLinus Walleij .get_tag_protocol = ks8995_get_tag_protocol, 734*a7fe8b26SLinus Walleij .setup = ks8995_setup, 735*a7fe8b26SLinus Walleij .port_pre_bridge_flags = ks8995_port_pre_bridge_flags, 736*a7fe8b26SLinus Walleij .port_bridge_flags = ks8995_port_bridge_flags, 737*a7fe8b26SLinus Walleij .port_enable = ks8995_port_enable, 738*a7fe8b26SLinus Walleij .port_disable = ks8995_port_disable, 739*a7fe8b26SLinus Walleij .port_stp_state_set = ks8995_port_stp_state_set, 740*a7fe8b26SLinus Walleij .port_change_mtu = ks8995_change_mtu, 741*a7fe8b26SLinus Walleij .port_max_mtu = ks8995_get_max_mtu, 742*a7fe8b26SLinus Walleij .phylink_get_caps = ks8995_phylink_get_caps, 743*a7fe8b26SLinus Walleij }; 744*a7fe8b26SLinus Walleij 74560cbe71fSLinus Walleij /* ------------------------------------------------------------------------ */ 74660cbe71fSLinus Walleij static int ks8995_probe(struct spi_device *spi) 74760cbe71fSLinus Walleij { 74860cbe71fSLinus Walleij struct ks8995_switch *ks; 74960cbe71fSLinus Walleij int err; 75060cbe71fSLinus Walleij int variant = spi_get_device_id(spi)->driver_data; 75160cbe71fSLinus Walleij 75260cbe71fSLinus Walleij if (variant >= max_variant) { 75360cbe71fSLinus Walleij dev_err(&spi->dev, "bad chip variant %d\n", variant); 75460cbe71fSLinus Walleij return -ENODEV; 75560cbe71fSLinus Walleij } 75660cbe71fSLinus Walleij 75760cbe71fSLinus Walleij ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); 75860cbe71fSLinus Walleij if (!ks) 75960cbe71fSLinus Walleij return -ENOMEM; 76060cbe71fSLinus Walleij 76160cbe71fSLinus Walleij mutex_init(&ks->lock); 76260cbe71fSLinus Walleij ks->spi = spi; 763*a7fe8b26SLinus Walleij ks->dev = &spi->dev; 76460cbe71fSLinus Walleij ks->chip = &ks8995_chip[variant]; 76560cbe71fSLinus Walleij 76660cbe71fSLinus Walleij ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", 76760cbe71fSLinus Walleij GPIOD_OUT_HIGH); 76860cbe71fSLinus Walleij err = PTR_ERR_OR_ZERO(ks->reset_gpio); 76960cbe71fSLinus Walleij if (err) { 77060cbe71fSLinus Walleij dev_err(&spi->dev, 77160cbe71fSLinus Walleij "failed to get reset gpio: %d\n", err); 77260cbe71fSLinus Walleij return err; 77360cbe71fSLinus Walleij } 77460cbe71fSLinus Walleij 77560cbe71fSLinus Walleij err = gpiod_set_consumer_name(ks->reset_gpio, "switch-reset"); 77660cbe71fSLinus Walleij if (err) 77760cbe71fSLinus Walleij return err; 77860cbe71fSLinus Walleij 779ccf29cb8SLinus Walleij if (ks->reset_gpio) { 780ccf29cb8SLinus Walleij /* 781ccf29cb8SLinus Walleij * If a reset line was obtained, wait for 100us after 782ccf29cb8SLinus Walleij * de-asserting RESET before accessing any registers, see 783ccf29cb8SLinus Walleij * the KS8995MA datasheet, page 44. 784ccf29cb8SLinus Walleij */ 78560cbe71fSLinus Walleij gpiod_set_value_cansleep(ks->reset_gpio, 0); 786ccf29cb8SLinus Walleij udelay(100); 787ccf29cb8SLinus Walleij } 78860cbe71fSLinus Walleij 78960cbe71fSLinus Walleij spi_set_drvdata(spi, ks); 79060cbe71fSLinus Walleij 79160cbe71fSLinus Walleij spi->mode = SPI_MODE_0; 79260cbe71fSLinus Walleij spi->bits_per_word = 8; 79360cbe71fSLinus Walleij err = spi_setup(spi); 79460cbe71fSLinus Walleij if (err) { 79560cbe71fSLinus Walleij dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); 79660cbe71fSLinus Walleij return err; 79760cbe71fSLinus Walleij } 79860cbe71fSLinus Walleij 79960cbe71fSLinus Walleij err = ks8995_get_revision(ks); 80060cbe71fSLinus Walleij if (err) 80160cbe71fSLinus Walleij return err; 80260cbe71fSLinus Walleij 80360cbe71fSLinus Walleij err = ks8995_reset(ks); 80460cbe71fSLinus Walleij if (err) 80560cbe71fSLinus Walleij return err; 80660cbe71fSLinus Walleij 80760cbe71fSLinus Walleij dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", 80860cbe71fSLinus Walleij ks->chip->name, ks->chip->chip_id, ks->revision_id); 80960cbe71fSLinus Walleij 810*a7fe8b26SLinus Walleij err = ks8995_check_config(ks); 811*a7fe8b26SLinus Walleij if (err) 812*a7fe8b26SLinus Walleij return err; 813*a7fe8b26SLinus Walleij 814*a7fe8b26SLinus Walleij ks->ds = devm_kzalloc(&spi->dev, sizeof(*ks->ds), GFP_KERNEL); 815*a7fe8b26SLinus Walleij if (!ks->ds) 816*a7fe8b26SLinus Walleij return -ENOMEM; 817*a7fe8b26SLinus Walleij 818*a7fe8b26SLinus Walleij ks->ds->dev = &spi->dev; 819*a7fe8b26SLinus Walleij ks->ds->num_ports = KS8995_NUM_PORTS; 820*a7fe8b26SLinus Walleij ks->ds->ops = &ks8995_ds_ops; 821*a7fe8b26SLinus Walleij ks->ds->phylink_mac_ops = &ks8995_phylink_mac_ops; 822*a7fe8b26SLinus Walleij ks->ds->priv = ks; 823*a7fe8b26SLinus Walleij 824*a7fe8b26SLinus Walleij err = dsa_register_switch(ks->ds); 825*a7fe8b26SLinus Walleij if (err) 826*a7fe8b26SLinus Walleij return dev_err_probe(&spi->dev, err, 827*a7fe8b26SLinus Walleij "unable to register DSA switch\n"); 828*a7fe8b26SLinus Walleij 82960cbe71fSLinus Walleij return 0; 83060cbe71fSLinus Walleij } 83160cbe71fSLinus Walleij 83260cbe71fSLinus Walleij static void ks8995_remove(struct spi_device *spi) 83360cbe71fSLinus Walleij { 83460cbe71fSLinus Walleij struct ks8995_switch *ks = spi_get_drvdata(spi); 83560cbe71fSLinus Walleij 836*a7fe8b26SLinus Walleij dsa_unregister_switch(ks->ds); 83760cbe71fSLinus Walleij /* assert reset */ 83860cbe71fSLinus Walleij gpiod_set_value_cansleep(ks->reset_gpio, 1); 83960cbe71fSLinus Walleij } 84060cbe71fSLinus Walleij 84160cbe71fSLinus Walleij /* ------------------------------------------------------------------------ */ 84260cbe71fSLinus Walleij static struct spi_driver ks8995_driver = { 84360cbe71fSLinus Walleij .driver = { 84460cbe71fSLinus Walleij .name = "spi-ks8995", 84560cbe71fSLinus Walleij .of_match_table = ks8895_spi_of_match, 84660cbe71fSLinus Walleij }, 84760cbe71fSLinus Walleij .probe = ks8995_probe, 84860cbe71fSLinus Walleij .remove = ks8995_remove, 84960cbe71fSLinus Walleij .id_table = ks8995_id, 85060cbe71fSLinus Walleij }; 85160cbe71fSLinus Walleij 85260cbe71fSLinus Walleij module_spi_driver(ks8995_driver); 85360cbe71fSLinus Walleij 85460cbe71fSLinus Walleij MODULE_DESCRIPTION(DRV_DESC); 85560cbe71fSLinus Walleij MODULE_VERSION(DRV_VERSION); 85660cbe71fSLinus Walleij MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); 85760cbe71fSLinus Walleij MODULE_LICENSE("GPL v2"); 858