^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Microchip KSZ9477 switch driver main logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2017-2019 Microchip Technology Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/platform_data/microchip-ksz.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/if_bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/dsa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <net/switchdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "ksz9477_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ksz_common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Used with variable features to indicate capabilities. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define GBIT_SUPPORT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define NEW_XMII BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define IS_9893 BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) char string[ETH_GSTRING_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) } ksz9477_mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { 0x00, "rx_hi" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) { 0x01, "rx_undersize" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) { 0x02, "rx_fragments" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) { 0x03, "rx_oversize" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) { 0x04, "rx_jabbers" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) { 0x05, "rx_symbol_err" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) { 0x06, "rx_crc_err" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { 0x07, "rx_align_err" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) { 0x08, "rx_mac_ctrl" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { 0x09, "rx_pause" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { 0x0A, "rx_bcast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { 0x0B, "rx_mcast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { 0x0C, "rx_ucast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { 0x0D, "rx_64_or_less" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) { 0x0E, "rx_65_127" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { 0x0F, "rx_128_255" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { 0x10, "rx_256_511" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { 0x11, "rx_512_1023" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { 0x12, "rx_1024_1522" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { 0x13, "rx_1523_2000" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { 0x14, "rx_2001" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { 0x15, "tx_hi" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { 0x16, "tx_late_col" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { 0x17, "tx_pause" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { 0x18, "tx_bcast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { 0x19, "tx_mcast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { 0x1A, "tx_ucast" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { 0x1B, "tx_deferred" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { 0x1C, "tx_total_col" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { 0x1D, "tx_exc_col" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { 0x1E, "tx_single_col" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { 0x1F, "tx_mult_col" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { 0x80, "rx_total" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { 0x81, "tx_total" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { 0x82, "rx_discards" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { 0x83, "tx_discards" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) bits, set ? bits : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u32 bits, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) bits, set ? bits : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) val, !(val & VLAN_START), 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int ksz9477_get_vlan_table(struct ksz_device *dev, u16 vid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u32 *vlan_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mutex_lock(&dev->vlan_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ksz_write16(dev, REG_SW_VLAN_ENTRY_INDEX__2, vid & VLAN_INDEX_M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_READ | VLAN_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* wait to be cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = ksz9477_wait_vlan_ctrl_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dev_dbg(dev->dev, "Failed to read vlan table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ksz_read32(dev, REG_SW_VLAN_ENTRY__4, &vlan_table[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ksz_read32(dev, REG_SW_VLAN_ENTRY_UNTAG__4, &vlan_table[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ksz_read32(dev, REG_SW_VLAN_ENTRY_PORTS__4, &vlan_table[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ksz_write8(dev, REG_SW_VLAN_CTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mutex_unlock(&dev->vlan_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int ksz9477_set_vlan_table(struct ksz_device *dev, u16 vid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u32 *vlan_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) mutex_lock(&dev->vlan_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ksz_write32(dev, REG_SW_VLAN_ENTRY__4, vlan_table[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ksz_write32(dev, REG_SW_VLAN_ENTRY_UNTAG__4, vlan_table[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ksz_write32(dev, REG_SW_VLAN_ENTRY_PORTS__4, vlan_table[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ksz_write16(dev, REG_SW_VLAN_ENTRY_INDEX__2, vid & VLAN_INDEX_M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_START | VLAN_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* wait to be cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ret = ksz9477_wait_vlan_ctrl_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dev_dbg(dev->dev, "Failed to write vlan table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ksz_write8(dev, REG_SW_VLAN_CTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* update vlan cache table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dev->vlan_cache[vid].table[0] = vlan_table[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dev->vlan_cache[vid].table[1] = vlan_table[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dev->vlan_cache[vid].table[2] = vlan_table[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) mutex_unlock(&dev->vlan_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static void ksz9477_read_table(struct ksz_device *dev, u32 *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ksz_read32(dev, REG_SW_ALU_VAL_A, &table[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ksz_read32(dev, REG_SW_ALU_VAL_B, &table[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ksz_read32(dev, REG_SW_ALU_VAL_C, &table[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ksz_read32(dev, REG_SW_ALU_VAL_D, &table[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void ksz9477_write_table(struct ksz_device *dev, u32 *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ksz_write32(dev, REG_SW_ALU_VAL_A, table[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ksz_write32(dev, REG_SW_ALU_VAL_B, table[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ksz_write32(dev, REG_SW_ALU_VAL_C, table[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ksz_write32(dev, REG_SW_ALU_VAL_D, table[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int ksz9477_wait_alu_ready(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) val, !(val & ALU_START), 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return regmap_read_poll_timeout(dev->regmap[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) REG_SW_ALU_STAT_CTRL__4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) val, !(val & ALU_STAT_START),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static int ksz9477_reset_switch(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 data8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 data32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* reset switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* turn off SPI DO Edge select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) SPI_AUTO_EDGE_DETECTION, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* default configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ksz_read8(dev, REG_SW_LUE_CTRL_1, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) data8 = SW_AGING_ENABLE | SW_LINK_AUTO_AGING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) SW_SRC_ADDR_FILTER | SW_FLUSH_STP_TABLE | SW_FLUSH_MSTP_TABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ksz_write8(dev, REG_SW_LUE_CTRL_1, data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ksz_write32(dev, REG_SW_INT_MASK__4, SWITCH_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* set broadcast storm protection 10% rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) regmap_update_bits(dev->regmap[1], REG_SW_MAC_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) BROADCAST_STORM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) (BROADCAST_STORM_VALUE *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) BROADCAST_STORM_PROT_RATE) / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (dev->synclko_125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ksz_write8(dev, REG_SW_GLOBAL_OUTPUT_CTRL__1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) SW_ENABLE_REFCLKO | SW_REFCLKO_IS_125MHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u64 *cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct ksz_port *p = &dev->ports[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* retain the flush/freeze bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) data |= MIB_COUNTER_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) data |= (addr << MIB_COUNTER_INDEX_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ret = regmap_read_poll_timeout(dev->regmap[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) val, !(val & MIB_COUNTER_READ), 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* failed to read MIB. get out of loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dev_dbg(dev->dev, "Failed to get MIB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* count resets upon read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) *cnt += data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u64 *dropped, u64 *cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) addr = ksz9477_mib_names[addr].index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ksz9477_r_mib_cnt(dev, port, addr, cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct ksz_port *p = &dev->ports[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* enable/disable the port for flush/freeze function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mutex_lock(&p->mib.cnt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* used by MIB counter reading code to know freeze is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) p->freeze = freeze;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mutex_unlock(&p->mib.cnt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct ksz_port_mib *mib = &dev->ports[port].mib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* flush all enabled port MIB counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) mutex_lock(&mib->cnt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) MIB_COUNTER_FLUSH_FREEZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) mutex_unlock(&mib->cnt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) mib->cnt_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) enum dsa_tag_protocol mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (dev->features & IS_9893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) proto = DSA_TAG_PROTO_KSZ9893;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u16 val = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* No real PHY after this. Simulate the PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * A fixed PHY can be setup in the device tree, but this function is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * still called for that port during initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * For RGMII PHY there is no way to access it so the fixed PHY should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * be used. For SGMII PHY the supporting code will be added later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (addr >= dev->phy_port_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct ksz_port *p = &dev->ports[addr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case MII_BMCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) val = 0x1140;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case MII_BMSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) val = 0x796d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case MII_PHYSID1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) val = 0x0022;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case MII_PHYSID2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) val = 0x1631;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case MII_ADVERTISE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) val = 0x05e1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) case MII_LPA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) val = 0xc5e1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case MII_CTRL1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) val = 0x0700;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case MII_STAT1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (p->phydev.speed == SPEED_1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) val = 0x3800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ksz_pread16(dev, addr, 0x100 + (reg << 1), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* No real PHY after this. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (addr >= dev->phy_port_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* No gigabit support. Do not write to this register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void ksz9477_get_strings(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) u32 stringset, uint8_t *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (stringset != ETH_SS_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) memcpy(buf + i * ETH_GSTRING_LEN, ksz9477_mib_names[i].string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) u8 member)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ksz_pwrite32(dev, port, REG_PORT_VLAN_MEMBERSHIP__4, member);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) dev->ports[port].member = member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) u8 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct ksz_port *p = &dev->ports[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int member = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int forward = dev->member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ksz_pread8(dev, port, P_STP_CTRL, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case BR_STATE_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) data |= PORT_LEARN_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (port != dev->cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) member = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case BR_STATE_LISTENING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (port != dev->cpu_port &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) p->stp_state == BR_STATE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) member = dev->host_mask | p->vid_member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) case BR_STATE_LEARNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) data |= PORT_RX_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case BR_STATE_FORWARDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) data |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* This function is also used internally. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (port == dev->cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) member = dev->host_mask | p->vid_member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) mutex_lock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* Port is a member of a bridge. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (dev->br_member & (1 << port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) dev->member |= (1 << port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) member = dev->member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) mutex_unlock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case BR_STATE_BLOCKING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) data |= PORT_LEARN_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (port != dev->cpu_port &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) p->stp_state == BR_STATE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) member = dev->host_mask | p->vid_member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dev_err(ds->dev, "invalid STP state: %d\n", state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ksz_pwrite8(dev, port, P_STP_CTRL, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) p->stp_state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mutex_lock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* Port membership may share register with STP state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (member >= 0 && member != p->member)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ksz9477_cfg_port_member(dev, port, (u8)member);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* Check if forwarding needs to be updated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (state != BR_STATE_FORWARDING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (dev->br_member & (1 << port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) dev->member &= ~(1 << port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* When topology has changed the function ksz_update_port_member
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * should be called to modify port forwarding behavior.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (forward != dev->member)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ksz_update_port_member(dev, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) mutex_unlock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (port < dev->mib_port_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* flush individual port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ksz_pread8(dev, port, P_STP_CTRL, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (!(data & PORT_LEARN_DISABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ksz_pwrite8(dev, port, P_STP_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) data | PORT_LEARN_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) ksz_pwrite8(dev, port, P_STP_CTRL, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* flush all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_STP_TABLE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) bool flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct switchdev_trans *trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (switchdev_trans_ph_prepare(trans))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) PORT_VLAN_LOOKUP_VID_0, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_VLAN_ENABLE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_VLAN_ENABLE, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) PORT_VLAN_LOOKUP_VID_0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static void ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) u32 vlan_table[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (ksz9477_get_vlan_table(dev, vid, vlan_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_dbg(dev->dev, "Failed to get vlan table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) vlan_table[0] = VLAN_VALID | (vid & VLAN_FID_M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (untagged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) vlan_table[1] |= BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) vlan_table[1] &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) vlan_table[1] &= ~(BIT(dev->cpu_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) vlan_table[2] |= BIT(port) | BIT(dev->cpu_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (ksz9477_set_vlan_table(dev, vid, vlan_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) dev_dbg(dev->dev, "Failed to set vlan table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* change PVID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u32 vlan_table[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) u16 pvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) ksz_pread16(dev, port, REG_PORT_DEFAULT_VID, &pvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) pvid = pvid & 0xFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (ksz9477_get_vlan_table(dev, vid, vlan_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) dev_dbg(dev->dev, "Failed to get vlan table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) vlan_table[2] &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (pvid == vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) pvid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (untagged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) vlan_table[1] &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (ksz9477_set_vlan_table(dev, vid, vlan_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) dev_dbg(dev->dev, "Failed to set vlan table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, pvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int ksz9477_port_fdb_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) const unsigned char *addr, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) u32 alu_table[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) mutex_lock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* find any entry with mac & vid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) data = vid << ALU_FID_INDEX_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) data |= ((addr[0] << 8) | addr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ksz_write32(dev, REG_SW_ALU_INDEX_0, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) data = ((addr[2] << 24) | (addr[3] << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) data |= ((addr[4] << 8) | addr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ksz_write32(dev, REG_SW_ALU_INDEX_1, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* start read operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ret = ksz9477_wait_alu_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) dev_dbg(dev->dev, "Failed to read ALU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* read ALU entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ksz9477_read_table(dev, alu_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* update ALU entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) alu_table[0] = ALU_V_STATIC_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) alu_table[1] |= BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) alu_table[1] |= ALU_V_USE_FID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) alu_table[2] = (vid << ALU_V_FID_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) alu_table[2] |= ((addr[0] << 8) | addr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) alu_table[3] = ((addr[2] << 24) | (addr[3] << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) alu_table[3] |= ((addr[4] << 8) | addr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ksz9477_write_table(dev, alu_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ret = ksz9477_wait_alu_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) dev_dbg(dev->dev, "Failed to write ALU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) mutex_unlock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static int ksz9477_port_fdb_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) const unsigned char *addr, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) u32 alu_table[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mutex_lock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* read any entry with mac & vid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) data = vid << ALU_FID_INDEX_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) data |= ((addr[0] << 8) | addr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ksz_write32(dev, REG_SW_ALU_INDEX_0, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) data = ((addr[2] << 24) | (addr[3] << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) data |= ((addr[4] << 8) | addr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ksz_write32(dev, REG_SW_ALU_INDEX_1, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* start read operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ret = ksz9477_wait_alu_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_dbg(dev->dev, "Failed to read ALU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ksz_read32(dev, REG_SW_ALU_VAL_A, &alu_table[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (alu_table[0] & ALU_V_STATIC_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ksz_read32(dev, REG_SW_ALU_VAL_B, &alu_table[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ksz_read32(dev, REG_SW_ALU_VAL_C, &alu_table[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* clear forwarding port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) alu_table[2] &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* if there is no port to forward, clear table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if ((alu_table[2] & ALU_V_PORT_MAP) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) alu_table[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) alu_table[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) alu_table[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) alu_table[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) alu_table[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) alu_table[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) alu_table[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) alu_table[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ksz9477_write_table(dev, alu_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) ret = ksz9477_wait_alu_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_dbg(dev->dev, "Failed to write ALU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) mutex_unlock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static void ksz9477_convert_alu(struct alu_struct *alu, u32 *alu_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) alu->is_static = !!(alu_table[0] & ALU_V_STATIC_VALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) alu->is_src_filter = !!(alu_table[0] & ALU_V_SRC_FILTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) alu->is_dst_filter = !!(alu_table[0] & ALU_V_DST_FILTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) alu->prio_age = (alu_table[0] >> ALU_V_PRIO_AGE_CNT_S) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ALU_V_PRIO_AGE_CNT_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) alu->mstp = alu_table[0] & ALU_V_MSTP_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) alu->is_override = !!(alu_table[1] & ALU_V_OVERRIDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) alu->is_use_fid = !!(alu_table[1] & ALU_V_USE_FID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) alu->port_forward = alu_table[1] & ALU_V_PORT_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) alu->fid = (alu_table[2] >> ALU_V_FID_S) & ALU_V_FID_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) alu->mac[0] = (alu_table[2] >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) alu->mac[1] = alu_table[2] & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) alu->mac[2] = (alu_table[3] >> 24) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) alu->mac[3] = (alu_table[3] >> 16) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) alu->mac[4] = (alu_table[3] >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) alu->mac[5] = alu_table[3] & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) static int ksz9477_port_fdb_dump(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dsa_fdb_dump_cb_t *cb, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) u32 ksz_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) u32 alu_table[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct alu_struct alu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) mutex_lock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /* start ALU search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_START | ALU_SEARCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) timeout = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ksz_read32(dev, REG_SW_ALU_CTRL__4, &ksz_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if ((ksz_data & ALU_VALID) || !(ksz_data & ALU_START))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) usleep_range(1, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) } while (timeout-- > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dev_dbg(dev->dev, "Failed to search ALU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* read ALU table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) ksz9477_read_table(dev, alu_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ksz9477_convert_alu(&alu, alu_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (alu.port_forward & BIT(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) ret = cb(alu.mac, alu.fid, alu.is_static, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) } while (ksz_data & ALU_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* stop ALU search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ksz_write32(dev, REG_SW_ALU_CTRL__4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) mutex_unlock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static void ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) const struct switchdev_obj_port_mdb *mdb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) u32 static_table[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) u32 mac_hi, mac_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) mac_lo |= ((mdb->addr[4] << 8) | mdb->addr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) mutex_lock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) for (index = 0; index < dev->num_statics; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* find empty slot first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) data = (index << ALU_STAT_INDEX_S) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) ALU_STAT_READ | ALU_STAT_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (ksz9477_wait_alu_sta_ready(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /* read ALU static table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) ksz9477_read_table(dev, static_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (static_table[0] & ALU_V_STATIC_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* check this has same vid & mac address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (((static_table[2] >> ALU_V_FID_S) == mdb->vid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) ((static_table[2] & ALU_V_MAC_ADDR_HI) == mac_hi) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static_table[3] == mac_lo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* found matching one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* found empty one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /* no available entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (index == dev->num_statics)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* add entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static_table[0] = ALU_V_STATIC_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static_table[1] |= BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (mdb->vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static_table[1] |= ALU_V_USE_FID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) static_table[2] = (mdb->vid << ALU_V_FID_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static_table[2] |= mac_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static_table[3] = mac_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) ksz9477_write_table(dev, static_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) data = (index << ALU_STAT_INDEX_S) | ALU_STAT_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (ksz9477_wait_alu_sta_ready(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) mutex_unlock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) const struct switchdev_obj_port_mdb *mdb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) u32 static_table[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) u32 mac_hi, mac_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) mac_lo |= ((mdb->addr[4] << 8) | mdb->addr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) mutex_lock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) for (index = 0; index < dev->num_statics; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* find empty slot first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) data = (index << ALU_STAT_INDEX_S) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) ALU_STAT_READ | ALU_STAT_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) ret = ksz9477_wait_alu_sta_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* read ALU static table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ksz9477_read_table(dev, static_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (static_table[0] & ALU_V_STATIC_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* check this has same vid & mac address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (((static_table[2] >> ALU_V_FID_S) == mdb->vid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) ((static_table[2] & ALU_V_MAC_ADDR_HI) == mac_hi) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static_table[3] == mac_lo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* found matching one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* no available entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (index == dev->num_statics)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /* clear port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static_table[1] &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if ((static_table[1] & ALU_V_PORT_MAP) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* delete entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static_table[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static_table[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static_table[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static_table[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ksz9477_write_table(dev, static_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) data = (index << ALU_STAT_INDEX_S) | ALU_STAT_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /* wait to be finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ret = ksz9477_wait_alu_sta_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) mutex_unlock(&dev->alu_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct dsa_mall_mirror_tc_entry *mirror,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) bool ingress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (ingress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* configure mirror port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) PORT_MIRROR_SNIFFER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct dsa_mall_mirror_tc_entry *mirror)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (mirror->ingress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) ksz_pread8(dev, port, P_MIRROR_CTRL, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!(data & (PORT_MIRROR_RX | PORT_MIRROR_TX)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) PORT_MIRROR_SNIFFER, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) bool gbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (dev->features & NEW_XMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) gbit = !(data & PORT_MII_NOT_1GBIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) gbit = !!(data & PORT_MII_1000MBIT_S1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return gbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) static void ksz9477_set_gbit(struct ksz_device *dev, bool gbit, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (dev->features & NEW_XMII) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (gbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) *data &= ~PORT_MII_NOT_1GBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) *data |= PORT_MII_NOT_1GBIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (gbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) *data |= PORT_MII_1000MBIT_S1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) *data &= ~PORT_MII_1000MBIT_S1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static int ksz9477_get_xmii(struct ksz_device *dev, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (dev->features & NEW_XMII) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) switch (data & PORT_MII_SEL_M) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) case PORT_MII_SEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case PORT_RMII_SEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) case PORT_GMII_SEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) mode = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) mode = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) switch (data & PORT_MII_SEL_M) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) case PORT_MII_SEL_S1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) case PORT_RMII_SEL_S1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) case PORT_GMII_SEL_S1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) mode = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) mode = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static void ksz9477_set_xmii(struct ksz_device *dev, int mode, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) u8 xmii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (dev->features & NEW_XMII) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) xmii = PORT_MII_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) xmii = PORT_RMII_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) xmii = PORT_GMII_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) xmii = PORT_RGMII_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) xmii = PORT_MII_SEL_S1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) xmii = PORT_RMII_SEL_S1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) xmii = PORT_GMII_SEL_S1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) xmii = PORT_RGMII_SEL_S1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) *data &= ~PORT_MII_SEL_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) *data |= xmii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) phy_interface_t interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) bool gbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) u8 data8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (port < dev->phy_port_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return PHY_INTERFACE_MODE_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) gbit = ksz9477_get_gbit(dev, data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) mode = ksz9477_get_xmii(dev, data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) interface = PHY_INTERFACE_MODE_GMII;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (gbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) interface = PHY_INTERFACE_MODE_MII;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) interface = PHY_INTERFACE_MODE_RMII;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) interface = PHY_INTERFACE_MODE_RGMII;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (data8 & PORT_RGMII_ID_EG_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) interface = PHY_INTERFACE_MODE_RGMII_TXID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (data8 & PORT_RGMII_ID_IG_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) interface = PHY_INTERFACE_MODE_RGMII_RXID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (data8 & PORT_RGMII_ID_EG_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) interface = PHY_INTERFACE_MODE_RGMII_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) static void ksz9477_port_mmd_write(struct ksz_device *dev, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) u8 dev_addr, u16 reg_addr, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /* Apply PHY settings to address errata listed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * Silicon Errata and Data Sheet Clarification documents:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) * Register settings are needed to improve PHY receive performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) /* Transmit waveform amplitude can be improved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * (1000BASE-T, 100BASE-TX, 10BASE-Te)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* Energy Efficient Ethernet (EEE) feature select must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * be manually disabled (except on KSZ8565 which is 100Mbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (dev->features & GBIT_SUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* Register settings are required to meet data sheet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * supply current specifications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) u8 data8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) u8 member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) u16 data16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) struct ksz_port *p = &dev->ports[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* enable tag tail for host port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_TAIL_TAG_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_MAC_LOOPBACK, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /* set back pressure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ksz_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /* enable broadcast storm limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* disable DiffServ priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_PRIO_ENABLE, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* replace priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) ksz_port_cfg(dev, port, REG_PORT_MRI_MAC_CTRL, PORT_USER_PRIO_CEILING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) ksz9477_port_cfg32(dev, port, REG_PORT_MTI_QUEUE_CTRL_0__4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) MTI_PVID_REPLACE, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) /* enable 802.1p priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (port < dev->phy_port_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) /* do not force flow control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (dev->phy_errata_9477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) ksz9477_phy_errata_setup(dev, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) /* force flow control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /* configure MAC to 1G & RGMII mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) switch (p->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) case PHY_INTERFACE_MODE_MII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) ksz9477_set_xmii(dev, 0, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ksz9477_set_gbit(dev, false, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) p->phydev.speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) case PHY_INTERFACE_MODE_RMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) ksz9477_set_xmii(dev, 1, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) ksz9477_set_gbit(dev, false, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) p->phydev.speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) case PHY_INTERFACE_MODE_GMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) ksz9477_set_xmii(dev, 2, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ksz9477_set_gbit(dev, true, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) p->phydev.speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ksz9477_set_xmii(dev, 3, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ksz9477_set_gbit(dev, true, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) data8 &= ~PORT_RGMII_ID_IG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) data8 &= ~PORT_RGMII_ID_EG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) data8 |= PORT_RGMII_ID_IG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) data8 |= PORT_RGMII_ID_EG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* On KSZ9893, disable RGMII in-band status support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (dev->features & IS_9893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) data8 &= ~PORT_MII_MAC_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) p->phydev.speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) p->phydev.duplex = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) mutex_lock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) member = dev->port_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) member = dev->host_mask | p->vid_member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) mutex_unlock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) ksz9477_cfg_port_member(dev, port, member);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /* clear pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (port < dev->phy_port_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) ksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) static void ksz9477_config_cpu_port(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) struct ksz_port *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) ds->num_ports = dev->port_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) for (i = 0; i < dev->port_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) phy_interface_t interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) const char *prev_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) const char *prev_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) dev->cpu_port = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) dev->host_mask = (1 << dev->cpu_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) dev->port_mask |= dev->host_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) p = &dev->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /* Read from XMII register to determine host port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * interface. If set specifically in device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * note the difference to help debugging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) interface = ksz9477_get_interface(dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (!p->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (dev->compat_interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) dev_warn(dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) "Please update your device tree.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) p->interface = dev->compat_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) p->interface = interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (interface && interface != p->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) prev_msg = " instead of ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) prev_mode = phy_modes(interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) prev_msg = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) prev_mode = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) dev_info(dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) "Port%d: using phy mode %s%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) phy_modes(p->interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) prev_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) prev_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) /* enable cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) ksz9477_port_setup(dev, i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) p->vid_member = dev->port_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) p->on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) dev->member = dev->host_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) for (i = 0; i < dev->mib_port_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (i == dev->cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) p = &dev->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /* Initialize to non-zero so that ksz_cfg_port_member() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * be called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) p->vid_member = (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) p->member = dev->port_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) ksz9477_port_stp_state_set(ds, i, BR_STATE_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) p->on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (i < dev->phy_port_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) p->phy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (dev->chip_id == 0x00947700 && i == 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) p->sgmii = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) /* SGMII PHY detection code is not implemented yet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) p->phy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) static int ksz9477_setup(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) struct ksz_device *dev = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) dev->num_vlans, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (!dev->vlan_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) ret = ksz9477_reset_switch(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) dev_err(ds->dev, "failed to reset switch\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) /* Required for port partitioning. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) /* Do not work correctly with tail tagging. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) ksz_cfg(dev, REG_SW_MAC_CTRL_0, SW_CHECK_LENGTH, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) /* accept packet up to 2000bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_LEGAL_PACKET_DISABLE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) ksz9477_config_cpu_port(ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) ksz_cfg(dev, REG_SW_MAC_CTRL_1, MULTICAST_STORM_DISABLE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) /* queue based egress rate limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* enable global MIB counter freeze function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) /* start switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ksz_cfg(dev, REG_SW_OPERATION, SW_START, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) ksz_init_mib_timer(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) static const struct dsa_switch_ops ksz9477_switch_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) .get_tag_protocol = ksz9477_get_tag_protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) .setup = ksz9477_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) .phy_read = ksz9477_phy_read16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) .phy_write = ksz9477_phy_write16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) .phylink_mac_link_down = ksz_mac_link_down,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) .port_enable = ksz_enable_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) .get_strings = ksz9477_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) .get_ethtool_stats = ksz_get_ethtool_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) .get_sset_count = ksz_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) .port_bridge_join = ksz_port_bridge_join,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) .port_bridge_leave = ksz_port_bridge_leave,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) .port_stp_state_set = ksz9477_port_stp_state_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) .port_fast_age = ksz_port_fast_age,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) .port_vlan_filtering = ksz9477_port_vlan_filtering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) .port_vlan_prepare = ksz_port_vlan_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) .port_vlan_add = ksz9477_port_vlan_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) .port_vlan_del = ksz9477_port_vlan_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) .port_fdb_dump = ksz9477_port_fdb_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) .port_fdb_add = ksz9477_port_fdb_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) .port_fdb_del = ksz9477_port_fdb_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) .port_mdb_prepare = ksz_port_mdb_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) .port_mdb_add = ksz9477_port_mdb_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) .port_mdb_del = ksz9477_port_mdb_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) .port_mirror_add = ksz9477_port_mirror_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) .port_mirror_del = ksz9477_port_mirror_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) static u32 ksz9477_get_port_addr(int port, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return PORT_CTRL_ADDR(port, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int ksz9477_switch_detect(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) u8 data8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) u8 id_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) u8 id_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) u32 id32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* turn off SPI DO Edge select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) ret = ksz_read8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) data8 &= ~SPI_AUTO_EDGE_DETECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ret = ksz_write8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) /* read chip id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) ret = ksz_read32(dev, REG_CHIP_ID0__1, &id32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /* Number of ports can be reduced depending on chip. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) dev->mib_port_cnt = TOTAL_PORT_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) dev->phy_port_cnt = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) /* Default capability is gigabit capable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) dev->features = GBIT_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) dev_dbg(dev->dev, "Switch detect: ID=%08x%02x\n", id32, data8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) id_hi = (u8)(id32 >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) id_lo = (u8)(id32 >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if ((id_lo & 0xf) == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) /* Chip is from KSZ9893 design. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) dev_info(dev->dev, "Found KSZ9893\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) dev->features |= IS_9893;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /* Chip does not support gigabit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (data8 & SW_QW_ABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) dev->features &= ~GBIT_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) dev->mib_port_cnt = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) dev->phy_port_cnt = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) dev_info(dev->dev, "Found KSZ9477 or compatible\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* Chip uses new XMII register definitions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) dev->features |= NEW_XMII;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) /* Chip does not support gigabit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (!(data8 & SW_GIGABIT_ABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) dev->features &= ~GBIT_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) /* Change chip id to known ones so it can be matched against them. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) id32 = (id_hi << 16) | (id_lo << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) dev->chip_id = id32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) struct ksz_chip_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) u32 chip_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) const char *dev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) int num_vlans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) int num_alus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) int num_statics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) int cpu_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) int port_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) bool phy_errata_9477;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) static const struct ksz_chip_data ksz9477_switch_chips[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) .chip_id = 0x00947700,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) .dev_name = "KSZ9477",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .num_vlans = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .num_alus = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) .num_statics = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) .cpu_ports = 0x7F, /* can be configured as cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) .port_cnt = 7, /* total physical port count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) .phy_errata_9477 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) .chip_id = 0x00989700,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) .dev_name = "KSZ9897",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) .num_vlans = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) .num_alus = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) .num_statics = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) .cpu_ports = 0x7F, /* can be configured as cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) .port_cnt = 7, /* total physical port count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) .phy_errata_9477 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) .chip_id = 0x00989300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) .dev_name = "KSZ9893",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) .num_vlans = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) .num_alus = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) .num_statics = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) .cpu_ports = 0x07, /* can be configured as cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) .port_cnt = 3, /* total port count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) .chip_id = 0x00956700,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) .dev_name = "KSZ9567",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) .num_vlans = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) .num_alus = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) .num_statics = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) .cpu_ports = 0x7F, /* can be configured as cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) .port_cnt = 7, /* total physical port count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) .phy_errata_9477 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) static int ksz9477_switch_init(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) dev->ds->ops = &ksz9477_switch_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) for (i = 0; i < ARRAY_SIZE(ksz9477_switch_chips); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) const struct ksz_chip_data *chip = &ksz9477_switch_chips[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) if (dev->chip_id == chip->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) dev->name = chip->dev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) dev->num_vlans = chip->num_vlans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) dev->num_alus = chip->num_alus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) dev->num_statics = chip->num_statics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) dev->port_cnt = chip->port_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) dev->cpu_ports = chip->cpu_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) dev->phy_errata_9477 = chip->phy_errata_9477;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) /* no switch found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (!dev->port_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) dev->port_mask = (1 << dev->port_cnt) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) i = dev->mib_port_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (!dev->ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) for (i = 0; i < dev->mib_port_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) mutex_init(&dev->ports[i].mib.cnt_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) dev->ports[i].mib.counters =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) devm_kzalloc(dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) sizeof(u64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) (TOTAL_SWITCH_COUNTER_NUM + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) if (!dev->ports[i].mib.counters)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) /* set the real number of ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) dev->ds->num_ports = dev->port_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) static void ksz9477_switch_exit(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) ksz9477_reset_switch(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) static const struct ksz_dev_ops ksz9477_dev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) .get_port_addr = ksz9477_get_port_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) .cfg_port_member = ksz9477_cfg_port_member,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) .port_setup = ksz9477_port_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) .r_mib_cnt = ksz9477_r_mib_cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) .r_mib_pkt = ksz9477_r_mib_pkt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) .freeze_mib = ksz9477_freeze_mib,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) .port_init_cnt = ksz9477_port_init_cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) .shutdown = ksz9477_reset_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) .detect = ksz9477_switch_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) .init = ksz9477_switch_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) .exit = ksz9477_switch_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) int ksz9477_switch_register(struct ksz_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) struct phy_device *phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) ret = ksz_switch_register(dev, &ksz9477_dev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) for (i = 0; i < dev->phy_port_cnt; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) if (!dsa_is_user_port(dev->ds, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) phydev = dsa_to_port(dev->ds, i)->slave->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /* The MAC actually cannot run in 1000 half-duplex mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) phy_remove_link_mode(phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /* PHY does not support gigabit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) if (!(dev->features & GBIT_SUPPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) phy_remove_link_mode(phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) EXPORT_SYMBOL(ksz9477_switch_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch DSA Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) MODULE_LICENSE("GPL");