^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) /* Realtek SMI subdriver for the Realtek RTL8366RB ethernet switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This is a sparsely documented chip, the only viable documentation seems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * to be a patched up code drop from the vendor that appear in various
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * GPL source trees.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/irqchip/chained_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "realtek-smi-core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define RTL8366RB_PORT_NUM_CPU 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define RTL8366RB_NUM_PORTS 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define RTL8366RB_PHY_NO_MAX 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define RTL8366RB_PHY_ADDR_MAX 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Switch Global Configuration register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define RTL8366RB_SGCR 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define RTL8366RB_SGCR_EN_BC_STORM_CTRL BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define RTL8366RB_SGCR_MAX_LENGTH(a) ((a) << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define RTL8366RB_SGCR_MAX_LENGTH_MASK RTL8366RB_SGCR_MAX_LENGTH(0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define RTL8366RB_SGCR_MAX_LENGTH_1522 RTL8366RB_SGCR_MAX_LENGTH(0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define RTL8366RB_SGCR_MAX_LENGTH_1536 RTL8366RB_SGCR_MAX_LENGTH(0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RTL8366RB_SGCR_MAX_LENGTH_1552 RTL8366RB_SGCR_MAX_LENGTH(0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define RTL8366RB_SGCR_MAX_LENGTH_16000 RTL8366RB_SGCR_MAX_LENGTH(0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define RTL8366RB_SGCR_EN_VLAN BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define RTL8366RB_SGCR_EN_VLAN_4KTB BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Port Enable Control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define RTL8366RB_PECR 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Switch Security Control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define RTL8366RB_SSCR0 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define RTL8366RB_SSCR1 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define RTL8366RB_SSCR2 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define RTL8366RB_SSCR2_DROP_UNKNOWN_DA BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Port Mode Control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define RTL8366RB_PMC0 0x0005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define RTL8366RB_PMC0_SPI BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define RTL8366RB_PMC0_EN_AUTOLOAD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define RTL8366RB_PMC0_PROBE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define RTL8366RB_PMC0_DIS_BISR BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define RTL8366RB_PMC0_ADCTEST BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define RTL8366RB_PMC0_SRAM_DIAG BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define RTL8366RB_PMC0_EN_SCAN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define RTL8366RB_PMC0_P4_IOMODE_SHIFT 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define RTL8366RB_PMC0_P4_IOMODE_MASK GENMASK(9, 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define RTL8366RB_PMC0_P5_IOMODE_SHIFT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define RTL8366RB_PMC0_P5_IOMODE_MASK GENMASK(12, 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define RTL8366RB_PMC0_SDSMODE_SHIFT 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define RTL8366RB_PMC0_SDSMODE_MASK GENMASK(15, 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define RTL8366RB_PMC1 0x0006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* Port Mirror Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define RTL8366RB_PMCR 0x0007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define RTL8366RB_PMCR_SOURCE_PORT(a) (a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define RTL8366RB_PMCR_SOURCE_PORT_MASK 0x000f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define RTL8366RB_PMCR_MONITOR_PORT(a) ((a) << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define RTL8366RB_PMCR_MONITOR_PORT_MASK 0x00f0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define RTL8366RB_PMCR_MIRROR_RX BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define RTL8366RB_PMCR_MIRROR_TX BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define RTL8366RB_PMCR_MIRROR_SPC BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define RTL8366RB_PMCR_MIRROR_ISO BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* bits 0..7 = port 0, bits 8..15 = port 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define RTL8366RB_PAACR0 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* bits 0..7 = port 2, bits 8..15 = port 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define RTL8366RB_PAACR1 0x0011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* bits 0..7 = port 4, bits 8..15 = port 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define RTL8366RB_PAACR2 0x0012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define RTL8366RB_PAACR_SPEED_10M 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define RTL8366RB_PAACR_SPEED_100M 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define RTL8366RB_PAACR_SPEED_1000M 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define RTL8366RB_PAACR_FULL_DUPLEX BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define RTL8366RB_PAACR_LINK_UP BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define RTL8366RB_PAACR_TX_PAUSE BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define RTL8366RB_PAACR_RX_PAUSE BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define RTL8366RB_PAACR_AN BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define RTL8366RB_PAACR_CPU_PORT (RTL8366RB_PAACR_SPEED_1000M | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) RTL8366RB_PAACR_FULL_DUPLEX | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) RTL8366RB_PAACR_LINK_UP | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) RTL8366RB_PAACR_TX_PAUSE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) RTL8366RB_PAACR_RX_PAUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* bits 0..7 = port 0, bits 8..15 = port 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define RTL8366RB_PSTAT0 0x0014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* bits 0..7 = port 2, bits 8..15 = port 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define RTL8366RB_PSTAT1 0x0015
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* bits 0..7 = port 4, bits 8..15 = port 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define RTL8366RB_PSTAT2 0x0016
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define RTL8366RB_POWER_SAVING_REG 0x0021
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* CPU port control reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define RTL8368RB_CPU_CTRL_REG 0x0061
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define RTL8368RB_CPU_PORTS_MSK 0x00FF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Disables inserting custom tag length/type 0x8899 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define RTL8368RB_CPU_NO_TAG BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define RTL8366RB_SMAR0 0x0070 /* bits 0..15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define RTL8366RB_SMAR1 0x0071 /* bits 16..31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define RTL8366RB_SMAR2 0x0072 /* bits 32..47 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define RTL8366RB_RESET_CTRL_REG 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define RTL8366RB_CHIP_CTRL_RESET_HW BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define RTL8366RB_CHIP_CTRL_RESET_SW BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define RTL8366RB_CHIP_ID_REG 0x0509
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define RTL8366RB_CHIP_ID_8366 0x5937
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define RTL8366RB_CHIP_VERSION_CTRL_REG 0x050A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define RTL8366RB_CHIP_VERSION_MASK 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* PHY registers control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define RTL8366RB_PHY_ACCESS_CTRL_REG 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define RTL8366RB_PHY_CTRL_READ BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define RTL8366RB_PHY_CTRL_WRITE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define RTL8366RB_PHY_ACCESS_BUSY_REG 0x8001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define RTL8366RB_PHY_INT_BUSY BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define RTL8366RB_PHY_EXT_BUSY BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define RTL8366RB_PHY_ACCESS_DATA_REG 0x8002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define RTL8366RB_PHY_EXT_CTRL_REG 0x8010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define RTL8366RB_PHY_EXT_WRDATA_REG 0x8011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define RTL8366RB_PHY_EXT_RDDATA_REG 0x8012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define RTL8366RB_PHY_REG_MASK 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define RTL8366RB_PHY_PAGE_OFFSET 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define RTL8366RB_PHY_PAGE_MASK (0xf << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define RTL8366RB_PHY_NO_OFFSET 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define RTL8366RB_PHY_NO_MASK (0x1f << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* LED control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define RTL8366RB_LED_BLINKRATE_REG 0x0430
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define RTL8366RB_LED_BLINKRATE_MASK 0x0007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define RTL8366RB_LED_BLINKRATE_28MS 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define RTL8366RB_LED_BLINKRATE_56MS 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define RTL8366RB_LED_BLINKRATE_84MS 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define RTL8366RB_LED_BLINKRATE_111MS 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define RTL8366RB_LED_BLINKRATE_222MS 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define RTL8366RB_LED_BLINKRATE_446MS 0x0005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define RTL8366RB_LED_CTRL_REG 0x0431
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define RTL8366RB_LED_OFF 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define RTL8366RB_LED_DUP_COL 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define RTL8366RB_LED_LINK_ACT 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define RTL8366RB_LED_SPD1000 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define RTL8366RB_LED_SPD100 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define RTL8366RB_LED_SPD10 0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define RTL8366RB_LED_SPD1000_ACT 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define RTL8366RB_LED_SPD100_ACT 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define RTL8366RB_LED_SPD10_ACT 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define RTL8366RB_LED_SPD100_10_ACT 0x9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define RTL8366RB_LED_FIBER 0xa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define RTL8366RB_LED_AN_FAULT 0xb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define RTL8366RB_LED_LINK_RX 0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define RTL8366RB_LED_LINK_TX 0xd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define RTL8366RB_LED_MASTER 0xe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define RTL8366RB_LED_FORCE 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define RTL8366RB_LED_0_1_CTRL_REG 0x0432
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define RTL8366RB_LED_1_OFFSET 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define RTL8366RB_LED_2_3_CTRL_REG 0x0433
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define RTL8366RB_LED_3_OFFSET 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define RTL8366RB_MIB_COUNT 33
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define RTL8366RB_GLOBAL_MIB_COUNT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define RTL8366RB_MIB_COUNTER_PORT_OFFSET 0x0050
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define RTL8366RB_MIB_COUNTER_BASE 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define RTL8366RB_MIB_CTRL_REG 0x13F0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define RTL8366RB_MIB_CTRL_USER_MASK 0x0FFC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define RTL8366RB_MIB_CTRL_BUSY_MASK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define RTL8366RB_MIB_CTRL_RESET_MASK BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define RTL8366RB_MIB_CTRL_PORT_RESET(_p) BIT(2 + (_p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define RTL8366RB_MIB_CTRL_GLOBAL_RESET BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define RTL8366RB_PORT_VLAN_CTRL_BASE 0x0063
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define RTL8366RB_PORT_VLAN_CTRL_REG(_p) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) (RTL8366RB_PORT_VLAN_CTRL_BASE + (_p) / 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define RTL8366RB_PORT_VLAN_CTRL_MASK 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define RTL8366RB_PORT_VLAN_CTRL_SHIFT(_p) (4 * ((_p) % 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define RTL8366RB_VLAN_TABLE_READ_BASE 0x018C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define RTL8366RB_VLAN_TABLE_WRITE_BASE 0x0185
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define RTL8366RB_TABLE_ACCESS_CTRL_REG 0x0180
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define RTL8366RB_TABLE_VLAN_READ_CTRL 0x0E01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define RTL8366RB_TABLE_VLAN_WRITE_CTRL 0x0F01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define RTL8366RB_VLAN_MC_BASE(_x) (0x0020 + (_x) * 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define RTL8366RB_PORT_LINK_STATUS_BASE 0x0014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define RTL8366RB_PORT_STATUS_SPEED_MASK 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define RTL8366RB_PORT_STATUS_DUPLEX_MASK 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #define RTL8366RB_PORT_STATUS_LINK_MASK 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define RTL8366RB_PORT_STATUS_TXPAUSE_MASK 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define RTL8366RB_PORT_STATUS_RXPAUSE_MASK 0x0040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #define RTL8366RB_PORT_STATUS_AN_MASK 0x0080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #define RTL8366RB_NUM_VLANS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #define RTL8366RB_NUM_LEDGROUPS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #define RTL8366RB_NUM_VIDS 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define RTL8366RB_PRIORITYMAX 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #define RTL8366RB_FIDMAX 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #define RTL8366RB_PORT_1 BIT(0) /* In userspace port 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #define RTL8366RB_PORT_2 BIT(1) /* In userspace port 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define RTL8366RB_PORT_3 BIT(2) /* In userspace port 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define RTL8366RB_PORT_4 BIT(3) /* In userspace port 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define RTL8366RB_PORT_5 BIT(4) /* In userspace port 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define RTL8366RB_PORT_CPU BIT(5) /* CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define RTL8366RB_PORT_ALL (RTL8366RB_PORT_1 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) RTL8366RB_PORT_2 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) RTL8366RB_PORT_3 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) RTL8366RB_PORT_4 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) RTL8366RB_PORT_5 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) RTL8366RB_PORT_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define RTL8366RB_PORT_ALL_BUT_CPU (RTL8366RB_PORT_1 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) RTL8366RB_PORT_2 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) RTL8366RB_PORT_3 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) RTL8366RB_PORT_4 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) RTL8366RB_PORT_5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define RTL8366RB_PORT_ALL_EXTERNAL (RTL8366RB_PORT_1 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) RTL8366RB_PORT_2 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) RTL8366RB_PORT_3 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) RTL8366RB_PORT_4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #define RTL8366RB_PORT_ALL_INTERNAL RTL8366RB_PORT_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* First configuration word per member config, VID and prio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define RTL8366RB_VLAN_VID_MASK 0xfff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #define RTL8366RB_VLAN_PRIORITY_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #define RTL8366RB_VLAN_PRIORITY_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Second configuration word per member config, member and untagged */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #define RTL8366RB_VLAN_UNTAG_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define RTL8366RB_VLAN_UNTAG_MASK 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) #define RTL8366RB_VLAN_MEMBER_MASK 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Third config word per member config, STAG currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) #define RTL8366RB_VLAN_STAG_MBR_MASK 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #define RTL8366RB_VLAN_STAG_MBR_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) #define RTL8366RB_VLAN_STAG_IDX_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) #define RTL8366RB_VLAN_STAG_IDX_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #define RTL8366RB_VLAN_FID_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Port ingress bandwidth control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #define RTL8366RB_IB_BASE 0x0200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define RTL8366RB_IB_REG(pnum) (RTL8366RB_IB_BASE + (pnum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #define RTL8366RB_IB_BDTH_MASK 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #define RTL8366RB_IB_PREIFG BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Port egress bandwidth control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #define RTL8366RB_EB_BASE 0x02d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) #define RTL8366RB_EB_REG(pnum) (RTL8366RB_EB_BASE + (pnum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define RTL8366RB_EB_BDTH_MASK 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #define RTL8366RB_EB_PREIFG_REG 0x02f8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) #define RTL8366RB_EB_PREIFG BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #define RTL8366RB_BDTH_SW_MAX 1048512 /* 1048576? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) #define RTL8366RB_BDTH_UNIT 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) #define RTL8366RB_BDTH_REG_DEFAULT 16383
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* QOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #define RTL8366RB_QOS BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* Include/Exclude Preamble and IFG (20 bytes). 0:Exclude, 1:Include. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #define RTL8366RB_QOS_DEFAULT_PREIFG 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Interrupt handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define RTL8366RB_INTERRUPT_CONTROL_REG 0x0440
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #define RTL8366RB_INTERRUPT_POLARITY BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define RTL8366RB_P4_RGMII_LED BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #define RTL8366RB_INTERRUPT_MASK_REG 0x0441
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #define RTL8366RB_INTERRUPT_LINK_CHGALL GENMASK(11, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #define RTL8366RB_INTERRUPT_ACLEXCEED BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) #define RTL8366RB_INTERRUPT_STORMEXCEED BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define RTL8366RB_INTERRUPT_P4_FIBER BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define RTL8366RB_INTERRUPT_P4_UTP BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #define RTL8366RB_INTERRUPT_VALID (RTL8366RB_INTERRUPT_LINK_CHGALL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) RTL8366RB_INTERRUPT_ACLEXCEED | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) RTL8366RB_INTERRUPT_STORMEXCEED | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) RTL8366RB_INTERRUPT_P4_FIBER | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) RTL8366RB_INTERRUPT_P4_UTP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) #define RTL8366RB_INTERRUPT_STATUS_REG 0x0442
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #define RTL8366RB_NUM_INTERRUPT 14 /* 0..13 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* bits 0..5 enable force when cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #define RTL8366RB_MAC_FORCE_CTRL_REG 0x0F11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #define RTL8366RB_OAM_PARSER_REG 0x0F14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #define RTL8366RB_OAM_MULTIPLEXER_REG 0x0F15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #define RTL8366RB_GREEN_FEATURE_REG 0x0F51
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) #define RTL8366RB_GREEN_FEATURE_MSK 0x0007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #define RTL8366RB_GREEN_FEATURE_TX BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) #define RTL8366RB_GREEN_FEATURE_RX BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * struct rtl8366rb - RTL8366RB-specific data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * @max_mtu: per-port max MTU setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct rtl8366rb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) unsigned int max_mtu[RTL8366RB_NUM_PORTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { 0, 0, 4, "IfInOctets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { 0, 4, 4, "EtherStatsOctets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) { 0, 8, 2, "EtherStatsUnderSizePkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) { 0, 10, 2, "EtherFragments" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { 0, 12, 2, "EtherStatsPkts64Octets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) { 0, 14, 2, "EtherStatsPkts65to127Octets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { 0, 16, 2, "EtherStatsPkts128to255Octets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { 0, 18, 2, "EtherStatsPkts256to511Octets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) { 0, 20, 2, "EtherStatsPkts512to1023Octets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) { 0, 22, 2, "EtherStatsPkts1024to1518Octets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) { 0, 24, 2, "EtherOversizeStats" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) { 0, 26, 2, "EtherStatsJabbers" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) { 0, 28, 2, "IfInUcastPkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { 0, 30, 2, "EtherStatsMulticastPkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) { 0, 32, 2, "EtherStatsBroadcastPkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) { 0, 34, 2, "EtherStatsDropEvents" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) { 0, 36, 2, "Dot3StatsFCSErrors" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) { 0, 38, 2, "Dot3StatsSymbolErrors" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) { 0, 40, 2, "Dot3InPauseFrames" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) { 0, 42, 2, "Dot3ControlInUnknownOpcodes" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) { 0, 44, 4, "IfOutOctets" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) { 0, 48, 2, "Dot3StatsSingleCollisionFrames" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) { 0, 50, 2, "Dot3StatMultipleCollisionFrames" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) { 0, 52, 2, "Dot3sDeferredTransmissions" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) { 0, 54, 2, "Dot3StatsLateCollisions" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) { 0, 56, 2, "EtherStatsCollisions" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) { 0, 58, 2, "Dot3StatsExcessiveCollisions" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) { 0, 60, 2, "Dot3OutPauseFrames" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) { 0, 62, 2, "Dot1dBasePortDelayExceededDiscards" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) { 0, 64, 2, "Dot1dTpPortInDiscards" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) { 0, 66, 2, "IfOutUcastPkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) { 0, 68, 2, "IfOutMulticastPkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) { 0, 70, 2, "IfOutBroadcastPkts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int rtl8366rb_get_mib_counter(struct realtek_smi *smi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct rtl8366_mib_counter *mib,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) u64 *mibvalue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u32 addr, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) addr = RTL8366RB_MIB_COUNTER_BASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) RTL8366RB_MIB_COUNTER_PORT_OFFSET * (port) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) mib->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* Writing access counter address first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * then ASIC will prepare 64bits counter wait for being retrived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ret = regmap_write(smi->map, addr, 0); /* Write whatever */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* Read MIB control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ret = regmap_read(smi->map, RTL8366RB_MIB_CTRL_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (val & RTL8366RB_MIB_CTRL_BUSY_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (val & RTL8366RB_MIB_CTRL_RESET_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* Read each individual MIB 16 bits at the time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *mibvalue = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) for (i = mib->length; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ret = regmap_read(smi->map, addr + (i - 1), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *mibvalue = (*mibvalue << 16) | (val & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static u32 rtl8366rb_get_irqmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int line = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* For line interrupts we combine link down in bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * 6..11 with link up in bits 0..5 into one interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (line < 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) val = BIT(line) | BIT(line + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) val = BIT(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static void rtl8366rb_mask_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct realtek_smi *smi = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ret = regmap_update_bits(smi->map, RTL8366RB_INTERRUPT_MASK_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) rtl8366rb_get_irqmask(d), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_err(smi->dev, "could not mask IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static void rtl8366rb_unmask_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct realtek_smi *smi = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) ret = regmap_update_bits(smi->map, RTL8366RB_INTERRUPT_MASK_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) rtl8366rb_get_irqmask(d),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) rtl8366rb_get_irqmask(d));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) dev_err(smi->dev, "could not unmask IRQ\n");
^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 irqreturn_t rtl8366rb_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct realtek_smi *smi = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) u32 stat;
^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) /* This clears the IRQ status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ret = regmap_read(smi->map, RTL8366RB_INTERRUPT_STATUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) &stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dev_err(smi->dev, "can't read interrupt status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) stat &= RTL8366RB_INTERRUPT_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) while (stat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int line = __ffs(stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int child_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) stat &= ~BIT(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* For line interrupts we combine link down in bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * 6..11 with link up in bits 0..5 into one interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (line < 12 && line > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) line -= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) child_irq = irq_find_mapping(smi->irqdomain, line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) handle_nested_irq(child_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static struct irq_chip rtl8366rb_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .name = "RTL8366RB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .irq_mask = rtl8366rb_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .irq_unmask = rtl8366rb_unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static int rtl8366rb_irq_map(struct irq_domain *domain, unsigned int irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) irq_hw_number_t hwirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) irq_set_chip_data(irq, domain->host_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) irq_set_chip_and_handler(irq, &rtl8366rb_irq_chip, handle_simple_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) irq_set_nested_thread(irq, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) irq_set_noprobe(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static void rtl8366rb_irq_unmap(struct irq_domain *d, unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) irq_set_nested_thread(irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) irq_set_chip_and_handler(irq, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) irq_set_chip_data(irq, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static const struct irq_domain_ops rtl8366rb_irqdomain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .map = rtl8366rb_irq_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .unmap = rtl8366rb_irq_unmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) .xlate = irq_domain_xlate_onecell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct device_node *intc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) unsigned long irq_trig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) intc = of_get_child_by_name(smi->dev->of_node, "interrupt-controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (!intc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dev_err(smi->dev, "missing child interrupt-controller node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* RB8366RB IRQs cascade off this one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) irq = of_irq_get(intc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (irq <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) dev_err(smi->dev, "failed to get parent IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = irq ? irq : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* This clears the IRQ status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ret = regmap_read(smi->map, RTL8366RB_INTERRUPT_STATUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) dev_err(smi->dev, "can't read interrupt status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* Fetch IRQ edge information from the descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) switch (irq_trig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) case IRQF_TRIGGER_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) case IRQF_TRIGGER_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) dev_info(smi->dev, "active high/rising IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case IRQF_TRIGGER_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) case IRQF_TRIGGER_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) dev_info(smi->dev, "active low/falling IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) val = RTL8366RB_INTERRUPT_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ret = regmap_update_bits(smi->map, RTL8366RB_INTERRUPT_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) RTL8366RB_INTERRUPT_POLARITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) dev_err(smi->dev, "could not configure IRQ polarity\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ret = devm_request_threaded_irq(smi->dev, irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) rtl8366rb_irq, IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) "RTL8366RB", smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) dev_err(smi->dev, "unable to request irq: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) smi->irqdomain = irq_domain_add_linear(intc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) RTL8366RB_NUM_INTERRUPT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) &rtl8366rb_irqdomain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!smi->irqdomain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dev_err(smi->dev, "failed to create IRQ domain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) for (i = 0; i < smi->num_ports; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) irq_set_parent(irq_create_mapping(smi->irqdomain, i), irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) out_put_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) of_node_put(intc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static int rtl8366rb_set_addr(struct realtek_smi *smi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) u8 addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) eth_random_addr(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) dev_info(smi->dev, "set MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) val = addr[0] << 8 | addr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ret = regmap_write(smi->map, RTL8366RB_SMAR0, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) val = addr[2] << 8 | addr[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) ret = regmap_write(smi->map, RTL8366RB_SMAR1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) val = addr[4] << 8 | addr[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ret = regmap_write(smi->map, RTL8366RB_SMAR2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Found in a vendor driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* For the "version 0" early silicon, appear in most source releases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static const u16 rtl8366rb_init_jam_ver_0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 0x000B, 0x0001, 0x03A6, 0x0100, 0x03A7, 0x0001, 0x02D1, 0x3FFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 0x02D2, 0x3FFF, 0x02D3, 0x3FFF, 0x02D4, 0x3FFF, 0x02D5, 0x3FFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 0x02D6, 0x3FFF, 0x02D7, 0x3FFF, 0x02D8, 0x3FFF, 0x022B, 0x0688,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 0x022C, 0x0FAC, 0x03D0, 0x4688, 0x03D1, 0x01F5, 0x0000, 0x0830,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 0x02F9, 0x0200, 0x02F7, 0x7FFF, 0x02F8, 0x03FF, 0x0080, 0x03E8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 0x0081, 0x00CE, 0x0082, 0x00DA, 0x0083, 0x0230, 0xBE0F, 0x2000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 0x0231, 0x422A, 0x0232, 0x422A, 0x0233, 0x422A, 0x0234, 0x422A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 0x0235, 0x422A, 0x0236, 0x422A, 0x0237, 0x422A, 0x0238, 0x422A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 0x0239, 0x422A, 0x023A, 0x422A, 0x023B, 0x422A, 0x023C, 0x422A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 0x023D, 0x422A, 0x023E, 0x422A, 0x023F, 0x422A, 0x0240, 0x422A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 0x0241, 0x422A, 0x0242, 0x422A, 0x0243, 0x422A, 0x0244, 0x422A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 0x0245, 0x422A, 0x0246, 0x422A, 0x0247, 0x422A, 0x0248, 0x422A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 0x0249, 0x0146, 0x024A, 0x0146, 0x024B, 0x0146, 0xBE03, 0xC961,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 0x024D, 0x0146, 0x024E, 0x0146, 0x024F, 0x0146, 0x0250, 0x0146,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 0xBE64, 0x0226, 0x0252, 0x0146, 0x0253, 0x0146, 0x024C, 0x0146,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 0x0251, 0x0146, 0x0254, 0x0146, 0xBE62, 0x3FD0, 0x0084, 0x0320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 0x0255, 0x0146, 0x0256, 0x0146, 0x0257, 0x0146, 0x0258, 0x0146,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 0x0259, 0x0146, 0x025A, 0x0146, 0x025B, 0x0146, 0x025C, 0x0146,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 0x025D, 0x0146, 0x025E, 0x0146, 0x025F, 0x0146, 0x0260, 0x0146,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 0x0261, 0xA23F, 0x0262, 0x0294, 0x0263, 0xA23F, 0x0264, 0x0294,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 0x0265, 0xA23F, 0x0266, 0x0294, 0x0267, 0xA23F, 0x0268, 0x0294,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 0x0269, 0xA23F, 0x026A, 0x0294, 0x026B, 0xA23F, 0x026C, 0x0294,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 0x026D, 0xA23F, 0x026E, 0x0294, 0x026F, 0xA23F, 0x0270, 0x0294,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 0x02F5, 0x0048, 0xBE09, 0x0E00, 0xBE1E, 0x0FA0, 0xBE14, 0x8448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 0xBE15, 0x1007, 0xBE4A, 0xA284, 0xC454, 0x3F0B, 0xC474, 0x3F0B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 0xBE48, 0x3672, 0xBE4B, 0x17A7, 0xBE4C, 0x0B15, 0xBE52, 0x0EDD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 0xBE49, 0x8C00, 0xBE5B, 0x785C, 0xBE5C, 0x785C, 0xBE5D, 0x785C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 0xBE61, 0x368A, 0xBE63, 0x9B84, 0xC456, 0xCC13, 0xC476, 0xCC13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 0xBE65, 0x307D, 0xBE6D, 0x0005, 0xBE6E, 0xE120, 0xBE2E, 0x7BAF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* This v1 init sequence is from Belkin F5D8235 U-Boot release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static const u16 rtl8366rb_init_jam_ver_1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 0x0000, 0x0830, 0x0001, 0x8000, 0x0400, 0x8130, 0xBE78, 0x3C3C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 0x0431, 0x5432, 0xBE37, 0x0CE4, 0x02FA, 0xFFDF, 0x02FB, 0xFFE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 0xC44C, 0x1585, 0xC44C, 0x1185, 0xC44C, 0x1585, 0xC46C, 0x1585,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 0xC46C, 0x1185, 0xC46C, 0x1585, 0xC451, 0x2135, 0xC471, 0x2135,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 0xBE10, 0x8140, 0xBE15, 0x0007, 0xBE6E, 0xE120, 0xBE69, 0xD20F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 0xBE6B, 0x0320, 0xBE24, 0xB000, 0xBE23, 0xFF51, 0xBE22, 0xDF20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 0xBE21, 0x0140, 0xBE20, 0x00BB, 0xBE24, 0xB800, 0xBE24, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 0xBE24, 0x7000, 0xBE23, 0xFF51, 0xBE22, 0xDF60, 0xBE21, 0x0140,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 0xBE20, 0x0077, 0xBE24, 0x7800, 0xBE24, 0x0000, 0xBE2E, 0x7B7A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 0xBE36, 0x0CE4, 0x02F5, 0x0048, 0xBE77, 0x2940, 0x000A, 0x83E0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 0xBE79, 0x3C3C, 0xBE00, 0x1340,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* This v2 init sequence is from Belkin F5D8235 U-Boot release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static const u16 rtl8366rb_init_jam_ver_2[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 0x0450, 0x0000, 0x0400, 0x8130, 0x000A, 0x83ED, 0x0431, 0x5432,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 0xC44F, 0x6250, 0xC46F, 0x6250, 0xC456, 0x0C14, 0xC476, 0x0C14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 0xC44C, 0x1C85, 0xC44C, 0x1885, 0xC44C, 0x1C85, 0xC46C, 0x1C85,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 0xC46C, 0x1885, 0xC46C, 0x1C85, 0xC44C, 0x0885, 0xC44C, 0x0881,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 0xC44C, 0x0885, 0xC46C, 0x0885, 0xC46C, 0x0881, 0xC46C, 0x0885,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 0xBE2E, 0x7BA7, 0xBE36, 0x1000, 0xBE37, 0x1000, 0x8000, 0x0001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 0xBE69, 0xD50F, 0x8000, 0x0000, 0xBE69, 0xD50F, 0xBE6E, 0x0320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 0xBE77, 0x2940, 0xBE78, 0x3C3C, 0xBE79, 0x3C3C, 0xBE6E, 0xE120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 0x8000, 0x0001, 0xBE15, 0x1007, 0x8000, 0x0000, 0xBE15, 0x1007,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 0xBE14, 0x0448, 0xBE1E, 0x00A0, 0xBE10, 0x8160, 0xBE10, 0x8140,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 0xBE00, 0x1340, 0x0F51, 0x0010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* Appears in a DDWRT code dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static const u16 rtl8366rb_init_jam_ver_3[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 0x0000, 0x0830, 0x0400, 0x8130, 0x000A, 0x83ED, 0x0431, 0x5432,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 0x0F51, 0x0017, 0x02F5, 0x0048, 0x02FA, 0xFFDF, 0x02FB, 0xFFE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 0xC456, 0x0C14, 0xC476, 0x0C14, 0xC454, 0x3F8B, 0xC474, 0x3F8B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 0xC450, 0x2071, 0xC470, 0x2071, 0xC451, 0x226B, 0xC471, 0x226B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 0xC452, 0xA293, 0xC472, 0xA293, 0xC44C, 0x1585, 0xC44C, 0x1185,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 0xC44C, 0x1585, 0xC46C, 0x1585, 0xC46C, 0x1185, 0xC46C, 0x1585,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 0xC44C, 0x0185, 0xC44C, 0x0181, 0xC44C, 0x0185, 0xC46C, 0x0185,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 0xC46C, 0x0181, 0xC46C, 0x0185, 0xBE24, 0xB000, 0xBE23, 0xFF51,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 0xBE22, 0xDF20, 0xBE21, 0x0140, 0xBE20, 0x00BB, 0xBE24, 0xB800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 0xBE24, 0x0000, 0xBE24, 0x7000, 0xBE23, 0xFF51, 0xBE22, 0xDF60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 0xBE21, 0x0140, 0xBE20, 0x0077, 0xBE24, 0x7800, 0xBE24, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 0xBE2E, 0x7BA7, 0xBE36, 0x1000, 0xBE37, 0x1000, 0x8000, 0x0001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 0xBE69, 0xD50F, 0x8000, 0x0000, 0xBE69, 0xD50F, 0xBE6B, 0x0320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 0xBE77, 0x2800, 0xBE78, 0x3C3C, 0xBE79, 0x3C3C, 0xBE6E, 0xE120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 0x8000, 0x0001, 0xBE10, 0x8140, 0x8000, 0x0000, 0xBE10, 0x8140,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 0xBE15, 0x1007, 0xBE14, 0x0448, 0xBE1E, 0x00A0, 0xBE10, 0x8160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 0xBE10, 0x8140, 0xBE00, 0x1340, 0x0450, 0x0000, 0x0401, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /* Belkin F5D8235 v1, "belkin,f5d8235-v1" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static const u16 rtl8366rb_init_jam_f5d8235[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 0x0242, 0x02BF, 0x0245, 0x02BF, 0x0248, 0x02BF, 0x024B, 0x02BF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 0x024E, 0x02BF, 0x0251, 0x02BF, 0x0254, 0x0A3F, 0x0256, 0x0A3F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 0x0258, 0x0A3F, 0x025A, 0x0A3F, 0x025C, 0x0A3F, 0x025E, 0x0A3F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 0x0263, 0x007C, 0x0100, 0x0004, 0xBE5B, 0x3500, 0x800E, 0x200F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 0xBE1D, 0x0F00, 0x8001, 0x5011, 0x800A, 0xA2F4, 0x800B, 0x17A3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 0xBE4B, 0x17A3, 0xBE41, 0x5011, 0xBE17, 0x2100, 0x8000, 0x8304,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 0xBE40, 0x8304, 0xBE4A, 0xA2F4, 0x800C, 0xA8D5, 0x8014, 0x5500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 0x8015, 0x0004, 0xBE4C, 0xA8D5, 0xBE59, 0x0008, 0xBE09, 0x0E00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 0xBE36, 0x1036, 0xBE37, 0x1036, 0x800D, 0x00FF, 0xBE4D, 0x00FF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* DGN3500, "netgear,dgn3500", "netgear,dgn3500b" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static const u16 rtl8366rb_init_jam_dgn3500[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 0x0000, 0x0830, 0x0400, 0x8130, 0x000A, 0x83ED, 0x0F51, 0x0017,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 0x02F5, 0x0048, 0x02FA, 0xFFDF, 0x02FB, 0xFFE0, 0x0450, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 0x0401, 0x0000, 0x0431, 0x0960,
^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) /* This jam table activates "green ethernet", which means low power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * and is claimed to detect the cable length and not use more power than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * necessary, and the ports should enter power saving mode 10 seconds after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * a cable is disconnected. Seems to always be the same.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static const u16 rtl8366rb_green_jam[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {0xBE78, 0x323C}, {0xBE77, 0x5000}, {0xBE2E, 0x7BA7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {0xBE59, 0x3459}, {0xBE5A, 0x745A}, {0xBE5B, 0x785C},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {0xBE5C, 0x785C}, {0xBE6E, 0xE120}, {0xBE79, 0x323C},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static int rtl8366rb_setup(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct realtek_smi *smi = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) const u16 *jam_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct rtl8366rb *rb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) u32 chip_ver = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) u32 chip_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int jam_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) rb = smi->chip_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ret = regmap_read(smi->map, RTL8366RB_CHIP_ID_REG, &chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) dev_err(smi->dev, "unable to read chip id\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) switch (chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) case RTL8366RB_CHIP_ID_8366:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) dev_err(smi->dev, "unknown chip id (%04x)\n", chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ret = regmap_read(smi->map, RTL8366RB_CHIP_VERSION_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) &chip_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dev_err(smi->dev, "unable to read chip version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dev_info(smi->dev, "RTL%04x ver %u chip found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) chip_id, chip_ver & RTL8366RB_CHIP_VERSION_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* Do the init dance using the right jam table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) switch (chip_ver) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) jam_table = rtl8366rb_init_jam_ver_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) jam_size = ARRAY_SIZE(rtl8366rb_init_jam_ver_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) jam_table = rtl8366rb_init_jam_ver_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) jam_size = ARRAY_SIZE(rtl8366rb_init_jam_ver_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) jam_table = rtl8366rb_init_jam_ver_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) jam_size = ARRAY_SIZE(rtl8366rb_init_jam_ver_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) jam_table = rtl8366rb_init_jam_ver_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) jam_size = ARRAY_SIZE(rtl8366rb_init_jam_ver_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) /* Special jam tables for special routers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * TODO: are these necessary? Maintainers, please test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * without them, using just the off-the-shelf tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (of_machine_is_compatible("belkin,f5d8235-v1")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) jam_table = rtl8366rb_init_jam_f5d8235;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) jam_size = ARRAY_SIZE(rtl8366rb_init_jam_f5d8235);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (of_machine_is_compatible("netgear,dgn3500") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) of_machine_is_compatible("netgear,dgn3500b")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) jam_table = rtl8366rb_init_jam_dgn3500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) jam_size = ARRAY_SIZE(rtl8366rb_init_jam_dgn3500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) while (i < jam_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if ((jam_table[i] & 0xBE00) == 0xBE00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ret = regmap_read(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) RTL8366RB_PHY_ACCESS_BUSY_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (!(val & RTL8366RB_PHY_INT_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) RTL8366RB_PHY_ACCESS_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) RTL8366RB_PHY_CTRL_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) dev_dbg(smi->dev, "jam %04x into register %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) jam_table[i + 1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) jam_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) jam_table[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) jam_table[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) i += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* Set up the "green ethernet" feature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) while (i < ARRAY_SIZE(rtl8366rb_green_jam)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ret = regmap_read(smi->map, RTL8366RB_PHY_ACCESS_BUSY_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (!(val & RTL8366RB_PHY_INT_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) RTL8366RB_PHY_ACCESS_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) RTL8366RB_PHY_CTRL_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) rtl8366rb_green_jam[i][0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) rtl8366rb_green_jam[i][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) RTL8366RB_GREEN_FEATURE_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) (chip_ver == 1) ? 0x0007 : 0x0003);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* Vendor driver sets 0x240 in registers 0xc and 0xd (undocumented) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ret = regmap_write(smi->map, 0x0c, 0x240);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ret = regmap_write(smi->map, 0x0d, 0x240);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /* Set some random MAC address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) ret = rtl8366rb_set_addr(smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* Enable CPU port with custom DSA tag 8899.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * If you set RTL8368RB_CPU_NO_TAG (bit 15) in this registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * the custom tag is turned off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ret = regmap_update_bits(smi->map, RTL8368RB_CPU_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 0xFFFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) BIT(smi->cpu_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* Make sure we default-enable the fixed CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = regmap_update_bits(smi->map, RTL8366RB_PECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) BIT(smi->cpu_port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Set maximum packet length to 1536 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ret = regmap_update_bits(smi->map, RTL8366RB_SGCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) RTL8366RB_SGCR_MAX_LENGTH_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) RTL8366RB_SGCR_MAX_LENGTH_1536);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) for (i = 0; i < RTL8366RB_NUM_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* layer 2 size, see rtl8366rb_change_mtu() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) rb->max_mtu[i] = 1532;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Enable learning for all ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ret = regmap_write(smi->map, RTL8366RB_SSCR0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* Enable auto ageing for all ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ret = regmap_write(smi->map, RTL8366RB_SSCR1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /* Port 4 setup: this enables Port 4, usually the WAN port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * common PHY IO mode is apparently mode 0, and this is not what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * the port is initialized to. There is no explanation of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * IO modes in the Realtek source code, if your WAN port is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * connected to something exotic such as fiber, then this might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * be worth experimenting with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) ret = regmap_update_bits(smi->map, RTL8366RB_PMC0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) RTL8366RB_PMC0_P4_IOMODE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 0 << RTL8366RB_PMC0_P4_IOMODE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Discard VLAN tagged packets if the port is not a member of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * the VLAN with which the packets is associated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ret = regmap_write(smi->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) RTL8366RB_PORT_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* Don't drop packets whose DA has not been learned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ret = regmap_update_bits(smi->map, RTL8366RB_SSCR2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) RTL8366RB_SSCR2_DROP_UNKNOWN_DA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* Set blinking, TODO: make this configurable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ret = regmap_update_bits(smi->map, RTL8366RB_LED_BLINKRATE_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) RTL8366RB_LED_BLINKRATE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) RTL8366RB_LED_BLINKRATE_56MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /* Set up LED activity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Each port has 4 LEDs, we configure all ports to the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * behaviour (no individual config) but we can set up each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * LED separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (smi->leds_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* Turn everything off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) RTL8366RB_LED_0_1_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 0x0FFF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) RTL8366RB_LED_2_3_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 0x0FFF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) RTL8366RB_INTERRUPT_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) RTL8366RB_P4_RGMII_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) val = RTL8366RB_LED_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* TODO: make this configurable per LED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) val = RTL8366RB_LED_FORCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) ret = regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) RTL8366RB_LED_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 0xf << (i * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) val << (i * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ret = rtl8366_init_vlan(smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) ret = rtl8366rb_setup_cascaded_irq(smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) dev_info(smi->dev, "no interrupt support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) ret = realtek_smi_setup_mdio(smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) dev_info(smi->dev, "could not set up MDIO bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static enum dsa_tag_protocol rtl8366_get_tag_protocol(struct dsa_switch *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) enum dsa_tag_protocol mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /* This switch uses the 4 byte protocol A Realtek DSA tag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return DSA_TAG_PROTO_RTL4_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) rtl8366rb_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) phy_interface_t interface, struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) int speed, int duplex, bool tx_pause, bool rx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct realtek_smi *smi = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (port != smi->cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) dev_dbg(smi->dev, "MAC link up on CPU port (%d)\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* Force the fixed CPU port into 1Gbit mode, no autonegotiation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ret = regmap_update_bits(smi->map, RTL8366RB_MAC_FORCE_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) BIT(port), BIT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) dev_err(smi->dev, "failed to force 1Gbit on CPU port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) ret = regmap_update_bits(smi->map, RTL8366RB_PAACR2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 0xFF00U,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) RTL8366RB_PAACR_CPU_PORT << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) dev_err(smi->dev, "failed to set PAACR on CPU port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* Enable the CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) dev_err(smi->dev, "failed to enable the CPU port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) rtl8366rb_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) phy_interface_t interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct realtek_smi *smi = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (port != smi->cpu_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dev_dbg(smi->dev, "MAC link down on CPU port (%d)\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* Disable the CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) BIT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) dev_err(smi->dev, "failed to disable the CPU port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) static void rb8366rb_set_port_led(struct realtek_smi *smi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) int port, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) u16 val = enable ? 0x3f : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (smi->leds_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) switch (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) ret = regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) RTL8366RB_LED_0_1_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 0x3F, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) ret = regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) RTL8366RB_LED_0_1_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 0x3F << RTL8366RB_LED_1_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) val << RTL8366RB_LED_1_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ret = regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) RTL8366RB_LED_2_3_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 0x3F, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ret = regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) RTL8366RB_LED_2_3_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 0x3F << RTL8366RB_LED_3_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) val << RTL8366RB_LED_3_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) ret = regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) RTL8366RB_INTERRUPT_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) RTL8366RB_P4_RGMII_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) enable ? RTL8366RB_P4_RGMII_LED : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) dev_err(smi->dev, "no LED for port %d\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) dev_err(smi->dev, "error updating LED on port %d\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) rtl8366rb_port_enable(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct phy_device *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct realtek_smi *smi = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) dev_dbg(smi->dev, "enable port %d\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) rb8366rb_set_port_led(smi, port, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) rtl8366rb_port_disable(struct dsa_switch *ds, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) struct realtek_smi *smi = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) dev_dbg(smi->dev, "disable port %d\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) BIT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) rb8366rb_set_port_led(smi, port, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct realtek_smi *smi = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct rtl8366rb *rb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) unsigned int max_mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) /* Cache the per-port MTU setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) rb = smi->chip_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) rb->max_mtu[port] = new_mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) /* Roof out the MTU for the entire switch to the greatest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) * common denominator: the biggest set for any one port will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) * be the biggest MTU for the switch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * The first setting, 1522 bytes, is max IP packet 1500 bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * plus ethernet header, 1518 bytes, plus CPU tag, 4 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * This function should consider the parameter an SDU, so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * MTU passed for this setting is 1518 bytes. The same logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * of subtracting the DSA tag of 4 bytes apply to the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) max_mtu = 1518;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) for (i = 0; i < RTL8366RB_NUM_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (rb->max_mtu[i] > max_mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) max_mtu = rb->max_mtu[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (max_mtu <= 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) len = RTL8366RB_SGCR_MAX_LENGTH_1522;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) else if (max_mtu > 1518 && max_mtu <= 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) len = RTL8366RB_SGCR_MAX_LENGTH_1536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) else if (max_mtu > 1532 && max_mtu <= 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) len = RTL8366RB_SGCR_MAX_LENGTH_1552;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) len = RTL8366RB_SGCR_MAX_LENGTH_16000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return regmap_update_bits(smi->map, RTL8366RB_SGCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) RTL8366RB_SGCR_MAX_LENGTH_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) len);
^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 int rtl8366rb_max_mtu(struct dsa_switch *ds, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) /* The max MTU is 16000 bytes, so we subtract the CPU tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * and the max presented to the system is 15996 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return 15996;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) static int rtl8366rb_get_vlan_4k(struct realtek_smi *smi, u32 vid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) struct rtl8366_vlan_4k *vlan4k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) u32 data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (vid >= RTL8366RB_NUM_VIDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /* write VID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) ret = regmap_write(smi->map, RTL8366RB_VLAN_TABLE_WRITE_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) vid & RTL8366RB_VLAN_VID_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) /* write table access control word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ret = regmap_write(smi->map, RTL8366RB_TABLE_ACCESS_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) RTL8366RB_TABLE_VLAN_READ_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) ret = regmap_read(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) RTL8366RB_VLAN_TABLE_READ_BASE + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) &data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) vlan4k->vid = vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) vlan4k->untag = (data[1] >> RTL8366RB_VLAN_UNTAG_SHIFT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) RTL8366RB_VLAN_UNTAG_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) vlan4k->member = data[1] & RTL8366RB_VLAN_MEMBER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) vlan4k->fid = data[2] & RTL8366RB_VLAN_FID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) static int rtl8366rb_set_vlan_4k(struct realtek_smi *smi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) const struct rtl8366_vlan_4k *vlan4k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) u32 data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (vlan4k->vid >= RTL8366RB_NUM_VIDS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) vlan4k->member > RTL8366RB_VLAN_MEMBER_MASK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) vlan4k->untag > RTL8366RB_VLAN_UNTAG_MASK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) vlan4k->fid > RTL8366RB_FIDMAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) data[0] = vlan4k->vid & RTL8366RB_VLAN_VID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) data[1] = (vlan4k->member & RTL8366RB_VLAN_MEMBER_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ((vlan4k->untag & RTL8366RB_VLAN_UNTAG_MASK) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) RTL8366RB_VLAN_UNTAG_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) data[2] = vlan4k->fid & RTL8366RB_VLAN_FID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) RTL8366RB_VLAN_TABLE_WRITE_BASE + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /* write table access control word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) ret = regmap_write(smi->map, RTL8366RB_TABLE_ACCESS_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) RTL8366RB_TABLE_VLAN_WRITE_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) static int rtl8366rb_get_vlan_mc(struct realtek_smi *smi, u32 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) struct rtl8366_vlan_mc *vlanmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) u32 data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (index >= RTL8366RB_NUM_VLANS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) ret = regmap_read(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) RTL8366RB_VLAN_MC_BASE(index) + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) &data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) vlanmc->vid = data[0] & RTL8366RB_VLAN_VID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) vlanmc->priority = (data[0] >> RTL8366RB_VLAN_PRIORITY_SHIFT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) RTL8366RB_VLAN_PRIORITY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) vlanmc->untag = (data[1] >> RTL8366RB_VLAN_UNTAG_SHIFT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) RTL8366RB_VLAN_UNTAG_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) vlanmc->member = data[1] & RTL8366RB_VLAN_MEMBER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) vlanmc->fid = data[2] & RTL8366RB_VLAN_FID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) static int rtl8366rb_set_vlan_mc(struct realtek_smi *smi, u32 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) const struct rtl8366_vlan_mc *vlanmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) u32 data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (index >= RTL8366RB_NUM_VLANS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) vlanmc->vid >= RTL8366RB_NUM_VIDS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) vlanmc->priority > RTL8366RB_PRIORITYMAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) vlanmc->member > RTL8366RB_VLAN_MEMBER_MASK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) vlanmc->untag > RTL8366RB_VLAN_UNTAG_MASK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) vlanmc->fid > RTL8366RB_FIDMAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) data[0] = (vlanmc->vid & RTL8366RB_VLAN_VID_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) ((vlanmc->priority & RTL8366RB_VLAN_PRIORITY_MASK) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) RTL8366RB_VLAN_PRIORITY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) data[1] = (vlanmc->member & RTL8366RB_VLAN_MEMBER_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) ((vlanmc->untag & RTL8366RB_VLAN_UNTAG_MASK) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) RTL8366RB_VLAN_UNTAG_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) data[2] = vlanmc->fid & RTL8366RB_VLAN_FID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) ret = regmap_write(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) RTL8366RB_VLAN_MC_BASE(index) + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) static int rtl8366rb_get_mc_index(struct realtek_smi *smi, int port, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (port >= smi->num_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) ret = regmap_read(smi->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) *val = (data >> RTL8366RB_PORT_VLAN_CTRL_SHIFT(port)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) RTL8366RB_PORT_VLAN_CTRL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) static int rtl8366rb_set_mc_index(struct realtek_smi *smi, int port, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (port >= smi->num_ports || index >= RTL8366RB_NUM_VLANS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return regmap_update_bits(smi->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) RTL8366RB_PORT_VLAN_CTRL_MASK <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) RTL8366RB_PORT_VLAN_CTRL_SHIFT(port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) (index & RTL8366RB_PORT_VLAN_CTRL_MASK) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) RTL8366RB_PORT_VLAN_CTRL_SHIFT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) unsigned int max = RTL8366RB_NUM_VLANS - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (smi->vlan4k_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) max = RTL8366RB_NUM_VIDS - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (vlan == 0 || vlan > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) static int rtl8366rb_enable_vlan(struct realtek_smi *smi, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) dev_dbg(smi->dev, "%s VLAN\n", enable ? "enable" : "disable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) return regmap_update_bits(smi->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) RTL8366RB_SGCR, RTL8366RB_SGCR_EN_VLAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) enable ? RTL8366RB_SGCR_EN_VLAN : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) static int rtl8366rb_enable_vlan4k(struct realtek_smi *smi, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) dev_dbg(smi->dev, "%s VLAN 4k\n", enable ? "enable" : "disable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return regmap_update_bits(smi->map, RTL8366RB_SGCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) RTL8366RB_SGCR_EN_VLAN_4KTB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) enable ? RTL8366RB_SGCR_EN_VLAN_4KTB : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) static int rtl8366rb_phy_read(struct realtek_smi *smi, int phy, int regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (phy > RTL8366RB_PHY_NO_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ret = regmap_write(smi->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) RTL8366RB_PHY_CTRL_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) reg = 0x8000 | (1 << (phy + RTL8366RB_PHY_NO_OFFSET)) | regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) ret = regmap_write(smi->map, reg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) dev_err(smi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) "failed to write PHY%d reg %04x @ %04x, ret %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) phy, regnum, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) ret = regmap_read(smi->map, RTL8366RB_PHY_ACCESS_DATA_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) dev_dbg(smi->dev, "read PHY%d register 0x%04x @ %08x, val <- %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) phy, regnum, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) static int rtl8366rb_phy_write(struct realtek_smi *smi, int phy, int regnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) if (phy > RTL8366RB_PHY_NO_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) ret = regmap_write(smi->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) RTL8366RB_PHY_CTRL_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) reg = 0x8000 | (1 << (phy + RTL8366RB_PHY_NO_OFFSET)) | regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) dev_dbg(smi->dev, "write PHY%d register 0x%04x @ %04x, val -> %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) phy, regnum, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) ret = regmap_write(smi->map, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) static int rtl8366rb_reset_chip(struct realtek_smi *smi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) int timeout = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) realtek_smi_write_reg_noack(smi, RTL8366RB_RESET_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) RTL8366RB_CHIP_CTRL_RESET_HW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) usleep_range(20000, 25000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) ret = regmap_read(smi->map, RTL8366RB_RESET_CTRL_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) if (!(val & RTL8366RB_CHIP_CTRL_RESET_HW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) } while (--timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) dev_err(smi->dev, "timeout waiting for the switch to reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return 0;
^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 int rtl8366rb_detect(struct realtek_smi *smi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) struct device *dev = smi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) /* Detect device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) ret = regmap_read(smi->map, 0x5c, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) dev_err(dev, "can't get chip ID (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) case 0x6027:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) dev_info(dev, "found an RTL8366S switch\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) dev_err(dev, "this switch is not yet supported, submit patches!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) case 0x5937:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) dev_info(dev, "found an RTL8366RB switch\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) smi->cpu_port = RTL8366RB_PORT_NUM_CPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) smi->num_ports = RTL8366RB_NUM_PORTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) smi->num_vlan_mc = RTL8366RB_NUM_VLANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) smi->mib_counters = rtl8366rb_mib_counters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) smi->num_mib_counters = ARRAY_SIZE(rtl8366rb_mib_counters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) dev_info(dev, "found an Unknown Realtek switch (id=0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) ret = rtl8366rb_reset_chip(smi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) static const struct dsa_switch_ops rtl8366rb_switch_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) .get_tag_protocol = rtl8366_get_tag_protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) .setup = rtl8366rb_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .phylink_mac_link_up = rtl8366rb_mac_link_up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .phylink_mac_link_down = rtl8366rb_mac_link_down,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) .get_strings = rtl8366_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) .get_ethtool_stats = rtl8366_get_ethtool_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) .get_sset_count = rtl8366_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) .port_vlan_filtering = rtl8366_vlan_filtering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) .port_vlan_prepare = rtl8366_vlan_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) .port_vlan_add = rtl8366_vlan_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) .port_vlan_del = rtl8366_vlan_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) .port_enable = rtl8366rb_port_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) .port_disable = rtl8366rb_port_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) .port_change_mtu = rtl8366rb_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) .port_max_mtu = rtl8366rb_max_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) static const struct realtek_smi_ops rtl8366rb_smi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) .detect = rtl8366rb_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) .get_vlan_mc = rtl8366rb_get_vlan_mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) .set_vlan_mc = rtl8366rb_set_vlan_mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) .get_vlan_4k = rtl8366rb_get_vlan_4k,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) .set_vlan_4k = rtl8366rb_set_vlan_4k,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) .get_mc_index = rtl8366rb_get_mc_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) .set_mc_index = rtl8366rb_set_mc_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) .get_mib_counter = rtl8366rb_get_mib_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) .is_vlan_valid = rtl8366rb_is_vlan_valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) .enable_vlan = rtl8366rb_enable_vlan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) .enable_vlan4k = rtl8366rb_enable_vlan4k,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) .phy_read = rtl8366rb_phy_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) .phy_write = rtl8366rb_phy_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) const struct realtek_smi_variant rtl8366rb_variant = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) .ds_ops = &rtl8366rb_switch_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) .ops = &rtl8366rb_smi_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) .clk_delay = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) .cmd_read = 0xa9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) .cmd_write = 0xa8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) .chip_data_sz = sizeof(struct rtl8366rb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) EXPORT_SYMBOL_GPL(rtl8366rb_variant);