1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
3 * Copyright (c) 2018 Microsemi Corporation
9 #include <dm/of_access.h>
10 #include <dm/of_addr.h>
11 #include <fdt_support.h>
13 #include <linux/ioport.h>
18 #include <dt-bindings/mscc/jr2_data.h>
19 #include "mscc_xfer.h"
21 #define GCB_MIIM_MII_STATUS 0x0
22 #define GCB_MIIM_STAT_BUSY BIT(3)
23 #define GCB_MIIM_MII_CMD 0x8
24 #define GCB_MIIM_MII_CMD_SCAN BIT(0)
25 #define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
26 #define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
27 #define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
28 #define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
29 #define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
30 #define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
31 #define GCB_MIIM_MII_CMD_VLD BIT(31)
32 #define GCB_MIIM_DATA 0xC
33 #define GCB_MIIM_DATA_ERROR (0x3 << 16)
35 #define ANA_AC_RAM_CTRL_RAM_INIT 0x94358
36 #define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
38 #define ANA_CL_PORT_VLAN_CFG(x) (0x24018 + 0xc8 * (x))
39 #define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19)
40 #define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17)
42 #define ANA_L2_COMMON_FWD_CFG 0x8a2a8
43 #define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
45 #define ASM_CFG_STAT_CFG 0x3508
46 #define ASM_CFG_PORT(x) (0x36c4 + 0x4 * (x))
47 #define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8)
48 #define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1)
49 #define ASM_RAM_CTRL_RAM_INIT 0x39b8
51 #define DEV_DEV_CFG_DEV_RST_CTRL 0x0
52 #define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20)
53 #define DEV_MAC_CFG_MAC_ENA 0x1c
54 #define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4)
55 #define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0)
56 #define DEV_MAC_CFG_MAC_IFG 0x34
57 #define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8)
58 #define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4)
59 #define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x)
60 #define DEV_PCS1G_CFG_PCS1G_CFG 0x40
61 #define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0)
62 #define DEV_PCS1G_CFG_PCS1G_MODE 0x44
63 #define DEV_PCS1G_CFG_PCS1G_SD 0x48
64 #define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c
65 #define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
67 #define DSM_RAM_CTRL_RAM_INIT 0x8
69 #define HSIO_ANA_SERDES1G_DES_CFG 0xac
70 #define HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x) ((x) << 1)
71 #define HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x) ((x) << 5)
72 #define HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x) ((x) << 8)
73 #define HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x) ((x) << 13)
74 #define HSIO_ANA_SERDES1G_IB_CFG 0xb0
75 #define HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x) (x)
76 #define HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x) ((x) << 6)
77 #define HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP BIT(9)
78 #define HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV BIT(11)
79 #define HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM BIT(13)
80 #define HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x) ((x) << 19)
81 #define HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x) ((x) << 24)
82 #define HSIO_ANA_SERDES1G_OB_CFG 0xb4
83 #define HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x) (x)
84 #define HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x) ((x) << 4)
85 #define HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x) ((x) << 10)
86 #define HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x) ((x) << 13)
87 #define HSIO_ANA_SERDES1G_OB_CFG_SLP(x) ((x) << 17)
88 #define HSIO_ANA_SERDES1G_SER_CFG 0xb8
89 #define HSIO_ANA_SERDES1G_COMMON_CFG 0xbc
90 #define HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE BIT(0)
91 #define HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE BIT(18)
92 #define HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST BIT(31)
93 #define HSIO_ANA_SERDES1G_PLL_CFG 0xc0
94 #define HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA BIT(7)
95 #define HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8)
96 #define HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2 BIT(21)
97 #define HSIO_DIG_SERDES1G_DFT_CFG0 0xc8
98 #define HSIO_DIG_SERDES1G_TP_CFG 0xd4
99 #define HSIO_DIG_SERDES1G_MISC_CFG 0xdc
100 #define HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST BIT(0)
101 #define HSIO_MCB_SERDES1G_CFG 0xe8
102 #define HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT BIT(31)
103 #define HSIO_MCB_SERDES1G_CFG_ADDR(x) (x)
105 #define HSIO_ANA_SERDES6G_DES_CFG 0x11c
106 #define HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA BIT(0)
107 #define HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x) ((x) << 1)
108 #define HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST BIT(4)
109 #define HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x) ((x) << 5)
110 #define HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x) ((x) << 8)
111 #define HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x) ((x) << 10)
112 #define HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x) ((x) << 13)
113 #define HSIO_ANA_SERDES6G_IB_CFG 0x120
114 #define HSIO_ANA_SERDES6G_IB_CFG_REG_ENA BIT(0)
115 #define HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA BIT(1)
116 #define HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA BIT(2)
117 #define HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x) ((x) << 3)
118 #define HSIO_ANA_SERDES6G_IB_CFG_CONCUR BIT(4)
119 #define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA BIT(5)
120 #define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x) ((x) << 7)
121 #define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x) ((x) << 9)
122 #define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x) ((x) << 11)
123 #define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x) ((x) << 13)
124 #define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x) ((x) << 15)
125 #define HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x) ((x) << 18)
126 #define HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x) ((x) << 20)
127 #define HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x) ((x) << 24)
128 #define HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL BIT(28)
129 #define HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x) ((x) << 29)
130 #define HSIO_ANA_SERDES6G_IB_CFG1 0x124
131 #define HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET BIT(4)
132 #define HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP BIT(5)
133 #define HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID BIT(6)
134 #define HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP BIT(7)
135 #define HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x) ((x) << 8)
136 #define HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x) ((x) << 12)
137 #define HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x) ((x) << 17)
138 #define HSIO_ANA_SERDES6G_IB_CFG2 0x128
139 #define HSIO_ANA_SERDES6G_IB_CFG2_UREG(x) (x)
140 #define HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x) ((x) << 3)
141 #define HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x) ((x) << 5)
142 #define HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x) ((x) << 10)
143 #define HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x) ((x) << 16)
144 #define HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x) ((x) << 22)
145 #define HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x) ((x) << 27)
146 #define HSIO_ANA_SERDES6G_IB_CFG3 0x12c
147 #define HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x) (x)
148 #define HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x) ((x) << 6)
149 #define HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x) ((x) << 12)
150 #define HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x) ((x) << 18)
151 #define HSIO_ANA_SERDES6G_IB_CFG4 0x130
152 #define HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x) (x)
153 #define HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x) ((x) << 6)
154 #define HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x) ((x) << 12)
155 #define HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x) ((x) << 18)
156 #define HSIO_ANA_SERDES6G_IB_CFG5 0x134
157 #define HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x) (x)
158 #define HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x) ((x) << 6)
159 #define HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x) ((x) << 12)
160 #define HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x) ((x) << 18)
161 #define HSIO_ANA_SERDES6G_OB_CFG 0x138
162 #define HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x) (x)
163 #define HSIO_ANA_SERDES6G_OB_CFG_SR(x) ((x) << 4)
164 #define HSIO_ANA_SERDES6G_OB_CFG_SR_H BIT(8)
165 #define HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL BIT(9)
166 #define HSIO_ANA_SERDES6G_OB_CFG_R_COR BIT(10)
167 #define HSIO_ANA_SERDES6G_OB_CFG_POST1(x) ((x) << 11)
168 #define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR BIT(16)
169 #define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX BIT(17)
170 #define HSIO_ANA_SERDES6G_OB_CFG_PREC(x) ((x) << 18)
171 #define HSIO_ANA_SERDES6G_OB_CFG_POST0(x) ((x) << 23)
172 #define HSIO_ANA_SERDES6G_OB_CFG_POL BIT(29)
173 #define HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x) ((x) << 30)
174 #define HSIO_ANA_SERDES6G_OB_CFG_IDLE BIT(31)
175 #define HSIO_ANA_SERDES6G_OB_CFG1 0x13c
176 #define HSIO_ANA_SERDES6G_OB_CFG1_LEV(x) (x)
177 #define HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x) ((x) << 6)
178 #define HSIO_ANA_SERDES6G_SER_CFG 0x140
179 #define HSIO_ANA_SERDES6G_COMMON_CFG 0x144
180 #define HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x) (x)
181 #define HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x) (x << 2)
182 #define HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE BIT(14)
183 #define HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST BIT(16)
184 #define HSIO_ANA_SERDES6G_PLL_CFG 0x148
185 #define HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ BIT(0)
186 #define HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR BIT(1)
187 #define HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL BIT(2)
188 #define HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA BIT(3)
189 #define HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA BIT(4)
190 #define HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA BIT(5)
191 #define HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 6)
192 #define HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT BIT(14)
193 #define HSIO_ANA_SERDES6G_PLL_CFG_DIV4 BIT(15)
194 #define HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x) ((x) << 16)
195 #define HSIO_DIG_SERDES6G_MISC_CFG 0x108
196 #define HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST BIT(0)
197 #define HSIO_MCB_SERDES6G_CFG 0x168
198 #define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31)
199 #define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x)
200 #define HSIO_HW_CFGSTAT_HW_CFG 0x16c
202 #define LRN_COMMON_ACCESS_CTRL 0x0
203 #define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0)
204 #define LRN_COMMON_MAC_ACCESS_CFG0 0x4
205 #define LRN_COMMON_MAC_ACCESS_CFG1 0x8
206 #define LRN_COMMON_MAC_ACCESS_CFG2 0xc
207 #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x)
208 #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12)
209 #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15)
210 #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16)
211 #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23)
212 #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24)
214 #define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4 * (x))
215 #define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17)
217 #define QS_XTR_GRP_CFG(x) (0x0 + 4 * (x))
218 #define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4)
220 #define QSYS_SYSTEM_RESET_CFG 0xf0
221 #define QSYS_CALCFG_CAL_AUTO(x) (0x3d4 + 4 * (x))
222 #define QSYS_CALCFG_CAL_CTRL 0x3e8
223 #define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11)
224 #define QSYS_RAM_CTRL_RAM_INIT 0x3ec
226 #define REW_RAM_CTRL_RAM_INIT 0x53528
228 #define VOP_RAM_CTRL_RAM_INIT 0x43638
230 #define XTR_VALID_BYTES(x) (4 - ((x) & 3))
234 #define JR2_BUF_CELL_SZ 60
236 #define PGID_BROADCAST 510
237 #define PGID_UNICAST 511
239 static const char * const regs_names[] = {
240 "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
241 "port8", "port9", "port10", "port11", "port12", "port13", "port14",
242 "port15", "port16", "port17", "port18", "port19", "port20", "port21",
243 "port22", "port23", "port24", "port25", "port26", "port27", "port28",
244 "port29", "port30", "port31", "port32", "port33", "port34", "port35",
245 "port36", "port37", "port38", "port39", "port40", "port41", "port42",
246 "port43", "port44", "port45", "port46", "port47",
247 "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
248 "qfwd", "qs", "qsys", "rew",
251 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
267 #define JR2_MIIM_BUS_COUNT 3
269 struct jr2_phy_port_t {
277 void __iomem *regs[REGS_NAMES_COUNT];
278 struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
279 struct jr2_phy_port_t ports[MAX_PORT];
282 struct jr2_miim_dev {
284 phys_addr_t miim_base;
285 unsigned long miim_size;
289 static const unsigned long jr2_regs_qs[] = {
290 [MSCC_QS_XTR_RD] = 0x8,
291 [MSCC_QS_XTR_FLUSH] = 0x18,
292 [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
293 [MSCC_QS_INJ_WR] = 0x2c,
294 [MSCC_QS_INJ_CTRL] = 0x34,
297 static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT];
298 static int miim_count = -1;
300 static int mscc_miim_wait_ready(struct jr2_miim_dev *miim)
302 unsigned long deadline;
305 deadline = timer_get_us() + 250000;
308 val = readl(miim->regs + GCB_MIIM_MII_STATUS);
309 } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
311 if (val & GCB_MIIM_STAT_BUSY)
317 static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
319 struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
323 ret = mscc_miim_wait_ready(miim);
327 writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
328 GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
329 miim->regs + GCB_MIIM_MII_CMD);
331 ret = mscc_miim_wait_ready(miim);
335 val = readl(miim->regs + GCB_MIIM_DATA);
336 if (val & GCB_MIIM_DATA_ERROR) {
346 static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
349 struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
352 ret = mscc_miim_wait_ready(miim);
356 writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
357 GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
358 GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
364 static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
365 unsigned long miim_size)
374 sprintf(bus->name, "miim-bus%d", miim_count);
376 miim[miim_count].regs = ioremap(miim_base, miim_size);
377 miim[miim_count].miim_base = miim_base;
378 miim[miim_count].miim_size = miim_size;
379 bus->priv = &miim[miim_count];
380 bus->read = mscc_miim_read;
381 bus->write = mscc_miim_write;
383 if (mdio_register(bus))
386 miim[miim_count].bus = bus;
390 static void jr2_cpu_capture_setup(struct jr2_private *priv)
392 /* ASM: No preamble and IFH prefix on CPU injected frames */
393 writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
394 ASM_CFG_PORT_INJ_FORMAT_CFG(1),
395 priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
397 /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
398 writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
400 /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
401 writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
403 /* Enable CPU port for any frame transfer */
404 setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
405 QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
407 /* Send a copy to CPU when found as forwarding entry */
408 setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
409 ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
412 static void jr2_port_init(struct jr2_private *priv, int port)
414 void __iomem *regs = priv->regs[port];
417 writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
418 regs + DEV_PCS1G_CFG_PCS1G_CFG);
420 /* Disable Signal Detect */
421 writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
423 /* Enable MAC RX and TX */
424 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
425 DEV_MAC_CFG_MAC_ENA_TX_ENA,
426 regs + DEV_MAC_CFG_MAC_ENA);
428 /* Clear sgmii_mode_ena */
429 writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
432 * Clear sw_resolve_ena(bit 0) and set adv_ability to
433 * something meaningful just in case
435 writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
436 regs + DEV_PCS1G_CFG_PCS1G_ANEG);
438 /* Set MAC IFG Gaps */
439 writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
440 DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
441 DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
442 regs + DEV_MAC_CFG_MAC_IFG);
444 /* Set link speed and release all resets */
445 writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
446 regs + DEV_DEV_CFG_DEV_RST_CTRL);
448 /* Make VLAN aware for CPU traffic */
449 writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
450 ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
452 priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
454 /* Enable CPU port for any frame transfer */
455 setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
456 QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
459 static void serdes6g_write(void __iomem *base, u32 addr)
463 writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
464 HSIO_MCB_SERDES6G_CFG_ADDR(addr),
465 base + HSIO_MCB_SERDES6G_CFG);
468 data = readl(base + HSIO_MCB_SERDES6G_CFG);
469 } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
472 static void serdes6g_setup(void __iomem *base, uint32_t addr,
473 phy_interface_t interface)
481 u32 ob_ena1v_mode = 0;
483 u32 pll_fsm_ctrl_data = 0;
486 case PHY_INTERFACE_MODE_SGMII:
495 pll_fsm_ctrl_data = 60;
497 case PHY_INTERFACE_MODE_QSGMII:
502 pll_fsm_ctrl_data = 120;
505 pr_err("Interface not supported\n");
509 if (interface == PHY_INTERFACE_MODE_QSGMII)
510 writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
512 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
513 base + HSIO_ANA_SERDES6G_COMMON_CFG);
514 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
515 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
516 base + HSIO_ANA_SERDES6G_PLL_CFG);
517 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
518 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
519 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
520 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
521 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
522 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
523 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
524 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
525 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
526 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
527 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
528 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
529 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
530 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
531 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
532 base + HSIO_ANA_SERDES6G_IB_CFG);
533 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
534 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
535 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
536 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
537 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
538 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
539 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
540 base + HSIO_ANA_SERDES6G_IB_CFG1);
541 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
542 base + HSIO_DIG_SERDES6G_MISC_CFG);
544 serdes6g_write(base, addr);
546 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
547 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
548 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
549 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
550 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
551 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
552 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
553 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
554 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
555 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
556 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
557 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
558 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
559 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
560 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
561 base + HSIO_ANA_SERDES6G_IB_CFG);
562 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
563 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
564 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
565 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
566 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
567 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
568 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
569 base + HSIO_ANA_SERDES6G_IB_CFG1);
571 writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
572 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
573 HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
574 HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
575 HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
576 base + HSIO_ANA_SERDES6G_COMMON_CFG);
577 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
578 base + HSIO_DIG_SERDES6G_MISC_CFG);
580 writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
581 HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
582 HSIO_ANA_SERDES6G_OB_CFG_SR_H |
583 HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
584 HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
585 writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
586 HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
587 base + HSIO_ANA_SERDES6G_OB_CFG1);
589 writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
590 HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
591 HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
592 HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
593 base + HSIO_ANA_SERDES6G_DES_CFG);
594 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
595 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
596 base + HSIO_ANA_SERDES6G_PLL_CFG);
598 serdes6g_write(base, addr);
600 /* set pll_fsm_ena = 1 */
601 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
602 HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
603 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
604 base + HSIO_ANA_SERDES6G_PLL_CFG);
606 serdes6g_write(base, addr);
608 /* wait 20ms for pll bringup */
611 /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
612 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
613 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
614 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
615 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
616 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
617 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
618 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
619 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
620 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
621 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
622 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
623 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
624 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
625 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
626 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
627 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
628 base + HSIO_ANA_SERDES6G_IB_CFG);
629 writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
631 serdes6g_write(base, addr);
633 /* wait 60 for calibration */
636 /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
637 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
638 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
639 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
640 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
641 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
642 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
643 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
644 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
645 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
646 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
647 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
648 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
649 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
650 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
651 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
652 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
653 base + HSIO_ANA_SERDES6G_IB_CFG);
654 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
655 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
656 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
657 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
658 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
659 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
660 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
661 base + HSIO_ANA_SERDES6G_IB_CFG1);
663 serdes6g_write(base, addr);
666 static void serdes1g_write(void __iomem *base, u32 addr)
670 writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
671 HSIO_MCB_SERDES1G_CFG_ADDR(addr),
672 base + HSIO_MCB_SERDES1G_CFG);
675 data = readl(base + HSIO_MCB_SERDES1G_CFG);
676 } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
679 static void serdes1g_setup(void __iomem *base, uint32_t addr,
680 phy_interface_t interface)
682 writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
683 writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
684 writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
685 writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
686 HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
687 HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
688 HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
689 HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
690 base + HSIO_ANA_SERDES1G_OB_CFG);
691 writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
692 HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
693 HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
694 HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
695 HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
696 HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
697 HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
698 base + HSIO_ANA_SERDES1G_IB_CFG);
699 writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
700 HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
701 HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
702 HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
703 base + HSIO_ANA_SERDES1G_DES_CFG);
704 writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
705 base + HSIO_DIG_SERDES1G_MISC_CFG);
706 writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
707 HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
708 HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
709 base + HSIO_ANA_SERDES1G_PLL_CFG);
710 writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
711 HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
712 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
713 base + HSIO_ANA_SERDES1G_COMMON_CFG);
715 serdes1g_write(base, addr);
717 setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
718 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
720 serdes1g_write(base, addr);
722 clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
723 HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
725 serdes1g_write(base, addr);
728 static int ram_init(u32 val, void __iomem *addr)
732 if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
733 printf("Timeout in memory reset, reg = 0x%08x\n", val);
740 static int jr2_switch_init(struct jr2_private *priv)
742 /* Initialize memories */
743 ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
744 ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
745 ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
746 ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
749 writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
750 writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
752 /* Enable switch-core and queue system */
753 writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
758 static void jr2_switch_config(struct jr2_private *priv)
760 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
761 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
762 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
763 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
765 writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
766 QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
767 priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
770 static int jr2_initialize(struct jr2_private *priv)
774 /* Initialize switch memories, enable core */
775 ret = jr2_switch_init(priv);
779 jr2_switch_config(priv);
781 for (i = 0; i < MAX_PORT; i++)
782 jr2_port_init(priv, i);
784 jr2_cpu_capture_setup(priv);
789 static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
791 if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
792 LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
799 static int jr2_mac_table_add(struct jr2_private *priv,
800 const unsigned char mac[ETH_ALEN], int pgid)
802 u32 macl = 0, mach = 0;
805 * Set the MAC address to handle and the vlan associated in a format
806 * understood by the hardware.
808 mach |= MAC_VID << 16;
809 mach |= ((u32)mac[0]) << 8;
810 mach |= ((u32)mac[1]) << 0;
811 macl |= ((u32)mac[2]) << 24;
812 macl |= ((u32)mac[3]) << 16;
813 macl |= ((u32)mac[4]) << 8;
814 macl |= ((u32)mac[5]) << 0;
816 writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
817 writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
819 writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
820 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
821 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
822 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
823 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
824 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
825 priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
827 writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
828 priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
830 return jr2_vlant_wait_for_completion(priv);
833 static int jr2_write_hwaddr(struct udevice *dev)
835 struct jr2_private *priv = dev_get_priv(dev);
836 struct eth_pdata *pdata = dev_get_platdata(dev);
838 return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
841 static void serdes_setup(struct jr2_private *priv)
846 for (i = 0; i < MAX_PORT; ++i) {
847 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
850 mask = BIT(priv->ports[i].serdes_index);
851 if (priv->ports[i].serdes_index < SERDES1G_MAX) {
852 serdes1g_setup(priv->regs[HSIO], mask,
853 priv->ports[i].phy_mode);
855 mask >>= SERDES6G(0);
856 serdes6g_setup(priv->regs[HSIO], mask,
857 priv->ports[i].phy_mode);
862 static int jr2_start(struct udevice *dev)
864 struct jr2_private *priv = dev_get_priv(dev);
865 struct eth_pdata *pdata = dev_get_platdata(dev);
866 const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
870 ret = jr2_initialize(priv);
874 /* Set MAC address tables entries for CPU redirection */
875 ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
879 ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
888 static void jr2_stop(struct udevice *dev)
892 static int jr2_send(struct udevice *dev, void *packet, int length)
894 struct jr2_private *priv = dev_get_priv(dev);
898 memset(ifh, '\0', IFH_LEN);
900 /* Set DST PORT_MASK */
902 ifh[1] = htonl(0x1FFFFF);
904 /* Set DST_MODE to INJECT and UPDATE_FCS */
905 ifh[5] = htonl(0x4c0);
907 return mscc_send(priv->regs[QS], jr2_regs_qs,
908 ifh, IFH_LEN, buf, length);
911 static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
913 struct jr2_private *priv = dev_get_priv(dev);
914 u32 *rxbuf = (u32 *)net_rx_packets[0];
917 byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
920 *packetp = net_rx_packets[0];
925 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
929 for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
930 if (miim[i].miim_base == base && miim[i].miim_size == size)
936 static void add_port_entry(struct jr2_private *priv, size_t index,
937 size_t phy_addr, struct mii_dev *bus,
938 u8 serdes_index, u8 phy_mode)
940 priv->ports[index].phy_addr = phy_addr;
941 priv->ports[index].bus = bus;
942 priv->ports[index].serdes_index = serdes_index;
943 priv->ports[index].phy_mode = phy_mode;
946 static int jr2_probe(struct udevice *dev)
948 struct jr2_private *priv = dev_get_priv(dev);
953 phys_addr_t addr_base;
954 unsigned long addr_size;
955 ofnode eth_node, node, mdio_node;
958 struct ofnode_phandle_args phandle;
959 struct phy_device *phy;
964 /* Get registers and map them to the private structure */
965 for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
966 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
967 if (!priv->regs[i]) {
969 ("Error can't get regs base addresses for %s\n",
975 /* Initialize miim buses */
976 memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
978 /* iterate all the ports and find out on which bus they are */
980 eth_node = dev_read_first_subnode(dev);
981 for (node = ofnode_first_subnode(eth_node);
983 node = ofnode_next_subnode(node)) {
984 if (ofnode_read_resource(node, 0, &res))
988 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
993 /* Get phy address on mdio bus */
994 if (ofnode_read_resource(phandle.node, 0, &res))
996 phy_addr = res.start;
999 mdio_node = ofnode_get_parent(phandle.node);
1001 if (ofnode_read_resource(mdio_node, 0, &res))
1003 faddr = cpu_to_fdt32(res.start);
1005 addr_base = ofnode_translate_address(mdio_node, &faddr);
1006 addr_size = res.end - res.start;
1008 /* If the bus is new then create a new bus */
1009 if (!get_mdiobus(addr_base, addr_size))
1010 priv->bus[miim_count] =
1011 jr2_mdiobus_init(addr_base, addr_size);
1013 /* Connect mdio bus with the port */
1014 bus = get_mdiobus(addr_base, addr_size);
1016 /* Get serdes info */
1017 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
1022 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
1026 for (i = 0; i < MAX_PORT; i++) {
1027 if (!priv->ports[i].bus)
1030 phy = phy_connect(priv->ports[i].bus,
1031 priv->ports[i].phy_addr, dev,
1032 PHY_INTERFACE_MODE_NONE);
1034 board_phy_config(phy);
1040 static int jr2_remove(struct udevice *dev)
1042 struct jr2_private *priv = dev_get_priv(dev);
1045 for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
1046 mdio_unregister(priv->bus[i]);
1047 mdio_free(priv->bus[i]);
1053 static const struct eth_ops jr2_ops = {
1058 .write_hwaddr = jr2_write_hwaddr,
1061 static const struct udevice_id mscc_jr2_ids[] = {
1062 {.compatible = "mscc,vsc7454-switch" },
1066 U_BOOT_DRIVER(jr2) = {
1067 .name = "jr2-switch",
1069 .of_match = mscc_jr2_ids,
1071 .remove = jr2_remove,
1073 .priv_auto_alloc_size = sizeof(struct jr2_private),
1074 .platdata_auto_alloc_size = sizeof(struct eth_pdata),