^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) * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2016 John Crispin <john@phrozen.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^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/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <net/dsa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/if_bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/phylink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "qca8k.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MIB_DESC(_s, _o, _n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .size = (_s), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .offset = (_o), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .name = (_n), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static const struct qca8k_mib_desc ar8327_mib[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MIB_DESC(1, 0x00, "RxBroad"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MIB_DESC(1, 0x04, "RxPause"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MIB_DESC(1, 0x08, "RxMulti"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MIB_DESC(1, 0x0c, "RxFcsErr"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MIB_DESC(1, 0x10, "RxAlignErr"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MIB_DESC(1, 0x14, "RxRunt"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MIB_DESC(1, 0x18, "RxFragment"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MIB_DESC(1, 0x1c, "Rx64Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MIB_DESC(1, 0x20, "Rx128Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) MIB_DESC(1, 0x24, "Rx256Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MIB_DESC(1, 0x28, "Rx512Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MIB_DESC(1, 0x2c, "Rx1024Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MIB_DESC(1, 0x30, "Rx1518Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MIB_DESC(1, 0x34, "RxMaxByte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MIB_DESC(1, 0x38, "RxTooLong"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MIB_DESC(2, 0x3c, "RxGoodByte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MIB_DESC(2, 0x44, "RxBadByte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MIB_DESC(1, 0x4c, "RxOverFlow"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MIB_DESC(1, 0x50, "Filtered"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MIB_DESC(1, 0x54, "TxBroad"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) MIB_DESC(1, 0x58, "TxPause"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MIB_DESC(1, 0x5c, "TxMulti"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MIB_DESC(1, 0x60, "TxUnderRun"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MIB_DESC(1, 0x64, "Tx64Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) MIB_DESC(1, 0x68, "Tx128Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) MIB_DESC(1, 0x6c, "Tx256Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) MIB_DESC(1, 0x70, "Tx512Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) MIB_DESC(1, 0x74, "Tx1024Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) MIB_DESC(1, 0x78, "Tx1518Byte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) MIB_DESC(1, 0x7c, "TxMaxByte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) MIB_DESC(1, 0x80, "TxOverSize"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MIB_DESC(2, 0x84, "TxByte"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) MIB_DESC(1, 0x8c, "TxCollision"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) MIB_DESC(1, 0x90, "TxAbortCol"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) MIB_DESC(1, 0x94, "TxMultiCol"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) MIB_DESC(1, 0x98, "TxSingleCol"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) MIB_DESC(1, 0x9c, "TxExcDefer"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) MIB_DESC(1, 0xa0, "TxDefer"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) MIB_DESC(1, 0xa4, "TxLateCol"),
^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) /* The 32bit switch registers are accessed indirectly. To achieve this we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * to set the page of the register. Track the last page that was set to reduce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * mdio writes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static u16 qca8k_current_page = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) regaddr >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *r1 = regaddr & 0x1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) regaddr >>= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *r2 = regaddr & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) regaddr >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *page = regaddr & 0x3ff;
^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 u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ret = bus->read(bus, phy_id, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ret = bus->read(bus, phy_id, regnum + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) val |= ret << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) dev_err_ratelimited(&bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) "failed to read qca8k 32bit register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u16 lo, hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) lo = val & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) hi = (u16)(val >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ret = bus->write(bus, phy_id, regnum, lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = bus->write(bus, phy_id, regnum + 1, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dev_err_ratelimited(&bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) "failed to write qca8k 32bit register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) qca8k_set_page(struct mii_bus *bus, u16 page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (page == qca8k_current_page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (bus->write(bus, 0x18, 0, page) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dev_err_ratelimited(&bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "failed to set qca8k page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) qca8k_current_page = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) qca8k_read(struct qca8k_priv *priv, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u16 r1, r2, page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) qca8k_split_addr(reg, &r1, &r2, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) qca8k_set_page(priv->bus, page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) mutex_unlock(&priv->bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u16 r1, r2, page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) qca8k_split_addr(reg, &r1, &r2, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) qca8k_set_page(priv->bus, page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mutex_unlock(&priv->bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u16 r1, r2, page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) qca8k_split_addr(reg, &r1, &r2, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) qca8k_set_page(priv->bus, page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ret = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ret &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ret |= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) qca8k_mii_write32(priv->bus, 0x10 | r2, r1, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) mutex_unlock(&priv->bus->mdio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return ret;
^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 void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) qca8k_rmw(priv, reg, 0, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) qca8k_rmw(priv, reg, val, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *val = qca8k_read(priv, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) qca8k_write(priv, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static const struct regmap_range qca8k_readable_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) regmap_reg_range(0x0000, 0x00e4), /* Global control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) regmap_reg_range(0x0100, 0x0168), /* EEE control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) regmap_reg_range(0x0200, 0x0270), /* Parser control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) regmap_reg_range(0x0400, 0x0454), /* ACL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) regmap_reg_range(0x0600, 0x0718), /* Lookup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) regmap_reg_range(0x0800, 0x0b70), /* QM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) regmap_reg_range(0x0c00, 0x0c80), /* PKT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) regmap_reg_range(0x0e00, 0x0e98), /* L3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static const struct regmap_access_table qca8k_readable_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .yes_ranges = qca8k_readable_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct regmap_config qca8k_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .reg_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .max_register = 0x16ac, /* end MIB - Port6 range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .reg_read = qca8k_regmap_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .reg_write = qca8k_regmap_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .rd_table = &qca8k_readable_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) timeout = jiffies + msecs_to_jiffies(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* loop until the busy flag has cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u32 val = qca8k_read(priv, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int busy = val & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) } while (!time_after_eq(jiffies, timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return time_after_eq(jiffies, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u32 reg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* load the ARL table into an array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) reg[i] = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* vid - 83:72 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* aging - 67:64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) fdb->aging = reg[2] & QCA8K_ATU_STATUS_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* portmask - 54:48 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) fdb->port_mask = (reg[1] >> QCA8K_ATU_PORT_S) & QCA8K_ATU_PORT_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* mac - 47:0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) fdb->mac[0] = (reg[1] >> QCA8K_ATU_ADDR0_S) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) fdb->mac[1] = reg[1] & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) fdb->mac[2] = (reg[0] >> QCA8K_ATU_ADDR2_S) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) fdb->mac[5] = reg[0] & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u8 aging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) u32 reg[3] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* vid - 83:72 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) reg[2] = (vid & QCA8K_ATU_VID_M) << QCA8K_ATU_VID_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* aging - 67:64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) reg[2] |= aging & QCA8K_ATU_STATUS_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* portmask - 54:48 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) reg[1] = (port_mask & QCA8K_ATU_PORT_M) << QCA8K_ATU_PORT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* mac - 47:0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) reg[1] |= mac[0] << QCA8K_ATU_ADDR0_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) reg[1] |= mac[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) reg[0] |= mac[2] << QCA8K_ATU_ADDR2_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) reg[0] |= mac[3] << QCA8K_ATU_ADDR3_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) reg[0] |= mac[4] << QCA8K_ATU_ADDR4_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) reg[0] |= mac[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* load the array into the ARL table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) qca8k_write(priv, QCA8K_REG_ATU_DATA0 + (i * 4), reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Set the command and FDB index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) reg = QCA8K_ATU_FUNC_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) reg |= cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (port >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) reg |= QCA8K_ATU_FUNC_PORT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) reg |= (port & QCA8K_ATU_FUNC_PORT_M) << QCA8K_ATU_FUNC_PORT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* Write the function register triggering the table access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* wait for completion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* Check for table full violation when adding an entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (cmd == QCA8K_FDB_LOAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (reg & QCA8K_ATU_FUNC_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) qca8k_fdb_read(priv, fdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return ret;
^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 int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac, u16 port_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u16 vid, u8 aging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) qca8k_fdb_write(priv, vid, port_mask, mac, aging);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return ret;
^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 int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, u16 port_mask, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) qca8k_fdb_write(priv, vid, port_mask, mac, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) qca8k_fdb_flush(struct qca8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* Set the command and VLAN index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) reg = QCA8K_VTU_FUNC1_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) reg |= cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) reg |= vid << QCA8K_VTU_FUNC1_VID_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* Write the function register triggering the table access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* wait for completion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* Check for table full violation when adding an entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (cmd == QCA8K_VLAN_LOAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (reg & QCA8K_VTU_FUNC1_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, bool untagged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) We do the right thing with VLAN 0 and treat it as untagged while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) preserving the tag on egress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (vid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (untagged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) reg |= QCA8K_VTU_FUNC0_EG_MODE_UNTAG <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) QCA8K_VTU_FUNC0_EG_MODE_S(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) QCA8K_VTU_FUNC0_EG_MODE_S(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) u32 reg, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) bool del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) QCA8K_VTU_FUNC0_EG_MODE_S(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Check if we're the last member to be removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) del = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) for (i = 0; i < QCA8K_NUM_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mask = QCA8K_VTU_FUNC0_EG_MODE_NOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) mask <<= QCA8K_VTU_FUNC0_EG_MODE_S(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if ((reg & mask) != mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) del = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (del) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return ret;
^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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) qca8k_mib_init(struct qca8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* Port 0 and 6 have no internal PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (port > 0 && port < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) mask |= QCA8K_PORT_STATUS_LINK_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) qca8k_port_to_phy(int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* From Andrew Lunn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * Port 0 has no internal phy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * Port 1 has an internal PHY at MDIO address 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * Port 2 has an internal PHY at MDIO address 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * Port 5 has an internal PHY at MDIO address 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * Port 6 has no internal PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return port - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u32 phy, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* callee is responsible for not passing bad ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * but we still would like to make spills impossible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) QCA8K_MDIO_MASTER_DATA(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) QCA8K_MDIO_MASTER_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) u32 phy, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* callee is responsible for not passing bad ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * but we still would like to make spills impossible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) QCA8K_MDIO_MASTER_REG_ADDR(regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) QCA8K_MDIO_MASTER_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) val = (qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) QCA8K_MDIO_MASTER_DATA_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return qca8k_mdio_write(priv, port, regnum, data);
^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) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) qca8k_phy_read(struct dsa_switch *ds, int port, int regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ret = qca8k_mdio_read(priv, port, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) qca8k_setup_mdio_bus(struct qca8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct device_node *ports, *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ports = of_get_child_by_name(priv->dev->of_node, "ports");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (!ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) for_each_available_child_of_node(ports, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) err = of_property_read_u32(port, "reg", ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) of_node_put(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) of_node_put(ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (!dsa_is_user_port(priv->ds, reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (of_property_read_bool(port, "phy-handle"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) external_mdio_mask |= BIT(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) internal_mdio_mask |= BIT(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) of_node_put(ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (!external_mdio_mask && !internal_mdio_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) dev_err(priv->dev, "no PHYs are defined.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* The QCA8K_MDIO_MASTER_EN Bit, which grants access to PHYs through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * the MDIO_MASTER register also _disconnects_ the external MDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * passthrough to the internal PHYs. It's not possible to use both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * configurations at the same time!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * Because this came up during the review process:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * If the external mdio-bus driver is capable magically disabling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * the QCA8K_MDIO_MASTER_EN and mutex/spin-locking out the qca8k's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * accessors for the time being, it would be possible to pull this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!!external_mdio_mask && !!internal_mdio_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dev_err(priv->dev, "either internal or external mdio bus configuration is supported.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (external_mdio_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* Make sure to disable the internal mdio bus in cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * a dt-overlay and driver reload changed the configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) QCA8K_MDIO_MASTER_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) priv->ops.phy_read = qca8k_phy_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) priv->ops.phy_write = qca8k_phy_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) qca8k_setup(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* Make sure that port 0 is the cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!dsa_is_cpu_port(ds, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) pr_err("port 0 is not the CPU port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) mutex_init(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /* Start by setting up the register mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) priv->regmap = devm_regmap_init(ds->dev, NULL, priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) &qca8k_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (IS_ERR(priv->regmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) pr_warn("regmap initialization failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ret = qca8k_setup_mdio_bus(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* Enable CPU Port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* Enable MIB counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) qca8k_mib_init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* Enable QCA header mode on the cpu port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) /* Disable forwarding by default on all ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) for (i = 0; i < QCA8K_NUM_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) QCA8K_PORT_LOOKUP_MEMBER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /* Disable MAC by default on all ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) for (i = 1; i < QCA8K_NUM_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) qca8k_port_set_status(priv, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* Forward all unknown frames to CPU port for Linux processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* Setup connection between CPU port & user ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) for (i = 0; i < QCA8K_NUM_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* CPU port gets connected to all user ports of the switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (dsa_is_cpu_port(ds, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /* Individual user ports get connected to CPU port only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (dsa_is_user_port(ds, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) int shift = 16 * (i % 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) QCA8K_PORT_LOOKUP_MEMBER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) BIT(QCA8K_CPU_PORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Enable ARP Auto-learning by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) QCA8K_PORT_LOOKUP_LEARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* For port based vlans to work we need to set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * default egress vid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 0xfff << shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) QCA8K_PORT_VID_DEF << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* Setup our port MTUs to match power on defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) for (i = 0; i < QCA8K_NUM_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* Flush the FDB table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) qca8k_fdb_flush(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* We don't have interrupts for link changes, so we need to poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ds->pcs_poll = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) const struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) u32 reg, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) switch (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) case 0: /* 1st CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (state->interface != PHY_INTERFACE_MODE_RGMII &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) state->interface != PHY_INTERFACE_MODE_SGMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) reg = QCA8K_REG_PORT0_PAD_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /* Internal PHY, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) case 6: /* 2nd CPU port / external PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (state->interface != PHY_INTERFACE_MODE_RGMII &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) state->interface != PHY_INTERFACE_MODE_SGMII &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) state->interface != PHY_INTERFACE_MODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) reg = QCA8K_REG_PORT6_PAD_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return;
^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) if (port != 6 && phylink_autoneg_inband(mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) switch (state->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) case PHY_INTERFACE_MODE_RGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* RGMII mode means no delay so don't enable the delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) case PHY_INTERFACE_MODE_RGMII_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* RGMII_ID needs internal delay. This is enabled through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * PORT5_PAD_CTRL for all ports, rather than individual port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) qca8k_write(priv, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) QCA8K_PORT_PAD_RGMII_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /* Enable SGMII on the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* Enable/disable SerDes auto-negotiation as necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) val = qca8k_read(priv, QCA8K_REG_PWS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (phylink_autoneg_inband(mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) val &= ~QCA8K_PWS_SERDES_AEN_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) val |= QCA8K_PWS_SERDES_AEN_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) qca8k_write(priv, QCA8K_REG_PWS, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* Configure the SGMII parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) val = qca8k_read(priv, QCA8K_REG_SGMII_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (dsa_is_cpu_port(ds, port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* CPU port, we're talking to the CPU MAC, be a PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) val &= ~QCA8K_SGMII_MODE_CTRL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) val |= QCA8K_SGMII_MODE_CTRL_PHY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) } else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) val &= ~QCA8K_SGMII_MODE_CTRL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) val |= QCA8K_SGMII_MODE_CTRL_MAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) } else if (state->interface == PHY_INTERFACE_MODE_1000BASEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) val &= ~QCA8K_SGMII_MODE_CTRL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) val |= QCA8K_SGMII_MODE_CTRL_BASEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dev_err(ds->dev, "xMII mode %s not supported for port %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) phy_modes(state->interface), port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) qca8k_phylink_validate(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) unsigned long *supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) switch (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) case 0: /* 1st CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (state->interface != PHY_INTERFACE_MODE_NA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) state->interface != PHY_INTERFACE_MODE_RGMII &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) state->interface != PHY_INTERFACE_MODE_SGMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) goto unsupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /* Internal PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (state->interface != PHY_INTERFACE_MODE_NA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) state->interface != PHY_INTERFACE_MODE_GMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) goto unsupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) case 6: /* 2nd CPU port / external PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (state->interface != PHY_INTERFACE_MODE_NA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) state->interface != PHY_INTERFACE_MODE_RGMII &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) state->interface != PHY_INTERFACE_MODE_SGMII &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) state->interface != PHY_INTERFACE_MODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) goto unsupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) unsupported:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) linkmode_zero(supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) phylink_set_port_modes(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) phylink_set(mask, Autoneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) phylink_set(mask, 1000baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) phylink_set(mask, 10baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) phylink_set(mask, 10baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) phylink_set(mask, 100baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) phylink_set(mask, 100baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) phylink_set(mask, 1000baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) phylink_set(mask, Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) phylink_set(mask, Asym_Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) linkmode_and(supported, supported, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) linkmode_and(state->advertising, state->advertising, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) state->an_complete = state->link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) state->an_enabled = !!(reg & QCA8K_PORT_STATUS_LINK_AUTO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) state->duplex = (reg & QCA8K_PORT_STATUS_DUPLEX) ? DUPLEX_FULL :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) switch (reg & QCA8K_PORT_STATUS_SPEED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) case QCA8K_PORT_STATUS_SPEED_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) state->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case QCA8K_PORT_STATUS_SPEED_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) state->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) case QCA8K_PORT_STATUS_SPEED_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) state->speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) state->speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) state->pause = MLO_PAUSE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (reg & QCA8K_PORT_STATUS_RXFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) state->pause |= MLO_PAUSE_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (reg & QCA8K_PORT_STATUS_TXFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) state->pause |= MLO_PAUSE_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) qca8k_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) phy_interface_t interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) qca8k_port_set_status(priv, port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) phy_interface_t interface, struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) int speed, int duplex, bool tx_pause, bool rx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (phylink_autoneg_inband(mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) reg = QCA8K_PORT_STATUS_LINK_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) switch (speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) case SPEED_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) reg = QCA8K_PORT_STATUS_SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) case SPEED_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) reg = QCA8K_PORT_STATUS_SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) case SPEED_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) reg = QCA8K_PORT_STATUS_SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) reg = QCA8K_PORT_STATUS_LINK_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (duplex == DUPLEX_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) reg |= QCA8K_PORT_STATUS_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (rx_pause || dsa_is_cpu_port(ds, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) reg |= QCA8K_PORT_STATUS_RXFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (tx_pause || dsa_is_cpu_port(ds, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) reg |= QCA8K_PORT_STATUS_TXFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) reg |= QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (stringset != ETH_SS_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) uint64_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) const struct qca8k_mib_desc *mib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) u32 reg, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) u64 hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) mib = &ar8327_mib[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) data[i] = qca8k_read(priv, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (mib->size == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) hi = qca8k_read(priv, reg + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) data[i] |= hi << 32;
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (sset != ETH_SS_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return ARRAY_SIZE(ar8327_mib);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *eee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (eee->eee_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) reg |= lpi_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) reg &= ~lpi_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /* Nothing to do on the port's MAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) u32 stp_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) case BR_STATE_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) case BR_STATE_BLOCKING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) case BR_STATE_LISTENING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) case BR_STATE_LEARNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) case BR_STATE_FORWARDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) int port_mask = BIT(QCA8K_CPU_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (i = 1; i < QCA8K_NUM_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (dsa_to_port(ds, i)->bridge_dev != br)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* Add this port to the portvlan mask of the other ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * in the bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) qca8k_reg_set(priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) QCA8K_PORT_LOOKUP_CTRL(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) BIT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (i != port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) port_mask |= BIT(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) /* Add all other ports to this ports portvlan mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) QCA8K_PORT_LOOKUP_MEMBER, port_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) for (i = 1; i < QCA8K_NUM_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (dsa_to_port(ds, i)->bridge_dev != br)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* Remove this port to the portvlan mask of the other ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * in the bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) qca8k_reg_clear(priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) QCA8K_PORT_LOOKUP_CTRL(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) BIT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /* Set the cpu port to be the only one in the portvlan mask of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * this port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) qca8k_port_enable(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct phy_device *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) qca8k_port_set_status(priv, port, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) priv->port_sts[port].enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (dsa_is_user_port(ds, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) phy_support_asym_pause(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) qca8k_port_disable(struct dsa_switch *ds, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) qca8k_port_set_status(priv, port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) priv->port_sts[port].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) int i, mtu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) priv->port_mtu[port] = new_mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) for (i = 0; i < QCA8K_NUM_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (priv->port_mtu[i] > mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) mtu = priv->port_mtu[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* Include L2 header / FCS length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) qca8k_port_max_mtu(struct dsa_switch *ds, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) return QCA8K_MAX_MTU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) u16 port_mask, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /* Set the vid to the port vlan id if no vid is set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (!vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) vid = QCA8K_PORT_VID_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return qca8k_fdb_add(priv, addr, port_mask, vid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) QCA8K_ATU_STATUS_STATIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) qca8k_port_fdb_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) const unsigned char *addr, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) u16 port_mask = BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) qca8k_port_fdb_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) const unsigned char *addr, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) u16 port_mask = BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (!vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) vid = QCA8K_PORT_VID_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return qca8k_fdb_del(priv, addr, port_mask, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) dsa_fdb_dump_cb_t *cb, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct qca8k_fdb _fdb = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) int cnt = QCA8K_NUM_FDB_RECORDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) bool is_static;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) mutex_lock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (!_fdb.aging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) ret = cb(_fdb.mac, _fdb.vid, is_static, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) mutex_unlock(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) struct switchdev_trans *trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (switchdev_trans_ph_prepare(trans))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (vlan_filtering) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) QCA8K_PORT_LOOKUP_VLAN_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) QCA8K_PORT_LOOKUP_VLAN_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) QCA8K_PORT_LOOKUP_VLAN_MODE_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) qca8k_port_vlan_prepare(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) qca8k_port_vlan_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) for (vid = vlan->vid_begin; vid <= vlan->vid_end && !ret; ++vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) ret = qca8k_vlan_add(priv, port, vid, untagged);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (pvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) int shift = 16 * (port % 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 0xfff << shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) vlan->vid_end << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) QCA8K_PORT_VLAN_CVID(vlan->vid_end) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) QCA8K_PORT_VLAN_SVID(vlan->vid_end));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) qca8k_port_vlan_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) struct qca8k_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) for (vid = vlan->vid_begin; vid <= vlan->vid_end && !ret; ++vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ret = qca8k_vlan_del(priv, port, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) static enum dsa_tag_protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) qca8k_get_tag_protocol(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) enum dsa_tag_protocol mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return DSA_TAG_PROTO_QCA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) static const struct dsa_switch_ops qca8k_switch_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) .get_tag_protocol = qca8k_get_tag_protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) .setup = qca8k_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) .get_strings = qca8k_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) .get_ethtool_stats = qca8k_get_ethtool_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) .get_sset_count = qca8k_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) .get_mac_eee = qca8k_get_mac_eee,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) .set_mac_eee = qca8k_set_mac_eee,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) .port_enable = qca8k_port_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) .port_disable = qca8k_port_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) .port_change_mtu = qca8k_port_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) .port_max_mtu = qca8k_port_max_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) .port_stp_state_set = qca8k_port_stp_state_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) .port_bridge_join = qca8k_port_bridge_join,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) .port_bridge_leave = qca8k_port_bridge_leave,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) .port_fdb_add = qca8k_port_fdb_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) .port_fdb_del = qca8k_port_fdb_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) .port_fdb_dump = qca8k_port_fdb_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) .port_vlan_filtering = qca8k_port_vlan_filtering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) .port_vlan_prepare = qca8k_port_vlan_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) .port_vlan_add = qca8k_port_vlan_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) .port_vlan_del = qca8k_port_vlan_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) .phylink_validate = qca8k_phylink_validate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) .phylink_mac_link_state = qca8k_phylink_mac_link_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) .phylink_mac_config = qca8k_phylink_mac_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) .phylink_mac_link_down = qca8k_phylink_mac_link_down,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) .phylink_mac_link_up = qca8k_phylink_mac_link_up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) qca8k_sw_probe(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) struct qca8k_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) /* allocate the private data struct so that we can probe the switches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * ID register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) priv->bus = mdiodev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) priv->dev = &mdiodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) GPIOD_ASIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) if (IS_ERR(priv->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) return PTR_ERR(priv->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (priv->reset_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) gpiod_set_value_cansleep(priv->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* The active low duration must be greater than 10 ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * and checkpatch.pl wants 20 ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) gpiod_set_value_cansleep(priv->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /* read the switches ID register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) id >>= QCA8K_MASK_CTRL_ID_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) id &= QCA8K_MASK_CTRL_ID_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (id != QCA8K_ID_QCA8337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (!priv->ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) priv->ds->dev = &mdiodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) priv->ds->num_ports = QCA8K_NUM_PORTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) priv->ds->configure_vlan_while_not_filtering = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) priv->ds->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) priv->ops = qca8k_switch_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) priv->ds->ops = &priv->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) mutex_init(&priv->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) dev_set_drvdata(&mdiodev->dev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return dsa_register_switch(priv->ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) qca8k_sw_remove(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) for (i = 0; i < QCA8K_NUM_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) qca8k_port_set_status(priv, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) dsa_unregister_switch(priv->ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) qca8k_set_pm(struct qca8k_priv *priv, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) for (i = 0; i < QCA8K_NUM_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (!priv->port_sts[i].enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) qca8k_port_set_status(priv, i, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) static int qca8k_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) struct qca8k_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) qca8k_set_pm(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) return dsa_switch_suspend(priv->ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) static int qca8k_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) struct qca8k_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) qca8k_set_pm(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) return dsa_switch_resume(priv->ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) qca8k_suspend, qca8k_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) static const struct of_device_id qca8k_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) { .compatible = "qca,qca8334" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) { .compatible = "qca,qca8337" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) static struct mdio_driver qca8kmdio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) .probe = qca8k_sw_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) .remove = qca8k_sw_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) .mdiodrv.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) .name = "qca8k",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) .of_match_table = qca8k_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) .pm = &qca8k_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) mdio_module_driver(qca8kmdio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) MODULE_AUTHOR("Mathieu Olivari, John Crispin <john@phrozen.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) MODULE_DESCRIPTION("Driver for QCA8K ethernet switch family");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) MODULE_ALIAS("platform:qca8k");