1*e66f840cSTristram Ha // SPDX-License-Identifier: GPL-2.0 2*e66f840cSTristram Ha /* 3*e66f840cSTristram Ha * Microchip KSZ8795 switch driver 4*e66f840cSTristram Ha * 5*e66f840cSTristram Ha * Copyright (C) 2017 Microchip Technology Inc. 6*e66f840cSTristram Ha * Tristram Ha <Tristram.Ha@microchip.com> 7*e66f840cSTristram Ha */ 8*e66f840cSTristram Ha 9*e66f840cSTristram Ha #include <linux/delay.h> 10*e66f840cSTristram Ha #include <linux/export.h> 11*e66f840cSTristram Ha #include <linux/gpio.h> 12*e66f840cSTristram Ha #include <linux/kernel.h> 13*e66f840cSTristram Ha #include <linux/module.h> 14*e66f840cSTristram Ha #include <linux/platform_data/microchip-ksz.h> 15*e66f840cSTristram Ha #include <linux/phy.h> 16*e66f840cSTristram Ha #include <linux/etherdevice.h> 17*e66f840cSTristram Ha #include <linux/if_bridge.h> 18*e66f840cSTristram Ha #include <net/dsa.h> 19*e66f840cSTristram Ha #include <net/switchdev.h> 20*e66f840cSTristram Ha 21*e66f840cSTristram Ha #include "ksz_priv.h" 22*e66f840cSTristram Ha #include "ksz_common.h" 23*e66f840cSTristram Ha #include "ksz8795_reg.h" 24*e66f840cSTristram Ha 25*e66f840cSTristram Ha static const struct { 26*e66f840cSTristram Ha char string[ETH_GSTRING_LEN]; 27*e66f840cSTristram Ha } mib_names[TOTAL_SWITCH_COUNTER_NUM] = { 28*e66f840cSTristram Ha { "rx_hi" }, 29*e66f840cSTristram Ha { "rx_undersize" }, 30*e66f840cSTristram Ha { "rx_fragments" }, 31*e66f840cSTristram Ha { "rx_oversize" }, 32*e66f840cSTristram Ha { "rx_jabbers" }, 33*e66f840cSTristram Ha { "rx_symbol_err" }, 34*e66f840cSTristram Ha { "rx_crc_err" }, 35*e66f840cSTristram Ha { "rx_align_err" }, 36*e66f840cSTristram Ha { "rx_mac_ctrl" }, 37*e66f840cSTristram Ha { "rx_pause" }, 38*e66f840cSTristram Ha { "rx_bcast" }, 39*e66f840cSTristram Ha { "rx_mcast" }, 40*e66f840cSTristram Ha { "rx_ucast" }, 41*e66f840cSTristram Ha { "rx_64_or_less" }, 42*e66f840cSTristram Ha { "rx_65_127" }, 43*e66f840cSTristram Ha { "rx_128_255" }, 44*e66f840cSTristram Ha { "rx_256_511" }, 45*e66f840cSTristram Ha { "rx_512_1023" }, 46*e66f840cSTristram Ha { "rx_1024_1522" }, 47*e66f840cSTristram Ha { "rx_1523_2000" }, 48*e66f840cSTristram Ha { "rx_2001" }, 49*e66f840cSTristram Ha { "tx_hi" }, 50*e66f840cSTristram Ha { "tx_late_col" }, 51*e66f840cSTristram Ha { "tx_pause" }, 52*e66f840cSTristram Ha { "tx_bcast" }, 53*e66f840cSTristram Ha { "tx_mcast" }, 54*e66f840cSTristram Ha { "tx_ucast" }, 55*e66f840cSTristram Ha { "tx_deferred" }, 56*e66f840cSTristram Ha { "tx_total_col" }, 57*e66f840cSTristram Ha { "tx_exc_col" }, 58*e66f840cSTristram Ha { "tx_single_col" }, 59*e66f840cSTristram Ha { "tx_mult_col" }, 60*e66f840cSTristram Ha { "rx_total" }, 61*e66f840cSTristram Ha { "tx_total" }, 62*e66f840cSTristram Ha { "rx_discards" }, 63*e66f840cSTristram Ha { "tx_discards" }, 64*e66f840cSTristram Ha }; 65*e66f840cSTristram Ha 66*e66f840cSTristram Ha static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) 67*e66f840cSTristram Ha { 68*e66f840cSTristram Ha regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); 69*e66f840cSTristram Ha } 70*e66f840cSTristram Ha 71*e66f840cSTristram Ha static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, 72*e66f840cSTristram Ha bool set) 73*e66f840cSTristram Ha { 74*e66f840cSTristram Ha regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), 75*e66f840cSTristram Ha bits, set ? bits : 0); 76*e66f840cSTristram Ha } 77*e66f840cSTristram Ha 78*e66f840cSTristram Ha static int ksz8795_reset_switch(struct ksz_device *dev) 79*e66f840cSTristram Ha { 80*e66f840cSTristram Ha /* reset switch */ 81*e66f840cSTristram Ha ksz_write8(dev, REG_POWER_MANAGEMENT_1, 82*e66f840cSTristram Ha SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S); 83*e66f840cSTristram Ha ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0); 84*e66f840cSTristram Ha 85*e66f840cSTristram Ha return 0; 86*e66f840cSTristram Ha } 87*e66f840cSTristram Ha 88*e66f840cSTristram Ha static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) 89*e66f840cSTristram Ha { 90*e66f840cSTristram Ha u8 hi, lo; 91*e66f840cSTristram Ha 92*e66f840cSTristram Ha /* Number of queues can only be 1, 2, or 4. */ 93*e66f840cSTristram Ha switch (queue) { 94*e66f840cSTristram Ha case 4: 95*e66f840cSTristram Ha case 3: 96*e66f840cSTristram Ha queue = PORT_QUEUE_SPLIT_4; 97*e66f840cSTristram Ha break; 98*e66f840cSTristram Ha case 2: 99*e66f840cSTristram Ha queue = PORT_QUEUE_SPLIT_2; 100*e66f840cSTristram Ha break; 101*e66f840cSTristram Ha default: 102*e66f840cSTristram Ha queue = PORT_QUEUE_SPLIT_1; 103*e66f840cSTristram Ha } 104*e66f840cSTristram Ha ksz_pread8(dev, port, REG_PORT_CTRL_0, &lo); 105*e66f840cSTristram Ha ksz_pread8(dev, port, P_DROP_TAG_CTRL, &hi); 106*e66f840cSTristram Ha lo &= ~PORT_QUEUE_SPLIT_L; 107*e66f840cSTristram Ha if (queue & PORT_QUEUE_SPLIT_2) 108*e66f840cSTristram Ha lo |= PORT_QUEUE_SPLIT_L; 109*e66f840cSTristram Ha hi &= ~PORT_QUEUE_SPLIT_H; 110*e66f840cSTristram Ha if (queue & PORT_QUEUE_SPLIT_4) 111*e66f840cSTristram Ha hi |= PORT_QUEUE_SPLIT_H; 112*e66f840cSTristram Ha ksz_pwrite8(dev, port, REG_PORT_CTRL_0, lo); 113*e66f840cSTristram Ha ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, hi); 114*e66f840cSTristram Ha 115*e66f840cSTristram Ha /* Default is port based for egress rate limit. */ 116*e66f840cSTristram Ha if (queue != PORT_QUEUE_SPLIT_1) 117*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED, 118*e66f840cSTristram Ha true); 119*e66f840cSTristram Ha } 120*e66f840cSTristram Ha 121*e66f840cSTristram Ha static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, 122*e66f840cSTristram Ha u64 *cnt) 123*e66f840cSTristram Ha { 124*e66f840cSTristram Ha u16 ctrl_addr; 125*e66f840cSTristram Ha u32 data; 126*e66f840cSTristram Ha u8 check; 127*e66f840cSTristram Ha int loop; 128*e66f840cSTristram Ha 129*e66f840cSTristram Ha ctrl_addr = addr + SWITCH_COUNTER_NUM * port; 130*e66f840cSTristram Ha ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); 131*e66f840cSTristram Ha 132*e66f840cSTristram Ha mutex_lock(&dev->alu_mutex); 133*e66f840cSTristram Ha ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); 134*e66f840cSTristram Ha 135*e66f840cSTristram Ha /* It is almost guaranteed to always read the valid bit because of 136*e66f840cSTristram Ha * slow SPI speed. 137*e66f840cSTristram Ha */ 138*e66f840cSTristram Ha for (loop = 2; loop > 0; loop--) { 139*e66f840cSTristram Ha ksz_read8(dev, REG_IND_MIB_CHECK, &check); 140*e66f840cSTristram Ha 141*e66f840cSTristram Ha if (check & MIB_COUNTER_VALID) { 142*e66f840cSTristram Ha ksz_read32(dev, REG_IND_DATA_LO, &data); 143*e66f840cSTristram Ha if (check & MIB_COUNTER_OVERFLOW) 144*e66f840cSTristram Ha *cnt += MIB_COUNTER_VALUE + 1; 145*e66f840cSTristram Ha *cnt += data & MIB_COUNTER_VALUE; 146*e66f840cSTristram Ha break; 147*e66f840cSTristram Ha } 148*e66f840cSTristram Ha } 149*e66f840cSTristram Ha mutex_unlock(&dev->alu_mutex); 150*e66f840cSTristram Ha } 151*e66f840cSTristram Ha 152*e66f840cSTristram Ha static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, 153*e66f840cSTristram Ha u64 *dropped, u64 *cnt) 154*e66f840cSTristram Ha { 155*e66f840cSTristram Ha u16 ctrl_addr; 156*e66f840cSTristram Ha u32 data; 157*e66f840cSTristram Ha u8 check; 158*e66f840cSTristram Ha int loop; 159*e66f840cSTristram Ha 160*e66f840cSTristram Ha addr -= SWITCH_COUNTER_NUM; 161*e66f840cSTristram Ha ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port; 162*e66f840cSTristram Ha ctrl_addr += addr + KS_MIB_TOTAL_RX_0; 163*e66f840cSTristram Ha ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); 164*e66f840cSTristram Ha 165*e66f840cSTristram Ha mutex_lock(&dev->alu_mutex); 166*e66f840cSTristram Ha ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); 167*e66f840cSTristram Ha 168*e66f840cSTristram Ha /* It is almost guaranteed to always read the valid bit because of 169*e66f840cSTristram Ha * slow SPI speed. 170*e66f840cSTristram Ha */ 171*e66f840cSTristram Ha for (loop = 2; loop > 0; loop--) { 172*e66f840cSTristram Ha ksz_read8(dev, REG_IND_MIB_CHECK, &check); 173*e66f840cSTristram Ha 174*e66f840cSTristram Ha if (check & MIB_COUNTER_VALID) { 175*e66f840cSTristram Ha ksz_read32(dev, REG_IND_DATA_LO, &data); 176*e66f840cSTristram Ha if (addr < 2) { 177*e66f840cSTristram Ha u64 total; 178*e66f840cSTristram Ha 179*e66f840cSTristram Ha total = check & MIB_TOTAL_BYTES_H; 180*e66f840cSTristram Ha total <<= 32; 181*e66f840cSTristram Ha *cnt += total; 182*e66f840cSTristram Ha *cnt += data; 183*e66f840cSTristram Ha if (check & MIB_COUNTER_OVERFLOW) { 184*e66f840cSTristram Ha total = MIB_TOTAL_BYTES_H + 1; 185*e66f840cSTristram Ha total <<= 32; 186*e66f840cSTristram Ha *cnt += total; 187*e66f840cSTristram Ha } 188*e66f840cSTristram Ha } else { 189*e66f840cSTristram Ha if (check & MIB_COUNTER_OVERFLOW) 190*e66f840cSTristram Ha *cnt += MIB_PACKET_DROPPED + 1; 191*e66f840cSTristram Ha *cnt += data & MIB_PACKET_DROPPED; 192*e66f840cSTristram Ha } 193*e66f840cSTristram Ha break; 194*e66f840cSTristram Ha } 195*e66f840cSTristram Ha } 196*e66f840cSTristram Ha mutex_unlock(&dev->alu_mutex); 197*e66f840cSTristram Ha } 198*e66f840cSTristram Ha 199*e66f840cSTristram Ha static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze) 200*e66f840cSTristram Ha { 201*e66f840cSTristram Ha /* enable the port for flush/freeze function */ 202*e66f840cSTristram Ha if (freeze) 203*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); 204*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FREEZE, freeze); 205*e66f840cSTristram Ha 206*e66f840cSTristram Ha /* disable the port after freeze is done */ 207*e66f840cSTristram Ha if (!freeze) 208*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); 209*e66f840cSTristram Ha } 210*e66f840cSTristram Ha 211*e66f840cSTristram Ha static void ksz8795_port_init_cnt(struct ksz_device *dev, int port) 212*e66f840cSTristram Ha { 213*e66f840cSTristram Ha struct ksz_port_mib *mib = &dev->ports[port].mib; 214*e66f840cSTristram Ha 215*e66f840cSTristram Ha /* flush all enabled port MIB counters */ 216*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); 217*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true); 218*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); 219*e66f840cSTristram Ha 220*e66f840cSTristram Ha mib->cnt_ptr = 0; 221*e66f840cSTristram Ha 222*e66f840cSTristram Ha /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ 223*e66f840cSTristram Ha while (mib->cnt_ptr < dev->reg_mib_cnt) { 224*e66f840cSTristram Ha dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, 225*e66f840cSTristram Ha &mib->counters[mib->cnt_ptr]); 226*e66f840cSTristram Ha ++mib->cnt_ptr; 227*e66f840cSTristram Ha } 228*e66f840cSTristram Ha 229*e66f840cSTristram Ha /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ 230*e66f840cSTristram Ha while (mib->cnt_ptr < dev->mib_cnt) { 231*e66f840cSTristram Ha dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, 232*e66f840cSTristram Ha NULL, &mib->counters[mib->cnt_ptr]); 233*e66f840cSTristram Ha ++mib->cnt_ptr; 234*e66f840cSTristram Ha } 235*e66f840cSTristram Ha mib->cnt_ptr = 0; 236*e66f840cSTristram Ha memset(mib->counters, 0, dev->mib_cnt * sizeof(u64)); 237*e66f840cSTristram Ha } 238*e66f840cSTristram Ha 239*e66f840cSTristram Ha static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr, 240*e66f840cSTristram Ha u64 *data) 241*e66f840cSTristram Ha { 242*e66f840cSTristram Ha u16 ctrl_addr; 243*e66f840cSTristram Ha 244*e66f840cSTristram Ha ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr; 245*e66f840cSTristram Ha 246*e66f840cSTristram Ha mutex_lock(&dev->alu_mutex); 247*e66f840cSTristram Ha ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); 248*e66f840cSTristram Ha ksz_read64(dev, REG_IND_DATA_HI, data); 249*e66f840cSTristram Ha mutex_unlock(&dev->alu_mutex); 250*e66f840cSTristram Ha } 251*e66f840cSTristram Ha 252*e66f840cSTristram Ha static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr, 253*e66f840cSTristram Ha u64 data) 254*e66f840cSTristram Ha { 255*e66f840cSTristram Ha u16 ctrl_addr; 256*e66f840cSTristram Ha 257*e66f840cSTristram Ha ctrl_addr = IND_ACC_TABLE(table) | addr; 258*e66f840cSTristram Ha 259*e66f840cSTristram Ha mutex_lock(&dev->alu_mutex); 260*e66f840cSTristram Ha ksz_write64(dev, REG_IND_DATA_HI, data); 261*e66f840cSTristram Ha ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); 262*e66f840cSTristram Ha mutex_unlock(&dev->alu_mutex); 263*e66f840cSTristram Ha } 264*e66f840cSTristram Ha 265*e66f840cSTristram Ha static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data) 266*e66f840cSTristram Ha { 267*e66f840cSTristram Ha int timeout = 100; 268*e66f840cSTristram Ha 269*e66f840cSTristram Ha do { 270*e66f840cSTristram Ha ksz_read8(dev, REG_IND_DATA_CHECK, data); 271*e66f840cSTristram Ha timeout--; 272*e66f840cSTristram Ha } while ((*data & DYNAMIC_MAC_TABLE_NOT_READY) && timeout); 273*e66f840cSTristram Ha 274*e66f840cSTristram Ha /* Entry is not ready for accessing. */ 275*e66f840cSTristram Ha if (*data & DYNAMIC_MAC_TABLE_NOT_READY) { 276*e66f840cSTristram Ha return -EAGAIN; 277*e66f840cSTristram Ha /* Entry is ready for accessing. */ 278*e66f840cSTristram Ha } else { 279*e66f840cSTristram Ha ksz_read8(dev, REG_IND_DATA_8, data); 280*e66f840cSTristram Ha 281*e66f840cSTristram Ha /* There is no valid entry in the table. */ 282*e66f840cSTristram Ha if (*data & DYNAMIC_MAC_TABLE_MAC_EMPTY) 283*e66f840cSTristram Ha return -ENXIO; 284*e66f840cSTristram Ha } 285*e66f840cSTristram Ha return 0; 286*e66f840cSTristram Ha } 287*e66f840cSTristram Ha 288*e66f840cSTristram Ha static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr, 289*e66f840cSTristram Ha u8 *mac_addr, u8 *fid, u8 *src_port, 290*e66f840cSTristram Ha u8 *timestamp, u16 *entries) 291*e66f840cSTristram Ha { 292*e66f840cSTristram Ha u32 data_hi, data_lo; 293*e66f840cSTristram Ha u16 ctrl_addr; 294*e66f840cSTristram Ha u8 data; 295*e66f840cSTristram Ha int rc; 296*e66f840cSTristram Ha 297*e66f840cSTristram Ha ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr; 298*e66f840cSTristram Ha 299*e66f840cSTristram Ha mutex_lock(&dev->alu_mutex); 300*e66f840cSTristram Ha ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); 301*e66f840cSTristram Ha 302*e66f840cSTristram Ha rc = ksz8795_valid_dyn_entry(dev, &data); 303*e66f840cSTristram Ha if (rc == -EAGAIN) { 304*e66f840cSTristram Ha if (addr == 0) 305*e66f840cSTristram Ha *entries = 0; 306*e66f840cSTristram Ha } else if (rc == -ENXIO) { 307*e66f840cSTristram Ha *entries = 0; 308*e66f840cSTristram Ha /* At least one valid entry in the table. */ 309*e66f840cSTristram Ha } else { 310*e66f840cSTristram Ha u64 buf = 0; 311*e66f840cSTristram Ha int cnt; 312*e66f840cSTristram Ha 313*e66f840cSTristram Ha ksz_read64(dev, REG_IND_DATA_HI, &buf); 314*e66f840cSTristram Ha data_hi = (u32)(buf >> 32); 315*e66f840cSTristram Ha data_lo = (u32)buf; 316*e66f840cSTristram Ha 317*e66f840cSTristram Ha /* Check out how many valid entry in the table. */ 318*e66f840cSTristram Ha cnt = data & DYNAMIC_MAC_TABLE_ENTRIES_H; 319*e66f840cSTristram Ha cnt <<= DYNAMIC_MAC_ENTRIES_H_S; 320*e66f840cSTristram Ha cnt |= (data_hi & DYNAMIC_MAC_TABLE_ENTRIES) >> 321*e66f840cSTristram Ha DYNAMIC_MAC_ENTRIES_S; 322*e66f840cSTristram Ha *entries = cnt + 1; 323*e66f840cSTristram Ha 324*e66f840cSTristram Ha *fid = (data_hi & DYNAMIC_MAC_TABLE_FID) >> 325*e66f840cSTristram Ha DYNAMIC_MAC_FID_S; 326*e66f840cSTristram Ha *src_port = (data_hi & DYNAMIC_MAC_TABLE_SRC_PORT) >> 327*e66f840cSTristram Ha DYNAMIC_MAC_SRC_PORT_S; 328*e66f840cSTristram Ha *timestamp = (data_hi & DYNAMIC_MAC_TABLE_TIMESTAMP) >> 329*e66f840cSTristram Ha DYNAMIC_MAC_TIMESTAMP_S; 330*e66f840cSTristram Ha 331*e66f840cSTristram Ha mac_addr[5] = (u8)data_lo; 332*e66f840cSTristram Ha mac_addr[4] = (u8)(data_lo >> 8); 333*e66f840cSTristram Ha mac_addr[3] = (u8)(data_lo >> 16); 334*e66f840cSTristram Ha mac_addr[2] = (u8)(data_lo >> 24); 335*e66f840cSTristram Ha 336*e66f840cSTristram Ha mac_addr[1] = (u8)data_hi; 337*e66f840cSTristram Ha mac_addr[0] = (u8)(data_hi >> 8); 338*e66f840cSTristram Ha rc = 0; 339*e66f840cSTristram Ha } 340*e66f840cSTristram Ha mutex_unlock(&dev->alu_mutex); 341*e66f840cSTristram Ha 342*e66f840cSTristram Ha return rc; 343*e66f840cSTristram Ha } 344*e66f840cSTristram Ha 345*e66f840cSTristram Ha static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr, 346*e66f840cSTristram Ha struct alu_struct *alu) 347*e66f840cSTristram Ha { 348*e66f840cSTristram Ha u32 data_hi, data_lo; 349*e66f840cSTristram Ha u64 data; 350*e66f840cSTristram Ha 351*e66f840cSTristram Ha ksz8795_r_table(dev, TABLE_STATIC_MAC, addr, &data); 352*e66f840cSTristram Ha data_hi = data >> 32; 353*e66f840cSTristram Ha data_lo = (u32)data; 354*e66f840cSTristram Ha if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) { 355*e66f840cSTristram Ha alu->mac[5] = (u8)data_lo; 356*e66f840cSTristram Ha alu->mac[4] = (u8)(data_lo >> 8); 357*e66f840cSTristram Ha alu->mac[3] = (u8)(data_lo >> 16); 358*e66f840cSTristram Ha alu->mac[2] = (u8)(data_lo >> 24); 359*e66f840cSTristram Ha alu->mac[1] = (u8)data_hi; 360*e66f840cSTristram Ha alu->mac[0] = (u8)(data_hi >> 8); 361*e66f840cSTristram Ha alu->port_forward = (data_hi & STATIC_MAC_TABLE_FWD_PORTS) >> 362*e66f840cSTristram Ha STATIC_MAC_FWD_PORTS_S; 363*e66f840cSTristram Ha alu->is_override = 364*e66f840cSTristram Ha (data_hi & STATIC_MAC_TABLE_OVERRIDE) ? 1 : 0; 365*e66f840cSTristram Ha data_hi >>= 1; 366*e66f840cSTristram Ha alu->is_use_fid = (data_hi & STATIC_MAC_TABLE_USE_FID) ? 1 : 0; 367*e66f840cSTristram Ha alu->fid = (data_hi & STATIC_MAC_TABLE_FID) >> 368*e66f840cSTristram Ha STATIC_MAC_FID_S; 369*e66f840cSTristram Ha return 0; 370*e66f840cSTristram Ha } 371*e66f840cSTristram Ha return -ENXIO; 372*e66f840cSTristram Ha } 373*e66f840cSTristram Ha 374*e66f840cSTristram Ha static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr, 375*e66f840cSTristram Ha struct alu_struct *alu) 376*e66f840cSTristram Ha { 377*e66f840cSTristram Ha u32 data_hi, data_lo; 378*e66f840cSTristram Ha u64 data; 379*e66f840cSTristram Ha 380*e66f840cSTristram Ha data_lo = ((u32)alu->mac[2] << 24) | 381*e66f840cSTristram Ha ((u32)alu->mac[3] << 16) | 382*e66f840cSTristram Ha ((u32)alu->mac[4] << 8) | alu->mac[5]; 383*e66f840cSTristram Ha data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1]; 384*e66f840cSTristram Ha data_hi |= (u32)alu->port_forward << STATIC_MAC_FWD_PORTS_S; 385*e66f840cSTristram Ha 386*e66f840cSTristram Ha if (alu->is_override) 387*e66f840cSTristram Ha data_hi |= STATIC_MAC_TABLE_OVERRIDE; 388*e66f840cSTristram Ha if (alu->is_use_fid) { 389*e66f840cSTristram Ha data_hi |= STATIC_MAC_TABLE_USE_FID; 390*e66f840cSTristram Ha data_hi |= (u32)alu->fid << STATIC_MAC_FID_S; 391*e66f840cSTristram Ha } 392*e66f840cSTristram Ha if (alu->is_static) 393*e66f840cSTristram Ha data_hi |= STATIC_MAC_TABLE_VALID; 394*e66f840cSTristram Ha else 395*e66f840cSTristram Ha data_hi &= ~STATIC_MAC_TABLE_OVERRIDE; 396*e66f840cSTristram Ha 397*e66f840cSTristram Ha data = (u64)data_hi << 32 | data_lo; 398*e66f840cSTristram Ha ksz8795_w_table(dev, TABLE_STATIC_MAC, addr, data); 399*e66f840cSTristram Ha } 400*e66f840cSTristram Ha 401*e66f840cSTristram Ha static void ksz8795_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid) 402*e66f840cSTristram Ha { 403*e66f840cSTristram Ha *fid = vlan & VLAN_TABLE_FID; 404*e66f840cSTristram Ha *member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S; 405*e66f840cSTristram Ha *valid = !!(vlan & VLAN_TABLE_VALID); 406*e66f840cSTristram Ha } 407*e66f840cSTristram Ha 408*e66f840cSTristram Ha static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) 409*e66f840cSTristram Ha { 410*e66f840cSTristram Ha *vlan = fid; 411*e66f840cSTristram Ha *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S; 412*e66f840cSTristram Ha if (valid) 413*e66f840cSTristram Ha *vlan |= VLAN_TABLE_VALID; 414*e66f840cSTristram Ha } 415*e66f840cSTristram Ha 416*e66f840cSTristram Ha static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr) 417*e66f840cSTristram Ha { 418*e66f840cSTristram Ha u64 data; 419*e66f840cSTristram Ha int i; 420*e66f840cSTristram Ha 421*e66f840cSTristram Ha ksz8795_r_table(dev, TABLE_VLAN, addr, &data); 422*e66f840cSTristram Ha addr *= 4; 423*e66f840cSTristram Ha for (i = 0; i < 4; i++) { 424*e66f840cSTristram Ha dev->vlan_cache[addr + i].table[0] = (u16)data; 425*e66f840cSTristram Ha data >>= VLAN_TABLE_S; 426*e66f840cSTristram Ha } 427*e66f840cSTristram Ha } 428*e66f840cSTristram Ha 429*e66f840cSTristram Ha static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) 430*e66f840cSTristram Ha { 431*e66f840cSTristram Ha int index; 432*e66f840cSTristram Ha u16 *data; 433*e66f840cSTristram Ha u16 addr; 434*e66f840cSTristram Ha u64 buf; 435*e66f840cSTristram Ha 436*e66f840cSTristram Ha data = (u16 *)&buf; 437*e66f840cSTristram Ha addr = vid / 4; 438*e66f840cSTristram Ha index = vid & 3; 439*e66f840cSTristram Ha ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); 440*e66f840cSTristram Ha *vlan = data[index]; 441*e66f840cSTristram Ha } 442*e66f840cSTristram Ha 443*e66f840cSTristram Ha static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) 444*e66f840cSTristram Ha { 445*e66f840cSTristram Ha int index; 446*e66f840cSTristram Ha u16 *data; 447*e66f840cSTristram Ha u16 addr; 448*e66f840cSTristram Ha u64 buf; 449*e66f840cSTristram Ha 450*e66f840cSTristram Ha data = (u16 *)&buf; 451*e66f840cSTristram Ha addr = vid / 4; 452*e66f840cSTristram Ha index = vid & 3; 453*e66f840cSTristram Ha ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); 454*e66f840cSTristram Ha data[index] = vlan; 455*e66f840cSTristram Ha dev->vlan_cache[vid].table[0] = vlan; 456*e66f840cSTristram Ha ksz8795_w_table(dev, TABLE_VLAN, addr, buf); 457*e66f840cSTristram Ha } 458*e66f840cSTristram Ha 459*e66f840cSTristram Ha static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) 460*e66f840cSTristram Ha { 461*e66f840cSTristram Ha u8 restart, speed, ctrl, link; 462*e66f840cSTristram Ha int processed = true; 463*e66f840cSTristram Ha u16 data = 0; 464*e66f840cSTristram Ha u8 p = phy; 465*e66f840cSTristram Ha 466*e66f840cSTristram Ha switch (reg) { 467*e66f840cSTristram Ha case PHY_REG_CTRL: 468*e66f840cSTristram Ha ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); 469*e66f840cSTristram Ha ksz_pread8(dev, p, P_SPEED_STATUS, &speed); 470*e66f840cSTristram Ha ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); 471*e66f840cSTristram Ha if (restart & PORT_PHY_LOOPBACK) 472*e66f840cSTristram Ha data |= PHY_LOOPBACK; 473*e66f840cSTristram Ha if (ctrl & PORT_FORCE_100_MBIT) 474*e66f840cSTristram Ha data |= PHY_SPEED_100MBIT; 475*e66f840cSTristram Ha if (!(ctrl & PORT_AUTO_NEG_DISABLE)) 476*e66f840cSTristram Ha data |= PHY_AUTO_NEG_ENABLE; 477*e66f840cSTristram Ha if (restart & PORT_POWER_DOWN) 478*e66f840cSTristram Ha data |= PHY_POWER_DOWN; 479*e66f840cSTristram Ha if (restart & PORT_AUTO_NEG_RESTART) 480*e66f840cSTristram Ha data |= PHY_AUTO_NEG_RESTART; 481*e66f840cSTristram Ha if (ctrl & PORT_FORCE_FULL_DUPLEX) 482*e66f840cSTristram Ha data |= PHY_FULL_DUPLEX; 483*e66f840cSTristram Ha if (speed & PORT_HP_MDIX) 484*e66f840cSTristram Ha data |= PHY_HP_MDIX; 485*e66f840cSTristram Ha if (restart & PORT_FORCE_MDIX) 486*e66f840cSTristram Ha data |= PHY_FORCE_MDIX; 487*e66f840cSTristram Ha if (restart & PORT_AUTO_MDIX_DISABLE) 488*e66f840cSTristram Ha data |= PHY_AUTO_MDIX_DISABLE; 489*e66f840cSTristram Ha if (restart & PORT_TX_DISABLE) 490*e66f840cSTristram Ha data |= PHY_TRANSMIT_DISABLE; 491*e66f840cSTristram Ha if (restart & PORT_LED_OFF) 492*e66f840cSTristram Ha data |= PHY_LED_DISABLE; 493*e66f840cSTristram Ha break; 494*e66f840cSTristram Ha case PHY_REG_STATUS: 495*e66f840cSTristram Ha ksz_pread8(dev, p, P_LINK_STATUS, &link); 496*e66f840cSTristram Ha data = PHY_100BTX_FD_CAPABLE | 497*e66f840cSTristram Ha PHY_100BTX_CAPABLE | 498*e66f840cSTristram Ha PHY_10BT_FD_CAPABLE | 499*e66f840cSTristram Ha PHY_10BT_CAPABLE | 500*e66f840cSTristram Ha PHY_AUTO_NEG_CAPABLE; 501*e66f840cSTristram Ha if (link & PORT_AUTO_NEG_COMPLETE) 502*e66f840cSTristram Ha data |= PHY_AUTO_NEG_ACKNOWLEDGE; 503*e66f840cSTristram Ha if (link & PORT_STAT_LINK_GOOD) 504*e66f840cSTristram Ha data |= PHY_LINK_STATUS; 505*e66f840cSTristram Ha break; 506*e66f840cSTristram Ha case PHY_REG_ID_1: 507*e66f840cSTristram Ha data = KSZ8795_ID_HI; 508*e66f840cSTristram Ha break; 509*e66f840cSTristram Ha case PHY_REG_ID_2: 510*e66f840cSTristram Ha data = KSZ8795_ID_LO; 511*e66f840cSTristram Ha break; 512*e66f840cSTristram Ha case PHY_REG_AUTO_NEGOTIATION: 513*e66f840cSTristram Ha ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); 514*e66f840cSTristram Ha data = PHY_AUTO_NEG_802_3; 515*e66f840cSTristram Ha if (ctrl & PORT_AUTO_NEG_SYM_PAUSE) 516*e66f840cSTristram Ha data |= PHY_AUTO_NEG_SYM_PAUSE; 517*e66f840cSTristram Ha if (ctrl & PORT_AUTO_NEG_100BTX_FD) 518*e66f840cSTristram Ha data |= PHY_AUTO_NEG_100BTX_FD; 519*e66f840cSTristram Ha if (ctrl & PORT_AUTO_NEG_100BTX) 520*e66f840cSTristram Ha data |= PHY_AUTO_NEG_100BTX; 521*e66f840cSTristram Ha if (ctrl & PORT_AUTO_NEG_10BT_FD) 522*e66f840cSTristram Ha data |= PHY_AUTO_NEG_10BT_FD; 523*e66f840cSTristram Ha if (ctrl & PORT_AUTO_NEG_10BT) 524*e66f840cSTristram Ha data |= PHY_AUTO_NEG_10BT; 525*e66f840cSTristram Ha break; 526*e66f840cSTristram Ha case PHY_REG_REMOTE_CAPABILITY: 527*e66f840cSTristram Ha ksz_pread8(dev, p, P_REMOTE_STATUS, &link); 528*e66f840cSTristram Ha data = PHY_AUTO_NEG_802_3; 529*e66f840cSTristram Ha if (link & PORT_REMOTE_SYM_PAUSE) 530*e66f840cSTristram Ha data |= PHY_AUTO_NEG_SYM_PAUSE; 531*e66f840cSTristram Ha if (link & PORT_REMOTE_100BTX_FD) 532*e66f840cSTristram Ha data |= PHY_AUTO_NEG_100BTX_FD; 533*e66f840cSTristram Ha if (link & PORT_REMOTE_100BTX) 534*e66f840cSTristram Ha data |= PHY_AUTO_NEG_100BTX; 535*e66f840cSTristram Ha if (link & PORT_REMOTE_10BT_FD) 536*e66f840cSTristram Ha data |= PHY_AUTO_NEG_10BT_FD; 537*e66f840cSTristram Ha if (link & PORT_REMOTE_10BT) 538*e66f840cSTristram Ha data |= PHY_AUTO_NEG_10BT; 539*e66f840cSTristram Ha if (data & ~PHY_AUTO_NEG_802_3) 540*e66f840cSTristram Ha data |= PHY_REMOTE_ACKNOWLEDGE_NOT; 541*e66f840cSTristram Ha break; 542*e66f840cSTristram Ha default: 543*e66f840cSTristram Ha processed = false; 544*e66f840cSTristram Ha break; 545*e66f840cSTristram Ha } 546*e66f840cSTristram Ha if (processed) 547*e66f840cSTristram Ha *val = data; 548*e66f840cSTristram Ha } 549*e66f840cSTristram Ha 550*e66f840cSTristram Ha static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) 551*e66f840cSTristram Ha { 552*e66f840cSTristram Ha u8 p = phy; 553*e66f840cSTristram Ha u8 restart, speed, ctrl, data; 554*e66f840cSTristram Ha 555*e66f840cSTristram Ha switch (reg) { 556*e66f840cSTristram Ha case PHY_REG_CTRL: 557*e66f840cSTristram Ha 558*e66f840cSTristram Ha /* Do not support PHY reset function. */ 559*e66f840cSTristram Ha if (val & PHY_RESET) 560*e66f840cSTristram Ha break; 561*e66f840cSTristram Ha ksz_pread8(dev, p, P_SPEED_STATUS, &speed); 562*e66f840cSTristram Ha data = speed; 563*e66f840cSTristram Ha if (val & PHY_HP_MDIX) 564*e66f840cSTristram Ha data |= PORT_HP_MDIX; 565*e66f840cSTristram Ha else 566*e66f840cSTristram Ha data &= ~PORT_HP_MDIX; 567*e66f840cSTristram Ha if (data != speed) 568*e66f840cSTristram Ha ksz_pwrite8(dev, p, P_SPEED_STATUS, data); 569*e66f840cSTristram Ha ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); 570*e66f840cSTristram Ha data = ctrl; 571*e66f840cSTristram Ha if (!(val & PHY_AUTO_NEG_ENABLE)) 572*e66f840cSTristram Ha data |= PORT_AUTO_NEG_DISABLE; 573*e66f840cSTristram Ha else 574*e66f840cSTristram Ha data &= ~PORT_AUTO_NEG_DISABLE; 575*e66f840cSTristram Ha 576*e66f840cSTristram Ha /* Fiber port does not support auto-negotiation. */ 577*e66f840cSTristram Ha if (dev->ports[p].fiber) 578*e66f840cSTristram Ha data |= PORT_AUTO_NEG_DISABLE; 579*e66f840cSTristram Ha if (val & PHY_SPEED_100MBIT) 580*e66f840cSTristram Ha data |= PORT_FORCE_100_MBIT; 581*e66f840cSTristram Ha else 582*e66f840cSTristram Ha data &= ~PORT_FORCE_100_MBIT; 583*e66f840cSTristram Ha if (val & PHY_FULL_DUPLEX) 584*e66f840cSTristram Ha data |= PORT_FORCE_FULL_DUPLEX; 585*e66f840cSTristram Ha else 586*e66f840cSTristram Ha data &= ~PORT_FORCE_FULL_DUPLEX; 587*e66f840cSTristram Ha if (data != ctrl) 588*e66f840cSTristram Ha ksz_pwrite8(dev, p, P_FORCE_CTRL, data); 589*e66f840cSTristram Ha ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); 590*e66f840cSTristram Ha data = restart; 591*e66f840cSTristram Ha if (val & PHY_LED_DISABLE) 592*e66f840cSTristram Ha data |= PORT_LED_OFF; 593*e66f840cSTristram Ha else 594*e66f840cSTristram Ha data &= ~PORT_LED_OFF; 595*e66f840cSTristram Ha if (val & PHY_TRANSMIT_DISABLE) 596*e66f840cSTristram Ha data |= PORT_TX_DISABLE; 597*e66f840cSTristram Ha else 598*e66f840cSTristram Ha data &= ~PORT_TX_DISABLE; 599*e66f840cSTristram Ha if (val & PHY_AUTO_NEG_RESTART) 600*e66f840cSTristram Ha data |= PORT_AUTO_NEG_RESTART; 601*e66f840cSTristram Ha else 602*e66f840cSTristram Ha data &= ~(PORT_AUTO_NEG_RESTART); 603*e66f840cSTristram Ha if (val & PHY_POWER_DOWN) 604*e66f840cSTristram Ha data |= PORT_POWER_DOWN; 605*e66f840cSTristram Ha else 606*e66f840cSTristram Ha data &= ~PORT_POWER_DOWN; 607*e66f840cSTristram Ha if (val & PHY_AUTO_MDIX_DISABLE) 608*e66f840cSTristram Ha data |= PORT_AUTO_MDIX_DISABLE; 609*e66f840cSTristram Ha else 610*e66f840cSTristram Ha data &= ~PORT_AUTO_MDIX_DISABLE; 611*e66f840cSTristram Ha if (val & PHY_FORCE_MDIX) 612*e66f840cSTristram Ha data |= PORT_FORCE_MDIX; 613*e66f840cSTristram Ha else 614*e66f840cSTristram Ha data &= ~PORT_FORCE_MDIX; 615*e66f840cSTristram Ha if (val & PHY_LOOPBACK) 616*e66f840cSTristram Ha data |= PORT_PHY_LOOPBACK; 617*e66f840cSTristram Ha else 618*e66f840cSTristram Ha data &= ~PORT_PHY_LOOPBACK; 619*e66f840cSTristram Ha if (data != restart) 620*e66f840cSTristram Ha ksz_pwrite8(dev, p, P_NEG_RESTART_CTRL, data); 621*e66f840cSTristram Ha break; 622*e66f840cSTristram Ha case PHY_REG_AUTO_NEGOTIATION: 623*e66f840cSTristram Ha ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); 624*e66f840cSTristram Ha data = ctrl; 625*e66f840cSTristram Ha data &= ~(PORT_AUTO_NEG_SYM_PAUSE | 626*e66f840cSTristram Ha PORT_AUTO_NEG_100BTX_FD | 627*e66f840cSTristram Ha PORT_AUTO_NEG_100BTX | 628*e66f840cSTristram Ha PORT_AUTO_NEG_10BT_FD | 629*e66f840cSTristram Ha PORT_AUTO_NEG_10BT); 630*e66f840cSTristram Ha if (val & PHY_AUTO_NEG_SYM_PAUSE) 631*e66f840cSTristram Ha data |= PORT_AUTO_NEG_SYM_PAUSE; 632*e66f840cSTristram Ha if (val & PHY_AUTO_NEG_100BTX_FD) 633*e66f840cSTristram Ha data |= PORT_AUTO_NEG_100BTX_FD; 634*e66f840cSTristram Ha if (val & PHY_AUTO_NEG_100BTX) 635*e66f840cSTristram Ha data |= PORT_AUTO_NEG_100BTX; 636*e66f840cSTristram Ha if (val & PHY_AUTO_NEG_10BT_FD) 637*e66f840cSTristram Ha data |= PORT_AUTO_NEG_10BT_FD; 638*e66f840cSTristram Ha if (val & PHY_AUTO_NEG_10BT) 639*e66f840cSTristram Ha data |= PORT_AUTO_NEG_10BT; 640*e66f840cSTristram Ha if (data != ctrl) 641*e66f840cSTristram Ha ksz_pwrite8(dev, p, P_LOCAL_CTRL, data); 642*e66f840cSTristram Ha break; 643*e66f840cSTristram Ha default: 644*e66f840cSTristram Ha break; 645*e66f840cSTristram Ha } 646*e66f840cSTristram Ha } 647*e66f840cSTristram Ha 648*e66f840cSTristram Ha static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds, 649*e66f840cSTristram Ha int port) 650*e66f840cSTristram Ha { 651*e66f840cSTristram Ha return DSA_TAG_PROTO_KSZ8795; 652*e66f840cSTristram Ha } 653*e66f840cSTristram Ha 654*e66f840cSTristram Ha static void ksz8795_get_strings(struct dsa_switch *ds, int port, 655*e66f840cSTristram Ha u32 stringset, uint8_t *buf) 656*e66f840cSTristram Ha { 657*e66f840cSTristram Ha int i; 658*e66f840cSTristram Ha 659*e66f840cSTristram Ha for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) { 660*e66f840cSTristram Ha memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string, 661*e66f840cSTristram Ha ETH_GSTRING_LEN); 662*e66f840cSTristram Ha } 663*e66f840cSTristram Ha } 664*e66f840cSTristram Ha 665*e66f840cSTristram Ha static void ksz8795_cfg_port_member(struct ksz_device *dev, int port, 666*e66f840cSTristram Ha u8 member) 667*e66f840cSTristram Ha { 668*e66f840cSTristram Ha u8 data; 669*e66f840cSTristram Ha 670*e66f840cSTristram Ha ksz_pread8(dev, port, P_MIRROR_CTRL, &data); 671*e66f840cSTristram Ha data &= ~PORT_VLAN_MEMBERSHIP; 672*e66f840cSTristram Ha data |= (member & dev->port_mask); 673*e66f840cSTristram Ha ksz_pwrite8(dev, port, P_MIRROR_CTRL, data); 674*e66f840cSTristram Ha dev->ports[port].member = member; 675*e66f840cSTristram Ha } 676*e66f840cSTristram Ha 677*e66f840cSTristram Ha static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port, 678*e66f840cSTristram Ha u8 state) 679*e66f840cSTristram Ha { 680*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 681*e66f840cSTristram Ha int forward = dev->member; 682*e66f840cSTristram Ha struct ksz_port *p; 683*e66f840cSTristram Ha int member = -1; 684*e66f840cSTristram Ha u8 data; 685*e66f840cSTristram Ha 686*e66f840cSTristram Ha p = &dev->ports[port]; 687*e66f840cSTristram Ha 688*e66f840cSTristram Ha ksz_pread8(dev, port, P_STP_CTRL, &data); 689*e66f840cSTristram Ha data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); 690*e66f840cSTristram Ha 691*e66f840cSTristram Ha switch (state) { 692*e66f840cSTristram Ha case BR_STATE_DISABLED: 693*e66f840cSTristram Ha data |= PORT_LEARN_DISABLE; 694*e66f840cSTristram Ha if (port < SWITCH_PORT_NUM) 695*e66f840cSTristram Ha member = 0; 696*e66f840cSTristram Ha break; 697*e66f840cSTristram Ha case BR_STATE_LISTENING: 698*e66f840cSTristram Ha data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); 699*e66f840cSTristram Ha if (port < SWITCH_PORT_NUM && 700*e66f840cSTristram Ha p->stp_state == BR_STATE_DISABLED) 701*e66f840cSTristram Ha member = dev->host_mask | p->vid_member; 702*e66f840cSTristram Ha break; 703*e66f840cSTristram Ha case BR_STATE_LEARNING: 704*e66f840cSTristram Ha data |= PORT_RX_ENABLE; 705*e66f840cSTristram Ha break; 706*e66f840cSTristram Ha case BR_STATE_FORWARDING: 707*e66f840cSTristram Ha data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); 708*e66f840cSTristram Ha 709*e66f840cSTristram Ha /* This function is also used internally. */ 710*e66f840cSTristram Ha if (port == dev->cpu_port) 711*e66f840cSTristram Ha break; 712*e66f840cSTristram Ha 713*e66f840cSTristram Ha /* Port is a member of a bridge. */ 714*e66f840cSTristram Ha if (dev->br_member & BIT(port)) { 715*e66f840cSTristram Ha dev->member |= BIT(port); 716*e66f840cSTristram Ha member = dev->member; 717*e66f840cSTristram Ha } else { 718*e66f840cSTristram Ha member = dev->host_mask | p->vid_member; 719*e66f840cSTristram Ha } 720*e66f840cSTristram Ha break; 721*e66f840cSTristram Ha case BR_STATE_BLOCKING: 722*e66f840cSTristram Ha data |= PORT_LEARN_DISABLE; 723*e66f840cSTristram Ha if (port < SWITCH_PORT_NUM && 724*e66f840cSTristram Ha p->stp_state == BR_STATE_DISABLED) 725*e66f840cSTristram Ha member = dev->host_mask | p->vid_member; 726*e66f840cSTristram Ha break; 727*e66f840cSTristram Ha default: 728*e66f840cSTristram Ha dev_err(ds->dev, "invalid STP state: %d\n", state); 729*e66f840cSTristram Ha return; 730*e66f840cSTristram Ha } 731*e66f840cSTristram Ha 732*e66f840cSTristram Ha ksz_pwrite8(dev, port, P_STP_CTRL, data); 733*e66f840cSTristram Ha p->stp_state = state; 734*e66f840cSTristram Ha if (data & PORT_RX_ENABLE) 735*e66f840cSTristram Ha dev->rx_ports |= BIT(port); 736*e66f840cSTristram Ha else 737*e66f840cSTristram Ha dev->rx_ports &= ~BIT(port); 738*e66f840cSTristram Ha if (data & PORT_TX_ENABLE) 739*e66f840cSTristram Ha dev->tx_ports |= BIT(port); 740*e66f840cSTristram Ha else 741*e66f840cSTristram Ha dev->tx_ports &= ~BIT(port); 742*e66f840cSTristram Ha 743*e66f840cSTristram Ha /* Port membership may share register with STP state. */ 744*e66f840cSTristram Ha if (member >= 0 && member != p->member) 745*e66f840cSTristram Ha ksz8795_cfg_port_member(dev, port, (u8)member); 746*e66f840cSTristram Ha 747*e66f840cSTristram Ha /* Check if forwarding needs to be updated. */ 748*e66f840cSTristram Ha if (state != BR_STATE_FORWARDING) { 749*e66f840cSTristram Ha if (dev->br_member & BIT(port)) 750*e66f840cSTristram Ha dev->member &= ~BIT(port); 751*e66f840cSTristram Ha } 752*e66f840cSTristram Ha 753*e66f840cSTristram Ha /* When topology has changed the function ksz_update_port_member 754*e66f840cSTristram Ha * should be called to modify port forwarding behavior. 755*e66f840cSTristram Ha */ 756*e66f840cSTristram Ha if (forward != dev->member) 757*e66f840cSTristram Ha ksz_update_port_member(dev, port); 758*e66f840cSTristram Ha } 759*e66f840cSTristram Ha 760*e66f840cSTristram Ha static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port) 761*e66f840cSTristram Ha { 762*e66f840cSTristram Ha u8 learn[TOTAL_PORT_NUM]; 763*e66f840cSTristram Ha int first, index, cnt; 764*e66f840cSTristram Ha struct ksz_port *p; 765*e66f840cSTristram Ha 766*e66f840cSTristram Ha if ((uint)port < TOTAL_PORT_NUM) { 767*e66f840cSTristram Ha first = port; 768*e66f840cSTristram Ha cnt = port + 1; 769*e66f840cSTristram Ha } else { 770*e66f840cSTristram Ha /* Flush all ports. */ 771*e66f840cSTristram Ha first = 0; 772*e66f840cSTristram Ha cnt = dev->mib_port_cnt; 773*e66f840cSTristram Ha } 774*e66f840cSTristram Ha for (index = first; index < cnt; index++) { 775*e66f840cSTristram Ha p = &dev->ports[index]; 776*e66f840cSTristram Ha if (!p->on) 777*e66f840cSTristram Ha continue; 778*e66f840cSTristram Ha ksz_pread8(dev, index, P_STP_CTRL, &learn[index]); 779*e66f840cSTristram Ha if (!(learn[index] & PORT_LEARN_DISABLE)) 780*e66f840cSTristram Ha ksz_pwrite8(dev, index, P_STP_CTRL, 781*e66f840cSTristram Ha learn[index] | PORT_LEARN_DISABLE); 782*e66f840cSTristram Ha } 783*e66f840cSTristram Ha ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); 784*e66f840cSTristram Ha for (index = first; index < cnt; index++) { 785*e66f840cSTristram Ha p = &dev->ports[index]; 786*e66f840cSTristram Ha if (!p->on) 787*e66f840cSTristram Ha continue; 788*e66f840cSTristram Ha if (!(learn[index] & PORT_LEARN_DISABLE)) 789*e66f840cSTristram Ha ksz_pwrite8(dev, index, P_STP_CTRL, learn[index]); 790*e66f840cSTristram Ha } 791*e66f840cSTristram Ha } 792*e66f840cSTristram Ha 793*e66f840cSTristram Ha static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, 794*e66f840cSTristram Ha bool flag) 795*e66f840cSTristram Ha { 796*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 797*e66f840cSTristram Ha 798*e66f840cSTristram Ha ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag); 799*e66f840cSTristram Ha 800*e66f840cSTristram Ha return 0; 801*e66f840cSTristram Ha } 802*e66f840cSTristram Ha 803*e66f840cSTristram Ha static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port, 804*e66f840cSTristram Ha const struct switchdev_obj_port_vlan *vlan) 805*e66f840cSTristram Ha { 806*e66f840cSTristram Ha bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 807*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 808*e66f840cSTristram Ha u16 data, vid, new_pvid = 0; 809*e66f840cSTristram Ha u8 fid, member, valid; 810*e66f840cSTristram Ha 811*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); 812*e66f840cSTristram Ha 813*e66f840cSTristram Ha for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 814*e66f840cSTristram Ha ksz8795_r_vlan_table(dev, vid, &data); 815*e66f840cSTristram Ha ksz8795_from_vlan(data, &fid, &member, &valid); 816*e66f840cSTristram Ha 817*e66f840cSTristram Ha /* First time to setup the VLAN entry. */ 818*e66f840cSTristram Ha if (!valid) { 819*e66f840cSTristram Ha /* Need to find a way to map VID to FID. */ 820*e66f840cSTristram Ha fid = 1; 821*e66f840cSTristram Ha valid = 1; 822*e66f840cSTristram Ha } 823*e66f840cSTristram Ha member |= BIT(port); 824*e66f840cSTristram Ha 825*e66f840cSTristram Ha ksz8795_to_vlan(fid, member, valid, &data); 826*e66f840cSTristram Ha ksz8795_w_vlan_table(dev, vid, data); 827*e66f840cSTristram Ha 828*e66f840cSTristram Ha /* change PVID */ 829*e66f840cSTristram Ha if (vlan->flags & BRIDGE_VLAN_INFO_PVID) 830*e66f840cSTristram Ha new_pvid = vid; 831*e66f840cSTristram Ha } 832*e66f840cSTristram Ha 833*e66f840cSTristram Ha if (new_pvid) { 834*e66f840cSTristram Ha ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid); 835*e66f840cSTristram Ha vid &= 0xfff; 836*e66f840cSTristram Ha vid |= new_pvid; 837*e66f840cSTristram Ha ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid); 838*e66f840cSTristram Ha } 839*e66f840cSTristram Ha } 840*e66f840cSTristram Ha 841*e66f840cSTristram Ha static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, 842*e66f840cSTristram Ha const struct switchdev_obj_port_vlan *vlan) 843*e66f840cSTristram Ha { 844*e66f840cSTristram Ha bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 845*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 846*e66f840cSTristram Ha u16 data, vid, pvid, new_pvid = 0; 847*e66f840cSTristram Ha u8 fid, member, valid; 848*e66f840cSTristram Ha 849*e66f840cSTristram Ha ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); 850*e66f840cSTristram Ha pvid = pvid & 0xFFF; 851*e66f840cSTristram Ha 852*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); 853*e66f840cSTristram Ha 854*e66f840cSTristram Ha for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 855*e66f840cSTristram Ha ksz8795_r_vlan_table(dev, vid, &data); 856*e66f840cSTristram Ha ksz8795_from_vlan(data, &fid, &member, &valid); 857*e66f840cSTristram Ha 858*e66f840cSTristram Ha member &= ~BIT(port); 859*e66f840cSTristram Ha 860*e66f840cSTristram Ha /* Invalidate the entry if no more member. */ 861*e66f840cSTristram Ha if (!member) { 862*e66f840cSTristram Ha fid = 0; 863*e66f840cSTristram Ha valid = 0; 864*e66f840cSTristram Ha } 865*e66f840cSTristram Ha 866*e66f840cSTristram Ha if (pvid == vid) 867*e66f840cSTristram Ha new_pvid = 1; 868*e66f840cSTristram Ha 869*e66f840cSTristram Ha ksz8795_to_vlan(fid, member, valid, &data); 870*e66f840cSTristram Ha ksz8795_w_vlan_table(dev, vid, data); 871*e66f840cSTristram Ha } 872*e66f840cSTristram Ha 873*e66f840cSTristram Ha if (new_pvid != pvid) 874*e66f840cSTristram Ha ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid); 875*e66f840cSTristram Ha 876*e66f840cSTristram Ha return 0; 877*e66f840cSTristram Ha } 878*e66f840cSTristram Ha 879*e66f840cSTristram Ha static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port, 880*e66f840cSTristram Ha struct dsa_mall_mirror_tc_entry *mirror, 881*e66f840cSTristram Ha bool ingress) 882*e66f840cSTristram Ha { 883*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 884*e66f840cSTristram Ha 885*e66f840cSTristram Ha if (ingress) { 886*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); 887*e66f840cSTristram Ha dev->mirror_rx |= BIT(port); 888*e66f840cSTristram Ha } else { 889*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); 890*e66f840cSTristram Ha dev->mirror_tx |= BIT(port); 891*e66f840cSTristram Ha } 892*e66f840cSTristram Ha 893*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false); 894*e66f840cSTristram Ha 895*e66f840cSTristram Ha /* configure mirror port */ 896*e66f840cSTristram Ha if (dev->mirror_rx || dev->mirror_tx) 897*e66f840cSTristram Ha ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, 898*e66f840cSTristram Ha PORT_MIRROR_SNIFFER, true); 899*e66f840cSTristram Ha 900*e66f840cSTristram Ha return 0; 901*e66f840cSTristram Ha } 902*e66f840cSTristram Ha 903*e66f840cSTristram Ha static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port, 904*e66f840cSTristram Ha struct dsa_mall_mirror_tc_entry *mirror) 905*e66f840cSTristram Ha { 906*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 907*e66f840cSTristram Ha u8 data; 908*e66f840cSTristram Ha 909*e66f840cSTristram Ha if (mirror->ingress) { 910*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); 911*e66f840cSTristram Ha dev->mirror_rx &= ~BIT(port); 912*e66f840cSTristram Ha } else { 913*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); 914*e66f840cSTristram Ha dev->mirror_tx &= ~BIT(port); 915*e66f840cSTristram Ha } 916*e66f840cSTristram Ha 917*e66f840cSTristram Ha ksz_pread8(dev, port, P_MIRROR_CTRL, &data); 918*e66f840cSTristram Ha 919*e66f840cSTristram Ha if (!dev->mirror_rx && !dev->mirror_tx) 920*e66f840cSTristram Ha ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, 921*e66f840cSTristram Ha PORT_MIRROR_SNIFFER, false); 922*e66f840cSTristram Ha } 923*e66f840cSTristram Ha 924*e66f840cSTristram Ha static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port) 925*e66f840cSTristram Ha { 926*e66f840cSTristram Ha struct ksz_port *p = &dev->ports[port]; 927*e66f840cSTristram Ha u8 data8, member; 928*e66f840cSTristram Ha 929*e66f840cSTristram Ha /* enable broadcast storm limit */ 930*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); 931*e66f840cSTristram Ha 932*e66f840cSTristram Ha ksz8795_set_prio_queue(dev, port, 4); 933*e66f840cSTristram Ha 934*e66f840cSTristram Ha /* disable DiffServ priority */ 935*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false); 936*e66f840cSTristram Ha 937*e66f840cSTristram Ha /* replace priority */ 938*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_802_1P_CTRL, PORT_802_1P_REMAPPING, false); 939*e66f840cSTristram Ha 940*e66f840cSTristram Ha /* enable 802.1p priority */ 941*e66f840cSTristram Ha ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true); 942*e66f840cSTristram Ha 943*e66f840cSTristram Ha if (cpu_port) { 944*e66f840cSTristram Ha /* Configure MII interface for proper network communication. */ 945*e66f840cSTristram Ha ksz_read8(dev, REG_PORT_5_CTRL_6, &data8); 946*e66f840cSTristram Ha data8 &= ~PORT_INTERFACE_TYPE; 947*e66f840cSTristram Ha data8 &= ~PORT_GMII_1GPS_MODE; 948*e66f840cSTristram Ha switch (dev->interface) { 949*e66f840cSTristram Ha case PHY_INTERFACE_MODE_MII: 950*e66f840cSTristram Ha p->phydev.speed = SPEED_100; 951*e66f840cSTristram Ha break; 952*e66f840cSTristram Ha case PHY_INTERFACE_MODE_RMII: 953*e66f840cSTristram Ha data8 |= PORT_INTERFACE_RMII; 954*e66f840cSTristram Ha p->phydev.speed = SPEED_100; 955*e66f840cSTristram Ha break; 956*e66f840cSTristram Ha case PHY_INTERFACE_MODE_GMII: 957*e66f840cSTristram Ha data8 |= PORT_GMII_1GPS_MODE; 958*e66f840cSTristram Ha data8 |= PORT_INTERFACE_GMII; 959*e66f840cSTristram Ha p->phydev.speed = SPEED_1000; 960*e66f840cSTristram Ha break; 961*e66f840cSTristram Ha default: 962*e66f840cSTristram Ha data8 &= ~PORT_RGMII_ID_IN_ENABLE; 963*e66f840cSTristram Ha data8 &= ~PORT_RGMII_ID_OUT_ENABLE; 964*e66f840cSTristram Ha if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || 965*e66f840cSTristram Ha dev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 966*e66f840cSTristram Ha data8 |= PORT_RGMII_ID_IN_ENABLE; 967*e66f840cSTristram Ha if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || 968*e66f840cSTristram Ha dev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 969*e66f840cSTristram Ha data8 |= PORT_RGMII_ID_OUT_ENABLE; 970*e66f840cSTristram Ha data8 |= PORT_GMII_1GPS_MODE; 971*e66f840cSTristram Ha data8 |= PORT_INTERFACE_RGMII; 972*e66f840cSTristram Ha p->phydev.speed = SPEED_1000; 973*e66f840cSTristram Ha break; 974*e66f840cSTristram Ha } 975*e66f840cSTristram Ha ksz_write8(dev, REG_PORT_5_CTRL_6, data8); 976*e66f840cSTristram Ha p->phydev.duplex = 1; 977*e66f840cSTristram Ha 978*e66f840cSTristram Ha member = dev->port_mask; 979*e66f840cSTristram Ha dev->on_ports = dev->host_mask; 980*e66f840cSTristram Ha dev->live_ports = dev->host_mask; 981*e66f840cSTristram Ha } else { 982*e66f840cSTristram Ha member = dev->host_mask | p->vid_member; 983*e66f840cSTristram Ha dev->on_ports |= BIT(port); 984*e66f840cSTristram Ha 985*e66f840cSTristram Ha /* Link was detected before port is enabled. */ 986*e66f840cSTristram Ha if (p->phydev.link) 987*e66f840cSTristram Ha dev->live_ports |= BIT(port); 988*e66f840cSTristram Ha } 989*e66f840cSTristram Ha ksz8795_cfg_port_member(dev, port, member); 990*e66f840cSTristram Ha } 991*e66f840cSTristram Ha 992*e66f840cSTristram Ha static void ksz8795_config_cpu_port(struct dsa_switch *ds) 993*e66f840cSTristram Ha { 994*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 995*e66f840cSTristram Ha struct ksz_port *p; 996*e66f840cSTristram Ha u8 remote; 997*e66f840cSTristram Ha int i; 998*e66f840cSTristram Ha 999*e66f840cSTristram Ha ds->num_ports = dev->port_cnt + 1; 1000*e66f840cSTristram Ha 1001*e66f840cSTristram Ha /* Switch marks the maximum frame with extra byte as oversize. */ 1002*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true); 1003*e66f840cSTristram Ha ksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true); 1004*e66f840cSTristram Ha 1005*e66f840cSTristram Ha p = &dev->ports[dev->cpu_port]; 1006*e66f840cSTristram Ha p->vid_member = dev->port_mask; 1007*e66f840cSTristram Ha p->on = 1; 1008*e66f840cSTristram Ha 1009*e66f840cSTristram Ha ksz8795_port_setup(dev, dev->cpu_port, true); 1010*e66f840cSTristram Ha dev->member = dev->host_mask; 1011*e66f840cSTristram Ha 1012*e66f840cSTristram Ha for (i = 0; i < SWITCH_PORT_NUM; i++) { 1013*e66f840cSTristram Ha p = &dev->ports[i]; 1014*e66f840cSTristram Ha 1015*e66f840cSTristram Ha /* Initialize to non-zero so that ksz_cfg_port_member() will 1016*e66f840cSTristram Ha * be called. 1017*e66f840cSTristram Ha */ 1018*e66f840cSTristram Ha p->vid_member = BIT(i); 1019*e66f840cSTristram Ha p->member = dev->port_mask; 1020*e66f840cSTristram Ha ksz8795_port_stp_state_set(ds, i, BR_STATE_DISABLED); 1021*e66f840cSTristram Ha 1022*e66f840cSTristram Ha /* Last port may be disabled. */ 1023*e66f840cSTristram Ha if (i == dev->port_cnt) 1024*e66f840cSTristram Ha break; 1025*e66f840cSTristram Ha p->on = 1; 1026*e66f840cSTristram Ha p->phy = 1; 1027*e66f840cSTristram Ha } 1028*e66f840cSTristram Ha for (i = 0; i < dev->phy_port_cnt; i++) { 1029*e66f840cSTristram Ha p = &dev->ports[i]; 1030*e66f840cSTristram Ha if (!p->on) 1031*e66f840cSTristram Ha continue; 1032*e66f840cSTristram Ha ksz_pread8(dev, i, P_REMOTE_STATUS, &remote); 1033*e66f840cSTristram Ha if (remote & PORT_FIBER_MODE) 1034*e66f840cSTristram Ha p->fiber = 1; 1035*e66f840cSTristram Ha if (p->fiber) 1036*e66f840cSTristram Ha ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, 1037*e66f840cSTristram Ha true); 1038*e66f840cSTristram Ha else 1039*e66f840cSTristram Ha ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, 1040*e66f840cSTristram Ha false); 1041*e66f840cSTristram Ha } 1042*e66f840cSTristram Ha } 1043*e66f840cSTristram Ha 1044*e66f840cSTristram Ha static int ksz8795_setup(struct dsa_switch *ds) 1045*e66f840cSTristram Ha { 1046*e66f840cSTristram Ha struct ksz_device *dev = ds->priv; 1047*e66f840cSTristram Ha struct alu_struct alu; 1048*e66f840cSTristram Ha int i, ret = 0; 1049*e66f840cSTristram Ha 1050*e66f840cSTristram Ha dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), 1051*e66f840cSTristram Ha dev->num_vlans, GFP_KERNEL); 1052*e66f840cSTristram Ha if (!dev->vlan_cache) 1053*e66f840cSTristram Ha return -ENOMEM; 1054*e66f840cSTristram Ha 1055*e66f840cSTristram Ha ret = ksz8795_reset_switch(dev); 1056*e66f840cSTristram Ha if (ret) { 1057*e66f840cSTristram Ha dev_err(ds->dev, "failed to reset switch\n"); 1058*e66f840cSTristram Ha return ret; 1059*e66f840cSTristram Ha } 1060*e66f840cSTristram Ha 1061*e66f840cSTristram Ha ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true); 1062*e66f840cSTristram Ha 1063*e66f840cSTristram Ha /* Enable automatic fast aging when link changed detected. */ 1064*e66f840cSTristram Ha ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true); 1065*e66f840cSTristram Ha 1066*e66f840cSTristram Ha /* Enable aggressive back off algorithm in half duplex mode. */ 1067*e66f840cSTristram Ha regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1, 1068*e66f840cSTristram Ha SW_AGGR_BACKOFF, SW_AGGR_BACKOFF); 1069*e66f840cSTristram Ha 1070*e66f840cSTristram Ha /* 1071*e66f840cSTristram Ha * Make sure unicast VLAN boundary is set as default and 1072*e66f840cSTristram Ha * enable no excessive collision drop. 1073*e66f840cSTristram Ha */ 1074*e66f840cSTristram Ha regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2, 1075*e66f840cSTristram Ha UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, 1076*e66f840cSTristram Ha UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); 1077*e66f840cSTristram Ha 1078*e66f840cSTristram Ha ksz8795_config_cpu_port(ds); 1079*e66f840cSTristram Ha 1080*e66f840cSTristram Ha ksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true); 1081*e66f840cSTristram Ha 1082*e66f840cSTristram Ha ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_REPLACE_VID, false); 1083*e66f840cSTristram Ha 1084*e66f840cSTristram Ha ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false); 1085*e66f840cSTristram Ha 1086*e66f840cSTristram Ha /* set broadcast storm protection 10% rate */ 1087*e66f840cSTristram Ha regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL, 1088*e66f840cSTristram Ha BROADCAST_STORM_RATE, 1089*e66f840cSTristram Ha (BROADCAST_STORM_VALUE * 1090*e66f840cSTristram Ha BROADCAST_STORM_PROT_RATE) / 100); 1091*e66f840cSTristram Ha 1092*e66f840cSTristram Ha for (i = 0; i < VLAN_TABLE_ENTRIES; i++) 1093*e66f840cSTristram Ha ksz8795_r_vlan_entries(dev, i); 1094*e66f840cSTristram Ha 1095*e66f840cSTristram Ha /* Setup STP address for STP operation. */ 1096*e66f840cSTristram Ha memset(&alu, 0, sizeof(alu)); 1097*e66f840cSTristram Ha ether_addr_copy(alu.mac, eth_stp_addr); 1098*e66f840cSTristram Ha alu.is_static = true; 1099*e66f840cSTristram Ha alu.is_override = true; 1100*e66f840cSTristram Ha alu.port_forward = dev->host_mask; 1101*e66f840cSTristram Ha 1102*e66f840cSTristram Ha ksz8795_w_sta_mac_table(dev, 0, &alu); 1103*e66f840cSTristram Ha 1104*e66f840cSTristram Ha ksz_init_mib_timer(dev); 1105*e66f840cSTristram Ha 1106*e66f840cSTristram Ha return 0; 1107*e66f840cSTristram Ha } 1108*e66f840cSTristram Ha 1109*e66f840cSTristram Ha static const struct dsa_switch_ops ksz8795_switch_ops = { 1110*e66f840cSTristram Ha .get_tag_protocol = ksz8795_get_tag_protocol, 1111*e66f840cSTristram Ha .setup = ksz8795_setup, 1112*e66f840cSTristram Ha .phy_read = ksz_phy_read16, 1113*e66f840cSTristram Ha .phy_write = ksz_phy_write16, 1114*e66f840cSTristram Ha .adjust_link = ksz_adjust_link, 1115*e66f840cSTristram Ha .port_enable = ksz_enable_port, 1116*e66f840cSTristram Ha .port_disable = ksz_disable_port, 1117*e66f840cSTristram Ha .get_strings = ksz8795_get_strings, 1118*e66f840cSTristram Ha .get_ethtool_stats = ksz_get_ethtool_stats, 1119*e66f840cSTristram Ha .get_sset_count = ksz_sset_count, 1120*e66f840cSTristram Ha .port_bridge_join = ksz_port_bridge_join, 1121*e66f840cSTristram Ha .port_bridge_leave = ksz_port_bridge_leave, 1122*e66f840cSTristram Ha .port_stp_state_set = ksz8795_port_stp_state_set, 1123*e66f840cSTristram Ha .port_fast_age = ksz_port_fast_age, 1124*e66f840cSTristram Ha .port_vlan_filtering = ksz8795_port_vlan_filtering, 1125*e66f840cSTristram Ha .port_vlan_prepare = ksz_port_vlan_prepare, 1126*e66f840cSTristram Ha .port_vlan_add = ksz8795_port_vlan_add, 1127*e66f840cSTristram Ha .port_vlan_del = ksz8795_port_vlan_del, 1128*e66f840cSTristram Ha .port_fdb_dump = ksz_port_fdb_dump, 1129*e66f840cSTristram Ha .port_mdb_prepare = ksz_port_mdb_prepare, 1130*e66f840cSTristram Ha .port_mdb_add = ksz_port_mdb_add, 1131*e66f840cSTristram Ha .port_mdb_del = ksz_port_mdb_del, 1132*e66f840cSTristram Ha .port_mirror_add = ksz8795_port_mirror_add, 1133*e66f840cSTristram Ha .port_mirror_del = ksz8795_port_mirror_del, 1134*e66f840cSTristram Ha }; 1135*e66f840cSTristram Ha 1136*e66f840cSTristram Ha static u32 ksz8795_get_port_addr(int port, int offset) 1137*e66f840cSTristram Ha { 1138*e66f840cSTristram Ha return PORT_CTRL_ADDR(port, offset); 1139*e66f840cSTristram Ha } 1140*e66f840cSTristram Ha 1141*e66f840cSTristram Ha static int ksz8795_switch_detect(struct ksz_device *dev) 1142*e66f840cSTristram Ha { 1143*e66f840cSTristram Ha u8 id1, id2; 1144*e66f840cSTristram Ha u16 id16; 1145*e66f840cSTristram Ha int ret; 1146*e66f840cSTristram Ha 1147*e66f840cSTristram Ha /* read chip id */ 1148*e66f840cSTristram Ha ret = ksz_read16(dev, REG_CHIP_ID0, &id16); 1149*e66f840cSTristram Ha if (ret) 1150*e66f840cSTristram Ha return ret; 1151*e66f840cSTristram Ha 1152*e66f840cSTristram Ha id1 = id16 >> 8; 1153*e66f840cSTristram Ha id2 = id16 & SW_CHIP_ID_M; 1154*e66f840cSTristram Ha if (id1 != FAMILY_ID || 1155*e66f840cSTristram Ha (id2 != CHIP_ID_94 && id2 != CHIP_ID_95)) 1156*e66f840cSTristram Ha return -ENODEV; 1157*e66f840cSTristram Ha 1158*e66f840cSTristram Ha dev->mib_port_cnt = TOTAL_PORT_NUM; 1159*e66f840cSTristram Ha dev->phy_port_cnt = SWITCH_PORT_NUM; 1160*e66f840cSTristram Ha dev->port_cnt = SWITCH_PORT_NUM; 1161*e66f840cSTristram Ha 1162*e66f840cSTristram Ha if (id2 == CHIP_ID_95) { 1163*e66f840cSTristram Ha u8 val; 1164*e66f840cSTristram Ha 1165*e66f840cSTristram Ha id2 = 0x95; 1166*e66f840cSTristram Ha ksz_read8(dev, REG_PORT_1_STATUS_0, &val); 1167*e66f840cSTristram Ha if (val & PORT_FIBER_MODE) 1168*e66f840cSTristram Ha id2 = 0x65; 1169*e66f840cSTristram Ha } else if (id2 == CHIP_ID_94) { 1170*e66f840cSTristram Ha dev->port_cnt--; 1171*e66f840cSTristram Ha dev->last_port = dev->port_cnt; 1172*e66f840cSTristram Ha id2 = 0x94; 1173*e66f840cSTristram Ha } 1174*e66f840cSTristram Ha id16 &= ~0xff; 1175*e66f840cSTristram Ha id16 |= id2; 1176*e66f840cSTristram Ha dev->chip_id = id16; 1177*e66f840cSTristram Ha 1178*e66f840cSTristram Ha dev->cpu_port = dev->mib_port_cnt - 1; 1179*e66f840cSTristram Ha dev->host_mask = BIT(dev->cpu_port); 1180*e66f840cSTristram Ha 1181*e66f840cSTristram Ha return 0; 1182*e66f840cSTristram Ha } 1183*e66f840cSTristram Ha 1184*e66f840cSTristram Ha struct ksz_chip_data { 1185*e66f840cSTristram Ha u16 chip_id; 1186*e66f840cSTristram Ha const char *dev_name; 1187*e66f840cSTristram Ha int num_vlans; 1188*e66f840cSTristram Ha int num_alus; 1189*e66f840cSTristram Ha int num_statics; 1190*e66f840cSTristram Ha int cpu_ports; 1191*e66f840cSTristram Ha int port_cnt; 1192*e66f840cSTristram Ha }; 1193*e66f840cSTristram Ha 1194*e66f840cSTristram Ha static const struct ksz_chip_data ksz8795_switch_chips[] = { 1195*e66f840cSTristram Ha { 1196*e66f840cSTristram Ha .chip_id = 0x8795, 1197*e66f840cSTristram Ha .dev_name = "KSZ8795", 1198*e66f840cSTristram Ha .num_vlans = 4096, 1199*e66f840cSTristram Ha .num_alus = 0, 1200*e66f840cSTristram Ha .num_statics = 8, 1201*e66f840cSTristram Ha .cpu_ports = 0x10, /* can be configured as cpu port */ 1202*e66f840cSTristram Ha .port_cnt = 4, /* total physical port count */ 1203*e66f840cSTristram Ha }, 1204*e66f840cSTristram Ha { 1205*e66f840cSTristram Ha .chip_id = 0x8794, 1206*e66f840cSTristram Ha .dev_name = "KSZ8794", 1207*e66f840cSTristram Ha .num_vlans = 4096, 1208*e66f840cSTristram Ha .num_alus = 0, 1209*e66f840cSTristram Ha .num_statics = 8, 1210*e66f840cSTristram Ha .cpu_ports = 0x10, /* can be configured as cpu port */ 1211*e66f840cSTristram Ha .port_cnt = 3, /* total physical port count */ 1212*e66f840cSTristram Ha }, 1213*e66f840cSTristram Ha { 1214*e66f840cSTristram Ha .chip_id = 0x8765, 1215*e66f840cSTristram Ha .dev_name = "KSZ8765", 1216*e66f840cSTristram Ha .num_vlans = 4096, 1217*e66f840cSTristram Ha .num_alus = 0, 1218*e66f840cSTristram Ha .num_statics = 8, 1219*e66f840cSTristram Ha .cpu_ports = 0x10, /* can be configured as cpu port */ 1220*e66f840cSTristram Ha .port_cnt = 4, /* total physical port count */ 1221*e66f840cSTristram Ha }, 1222*e66f840cSTristram Ha }; 1223*e66f840cSTristram Ha 1224*e66f840cSTristram Ha static int ksz8795_switch_init(struct ksz_device *dev) 1225*e66f840cSTristram Ha { 1226*e66f840cSTristram Ha int i; 1227*e66f840cSTristram Ha 1228*e66f840cSTristram Ha mutex_init(&dev->stats_mutex); 1229*e66f840cSTristram Ha mutex_init(&dev->alu_mutex); 1230*e66f840cSTristram Ha mutex_init(&dev->vlan_mutex); 1231*e66f840cSTristram Ha 1232*e66f840cSTristram Ha dev->ds->ops = &ksz8795_switch_ops; 1233*e66f840cSTristram Ha 1234*e66f840cSTristram Ha for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) { 1235*e66f840cSTristram Ha const struct ksz_chip_data *chip = &ksz8795_switch_chips[i]; 1236*e66f840cSTristram Ha 1237*e66f840cSTristram Ha if (dev->chip_id == chip->chip_id) { 1238*e66f840cSTristram Ha dev->name = chip->dev_name; 1239*e66f840cSTristram Ha dev->num_vlans = chip->num_vlans; 1240*e66f840cSTristram Ha dev->num_alus = chip->num_alus; 1241*e66f840cSTristram Ha dev->num_statics = chip->num_statics; 1242*e66f840cSTristram Ha dev->port_cnt = chip->port_cnt; 1243*e66f840cSTristram Ha dev->cpu_ports = chip->cpu_ports; 1244*e66f840cSTristram Ha 1245*e66f840cSTristram Ha break; 1246*e66f840cSTristram Ha } 1247*e66f840cSTristram Ha } 1248*e66f840cSTristram Ha 1249*e66f840cSTristram Ha /* no switch found */ 1250*e66f840cSTristram Ha if (!dev->cpu_ports) 1251*e66f840cSTristram Ha return -ENODEV; 1252*e66f840cSTristram Ha 1253*e66f840cSTristram Ha dev->port_mask = BIT(dev->port_cnt) - 1; 1254*e66f840cSTristram Ha dev->port_mask |= dev->host_mask; 1255*e66f840cSTristram Ha 1256*e66f840cSTristram Ha dev->reg_mib_cnt = SWITCH_COUNTER_NUM; 1257*e66f840cSTristram Ha dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM; 1258*e66f840cSTristram Ha 1259*e66f840cSTristram Ha i = dev->mib_port_cnt; 1260*e66f840cSTristram Ha dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i, 1261*e66f840cSTristram Ha GFP_KERNEL); 1262*e66f840cSTristram Ha if (!dev->ports) 1263*e66f840cSTristram Ha return -ENOMEM; 1264*e66f840cSTristram Ha for (i = 0; i < dev->mib_port_cnt; i++) { 1265*e66f840cSTristram Ha mutex_init(&dev->ports[i].mib.cnt_mutex); 1266*e66f840cSTristram Ha dev->ports[i].mib.counters = 1267*e66f840cSTristram Ha devm_kzalloc(dev->dev, 1268*e66f840cSTristram Ha sizeof(u64) * 1269*e66f840cSTristram Ha (TOTAL_SWITCH_COUNTER_NUM + 1), 1270*e66f840cSTristram Ha GFP_KERNEL); 1271*e66f840cSTristram Ha if (!dev->ports[i].mib.counters) 1272*e66f840cSTristram Ha return -ENOMEM; 1273*e66f840cSTristram Ha } 1274*e66f840cSTristram Ha 1275*e66f840cSTristram Ha return 0; 1276*e66f840cSTristram Ha } 1277*e66f840cSTristram Ha 1278*e66f840cSTristram Ha static void ksz8795_switch_exit(struct ksz_device *dev) 1279*e66f840cSTristram Ha { 1280*e66f840cSTristram Ha ksz8795_reset_switch(dev); 1281*e66f840cSTristram Ha } 1282*e66f840cSTristram Ha 1283*e66f840cSTristram Ha static const struct ksz_dev_ops ksz8795_dev_ops = { 1284*e66f840cSTristram Ha .get_port_addr = ksz8795_get_port_addr, 1285*e66f840cSTristram Ha .cfg_port_member = ksz8795_cfg_port_member, 1286*e66f840cSTristram Ha .flush_dyn_mac_table = ksz8795_flush_dyn_mac_table, 1287*e66f840cSTristram Ha .port_setup = ksz8795_port_setup, 1288*e66f840cSTristram Ha .r_phy = ksz8795_r_phy, 1289*e66f840cSTristram Ha .w_phy = ksz8795_w_phy, 1290*e66f840cSTristram Ha .r_dyn_mac_table = ksz8795_r_dyn_mac_table, 1291*e66f840cSTristram Ha .r_sta_mac_table = ksz8795_r_sta_mac_table, 1292*e66f840cSTristram Ha .w_sta_mac_table = ksz8795_w_sta_mac_table, 1293*e66f840cSTristram Ha .r_mib_cnt = ksz8795_r_mib_cnt, 1294*e66f840cSTristram Ha .r_mib_pkt = ksz8795_r_mib_pkt, 1295*e66f840cSTristram Ha .freeze_mib = ksz8795_freeze_mib, 1296*e66f840cSTristram Ha .port_init_cnt = ksz8795_port_init_cnt, 1297*e66f840cSTristram Ha .shutdown = ksz8795_reset_switch, 1298*e66f840cSTristram Ha .detect = ksz8795_switch_detect, 1299*e66f840cSTristram Ha .init = ksz8795_switch_init, 1300*e66f840cSTristram Ha .exit = ksz8795_switch_exit, 1301*e66f840cSTristram Ha }; 1302*e66f840cSTristram Ha 1303*e66f840cSTristram Ha int ksz8795_switch_register(struct ksz_device *dev) 1304*e66f840cSTristram Ha { 1305*e66f840cSTristram Ha return ksz_switch_register(dev, &ksz8795_dev_ops); 1306*e66f840cSTristram Ha } 1307*e66f840cSTristram Ha EXPORT_SYMBOL(ksz8795_switch_register); 1308*e66f840cSTristram Ha 1309*e66f840cSTristram Ha MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>"); 1310*e66f840cSTristram Ha MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver"); 1311*e66f840cSTristram Ha MODULE_LICENSE("GPL"); 1312