blob: 7157428a685ebd84a74eecba07b786d89bff2b2e [file] [log] [blame]
Horatiu Vultur43be1972019-04-03 19:54:45 +02001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2018 Microsemi Corporation
4 */
5
6#include <common.h>
7#include <config.h>
8#include <dm.h>
Simon Glass9bc15642020-02-03 07:36:16 -07009#include <malloc.h>
Horatiu Vultur43be1972019-04-03 19:54:45 +020010#include <dm/of_access.h>
11#include <dm/of_addr.h>
12#include <fdt_support.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060013#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Horatiu Vultur43be1972019-04-03 19:54:45 +020015#include <linux/io.h>
16#include <linux/ioport.h>
17#include <miiphy.h>
18#include <net.h>
19#include <wait_bit.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060020#include <linux/printk.h>
Horatiu Vultur43be1972019-04-03 19:54:45 +020021
22#include <dt-bindings/mscc/jr2_data.h>
23#include "mscc_xfer.h"
Horatiu Vultur6fbf1612019-06-09 15:27:29 +020024#include "mscc_miim.h"
Horatiu Vultur43be1972019-04-03 19:54:45 +020025
26#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358
27#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
28
29#define ANA_CL_PORT_VLAN_CFG(x) (0x24018 + 0xc8 * (x))
30#define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19)
31#define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17)
32
33#define ANA_L2_COMMON_FWD_CFG 0x8a2a8
34#define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
35
36#define ASM_CFG_STAT_CFG 0x3508
37#define ASM_CFG_PORT(x) (0x36c4 + 0x4 * (x))
38#define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8)
39#define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1)
40#define ASM_RAM_CTRL_RAM_INIT 0x39b8
41
42#define DEV_DEV_CFG_DEV_RST_CTRL 0x0
43#define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20)
44#define DEV_MAC_CFG_MAC_ENA 0x1c
45#define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4)
46#define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0)
47#define DEV_MAC_CFG_MAC_IFG 0x34
48#define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8)
49#define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4)
50#define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x)
51#define DEV_PCS1G_CFG_PCS1G_CFG 0x40
52#define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0)
53#define DEV_PCS1G_CFG_PCS1G_MODE 0x44
54#define DEV_PCS1G_CFG_PCS1G_SD 0x48
55#define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c
56#define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
57
58#define DSM_RAM_CTRL_RAM_INIT 0x8
59
60#define HSIO_ANA_SERDES1G_DES_CFG 0xac
61#define HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x) ((x) << 1)
62#define HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x) ((x) << 5)
63#define HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x) ((x) << 8)
64#define HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x) ((x) << 13)
65#define HSIO_ANA_SERDES1G_IB_CFG 0xb0
66#define HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x) (x)
67#define HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x) ((x) << 6)
68#define HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP BIT(9)
69#define HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV BIT(11)
70#define HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM BIT(13)
71#define HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x) ((x) << 19)
72#define HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x) ((x) << 24)
73#define HSIO_ANA_SERDES1G_OB_CFG 0xb4
74#define HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x) (x)
75#define HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x) ((x) << 4)
76#define HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x) ((x) << 10)
77#define HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x) ((x) << 13)
78#define HSIO_ANA_SERDES1G_OB_CFG_SLP(x) ((x) << 17)
79#define HSIO_ANA_SERDES1G_SER_CFG 0xb8
80#define HSIO_ANA_SERDES1G_COMMON_CFG 0xbc
81#define HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE BIT(0)
82#define HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE BIT(18)
83#define HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST BIT(31)
84#define HSIO_ANA_SERDES1G_PLL_CFG 0xc0
85#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA BIT(7)
86#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8)
87#define HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2 BIT(21)
88#define HSIO_DIG_SERDES1G_DFT_CFG0 0xc8
89#define HSIO_DIG_SERDES1G_TP_CFG 0xd4
90#define HSIO_DIG_SERDES1G_MISC_CFG 0xdc
91#define HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST BIT(0)
92#define HSIO_MCB_SERDES1G_CFG 0xe8
93#define HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT BIT(31)
94#define HSIO_MCB_SERDES1G_CFG_ADDR(x) (x)
95
96#define HSIO_ANA_SERDES6G_DES_CFG 0x11c
97#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA BIT(0)
98#define HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x) ((x) << 1)
99#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST BIT(4)
100#define HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x) ((x) << 5)
101#define HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x) ((x) << 8)
102#define HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x) ((x) << 10)
103#define HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x) ((x) << 13)
104#define HSIO_ANA_SERDES6G_IB_CFG 0x120
105#define HSIO_ANA_SERDES6G_IB_CFG_REG_ENA BIT(0)
106#define HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA BIT(1)
107#define HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA BIT(2)
108#define HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x) ((x) << 3)
109#define HSIO_ANA_SERDES6G_IB_CFG_CONCUR BIT(4)
110#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA BIT(5)
111#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x) ((x) << 7)
112#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x) ((x) << 9)
113#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x) ((x) << 11)
114#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x) ((x) << 13)
115#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x) ((x) << 15)
116#define HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x) ((x) << 18)
117#define HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x) ((x) << 20)
118#define HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x) ((x) << 24)
119#define HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL BIT(28)
120#define HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x) ((x) << 29)
121#define HSIO_ANA_SERDES6G_IB_CFG1 0x124
122#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET BIT(4)
123#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP BIT(5)
124#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID BIT(6)
125#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP BIT(7)
126#define HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x) ((x) << 8)
127#define HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x) ((x) << 12)
128#define HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x) ((x) << 17)
129#define HSIO_ANA_SERDES6G_IB_CFG2 0x128
130#define HSIO_ANA_SERDES6G_IB_CFG2_UREG(x) (x)
131#define HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x) ((x) << 3)
132#define HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x) ((x) << 5)
133#define HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x) ((x) << 10)
134#define HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x) ((x) << 16)
135#define HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x) ((x) << 22)
136#define HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x) ((x) << 27)
137#define HSIO_ANA_SERDES6G_IB_CFG3 0x12c
138#define HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x) (x)
139#define HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x) ((x) << 6)
140#define HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x) ((x) << 12)
141#define HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x) ((x) << 18)
142#define HSIO_ANA_SERDES6G_IB_CFG4 0x130
143#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x) (x)
144#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x) ((x) << 6)
145#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x) ((x) << 12)
146#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x) ((x) << 18)
147#define HSIO_ANA_SERDES6G_IB_CFG5 0x134
148#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x) (x)
149#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x) ((x) << 6)
150#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x) ((x) << 12)
151#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x) ((x) << 18)
152#define HSIO_ANA_SERDES6G_OB_CFG 0x138
153#define HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x) (x)
154#define HSIO_ANA_SERDES6G_OB_CFG_SR(x) ((x) << 4)
155#define HSIO_ANA_SERDES6G_OB_CFG_SR_H BIT(8)
156#define HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL BIT(9)
157#define HSIO_ANA_SERDES6G_OB_CFG_R_COR BIT(10)
158#define HSIO_ANA_SERDES6G_OB_CFG_POST1(x) ((x) << 11)
159#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR BIT(16)
160#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX BIT(17)
161#define HSIO_ANA_SERDES6G_OB_CFG_PREC(x) ((x) << 18)
162#define HSIO_ANA_SERDES6G_OB_CFG_POST0(x) ((x) << 23)
163#define HSIO_ANA_SERDES6G_OB_CFG_POL BIT(29)
164#define HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x) ((x) << 30)
165#define HSIO_ANA_SERDES6G_OB_CFG_IDLE BIT(31)
166#define HSIO_ANA_SERDES6G_OB_CFG1 0x13c
167#define HSIO_ANA_SERDES6G_OB_CFG1_LEV(x) (x)
168#define HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x) ((x) << 6)
169#define HSIO_ANA_SERDES6G_SER_CFG 0x140
170#define HSIO_ANA_SERDES6G_COMMON_CFG 0x144
171#define HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x) (x)
172#define HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x) (x << 2)
173#define HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE BIT(14)
174#define HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST BIT(16)
175#define HSIO_ANA_SERDES6G_PLL_CFG 0x148
176#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ BIT(0)
177#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR BIT(1)
178#define HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL BIT(2)
179#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA BIT(3)
180#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA BIT(4)
181#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA BIT(5)
182#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 6)
183#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT BIT(14)
184#define HSIO_ANA_SERDES6G_PLL_CFG_DIV4 BIT(15)
185#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x) ((x) << 16)
186#define HSIO_DIG_SERDES6G_MISC_CFG 0x108
187#define HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST BIT(0)
188#define HSIO_MCB_SERDES6G_CFG 0x168
189#define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31)
190#define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x)
191#define HSIO_HW_CFGSTAT_HW_CFG 0x16c
192
193#define LRN_COMMON_ACCESS_CTRL 0x0
194#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0)
195#define LRN_COMMON_MAC_ACCESS_CFG0 0x4
196#define LRN_COMMON_MAC_ACCESS_CFG1 0x8
197#define LRN_COMMON_MAC_ACCESS_CFG2 0xc
198#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x)
199#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12)
200#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15)
201#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16)
202#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23)
203#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24)
204
205#define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4 * (x))
206#define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17)
207
208#define QS_XTR_GRP_CFG(x) (0x0 + 4 * (x))
209#define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4)
210
211#define QSYS_SYSTEM_RESET_CFG 0xf0
212#define QSYS_CALCFG_CAL_AUTO(x) (0x3d4 + 4 * (x))
213#define QSYS_CALCFG_CAL_CTRL 0x3e8
214#define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11)
215#define QSYS_RAM_CTRL_RAM_INIT 0x3ec
216
217#define REW_RAM_CTRL_RAM_INIT 0x53528
218
219#define VOP_RAM_CTRL_RAM_INIT 0x43638
220
221#define XTR_VALID_BYTES(x) (4 - ((x) & 3))
222#define MAC_VID 0
223#define CPU_PORT 53
224#define IFH_LEN 7
225#define JR2_BUF_CELL_SZ 60
226#define ETH_ALEN 6
227#define PGID_BROADCAST 510
228#define PGID_UNICAST 511
229
230static const char * const regs_names[] = {
231 "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
232 "port8", "port9", "port10", "port11", "port12", "port13", "port14",
233 "port15", "port16", "port17", "port18", "port19", "port20", "port21",
234 "port22", "port23", "port24", "port25", "port26", "port27", "port28",
235 "port29", "port30", "port31", "port32", "port33", "port34", "port35",
236 "port36", "port37", "port38", "port39", "port40", "port41", "port42",
237 "port43", "port44", "port45", "port46", "port47",
238 "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
Horatiu Vultur034ac242021-03-10 09:31:38 +0100239 "qfwd", "qs", "qsys", "rew", "gcb", "icpu",
Horatiu Vultur43be1972019-04-03 19:54:45 +0200240};
241
242#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
243#define MAX_PORT 48
244
245enum jr2_ctrl_regs {
246 ANA_AC = MAX_PORT,
247 ANA_CL,
248 ANA_L2,
249 ASM,
250 HSIO,
251 LRN,
252 QFWD,
253 QS,
254 QSYS,
255 REW,
Horatiu Vultur034ac242021-03-10 09:31:38 +0100256 GCB,
257 ICPU,
Horatiu Vultur43be1972019-04-03 19:54:45 +0200258};
259
260#define JR2_MIIM_BUS_COUNT 3
261
262struct jr2_phy_port_t {
263 size_t phy_addr;
264 struct mii_dev *bus;
265 u8 serdes_index;
266 u8 phy_mode;
267};
268
269struct jr2_private {
270 void __iomem *regs[REGS_NAMES_COUNT];
271 struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
272 struct jr2_phy_port_t ports[MAX_PORT];
273};
274
Horatiu Vultur43be1972019-04-03 19:54:45 +0200275static const unsigned long jr2_regs_qs[] = {
276 [MSCC_QS_XTR_RD] = 0x8,
277 [MSCC_QS_XTR_FLUSH] = 0x18,
278 [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
279 [MSCC_QS_INJ_WR] = 0x2c,
280 [MSCC_QS_INJ_CTRL] = 0x34,
281};
282
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200283static struct mscc_miim_dev miim[JR2_MIIM_BUS_COUNT];
Horatiu Vultur43be1972019-04-03 19:54:45 +0200284static int miim_count = -1;
285
Horatiu Vultur43be1972019-04-03 19:54:45 +0200286static void jr2_cpu_capture_setup(struct jr2_private *priv)
287{
288 /* ASM: No preamble and IFH prefix on CPU injected frames */
289 writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
290 ASM_CFG_PORT_INJ_FORMAT_CFG(1),
291 priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
292
293 /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
294 writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
295
296 /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
297 writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
298
299 /* Enable CPU port for any frame transfer */
300 setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
301 QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
302
303 /* Send a copy to CPU when found as forwarding entry */
304 setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
305 ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
306}
307
308static void jr2_port_init(struct jr2_private *priv, int port)
309{
310 void __iomem *regs = priv->regs[port];
311
312 /* Enable PCS */
313 writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
314 regs + DEV_PCS1G_CFG_PCS1G_CFG);
315
316 /* Disable Signal Detect */
317 writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
318
319 /* Enable MAC RX and TX */
320 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
321 DEV_MAC_CFG_MAC_ENA_TX_ENA,
322 regs + DEV_MAC_CFG_MAC_ENA);
323
324 /* Clear sgmii_mode_ena */
325 writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
326
327 /*
328 * Clear sw_resolve_ena(bit 0) and set adv_ability to
329 * something meaningful just in case
330 */
331 writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
332 regs + DEV_PCS1G_CFG_PCS1G_ANEG);
333
334 /* Set MAC IFG Gaps */
335 writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
336 DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
337 DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
338 regs + DEV_MAC_CFG_MAC_IFG);
339
340 /* Set link speed and release all resets */
341 writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
342 regs + DEV_DEV_CFG_DEV_RST_CTRL);
343
344 /* Make VLAN aware for CPU traffic */
345 writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
346 ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
347 MAC_VID,
348 priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
349
350 /* Enable CPU port for any frame transfer */
351 setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
352 QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
353}
354
355static void serdes6g_write(void __iomem *base, u32 addr)
356{
357 u32 data;
358
359 writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
360 HSIO_MCB_SERDES6G_CFG_ADDR(addr),
361 base + HSIO_MCB_SERDES6G_CFG);
362
363 do {
364 data = readl(base + HSIO_MCB_SERDES6G_CFG);
365 } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
366}
367
368static void serdes6g_setup(void __iomem *base, uint32_t addr,
369 phy_interface_t interface)
370{
371 u32 ib_if_mode = 0;
372 u32 ib_qrate = 0;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200373 u32 ib1_tsdet = 0;
374 u32 ob_lev = 0;
375 u32 ob_ena_cas = 0;
376 u32 ob_ena1v_mode = 0;
377 u32 des_bw_ana = 0;
378 u32 pll_fsm_ctrl_data = 0;
379
380 switch (interface) {
381 case PHY_INTERFACE_MODE_SGMII:
382 ib_if_mode = 1;
383 ib_qrate = 1;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200384 ib1_tsdet = 3;
385 ob_lev = 48;
386 ob_ena_cas = 2;
387 ob_ena1v_mode = 1;
388 des_bw_ana = 3;
389 pll_fsm_ctrl_data = 60;
390 break;
391 case PHY_INTERFACE_MODE_QSGMII:
392 ib_if_mode = 3;
393 ib1_tsdet = 16;
394 ob_lev = 24;
395 des_bw_ana = 5;
396 pll_fsm_ctrl_data = 120;
397 break;
398 default:
399 pr_err("Interface not supported\n");
400 return;
401 }
402
403 if (interface == PHY_INTERFACE_MODE_QSGMII)
404 writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
405
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100406 writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
407 HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
408 HSIO_ANA_SERDES6G_OB_CFG_SR_H |
409 HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
410 HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
411
Horatiu Vultur43be1972019-04-03 19:54:45 +0200412 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
413 base + HSIO_ANA_SERDES6G_COMMON_CFG);
414 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
415 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
416 base + HSIO_ANA_SERDES6G_PLL_CFG);
417 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
418 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
419 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
420 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
421 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
422 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
423 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
424 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
425 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
426 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
427 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
428 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
429 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
430 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
431 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
432 base + HSIO_ANA_SERDES6G_IB_CFG);
433 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
434 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
435 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
436 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
437 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
438 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
439 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
440 base + HSIO_ANA_SERDES6G_IB_CFG1);
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100441
442 writel(HSIO_ANA_SERDES6G_IB_CFG2_UREG(4) |
443 HSIO_ANA_SERDES6G_IB_CFG2_UMAX(2) |
444 HSIO_ANA_SERDES6G_IB_CFG2_TCALV(12) |
445 HSIO_ANA_SERDES6G_IB_CFG2_OCALS(32) |
446 HSIO_ANA_SERDES6G_IB_CFG2_OINFS(7) |
447 HSIO_ANA_SERDES6G_IB_CFG2_OINFI(0x1f) |
448 HSIO_ANA_SERDES6G_IB_CFG2_TINFV(3),
449 base + HSIO_ANA_SERDES6G_IB_CFG2);
450
451 writel(HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(0x1f) |
452 HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(1) |
453 HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(0x1f),
454 base + HSIO_ANA_SERDES6G_IB_CFG3);
455
Horatiu Vultur43be1972019-04-03 19:54:45 +0200456 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
457 base + HSIO_DIG_SERDES6G_MISC_CFG);
458
459 serdes6g_write(base, addr);
460
461 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
462 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
463 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
464 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
465 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
466 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
467 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
468 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
469 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
470 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
471 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
472 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
473 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
474 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
475 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
476 base + HSIO_ANA_SERDES6G_IB_CFG);
477 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
478 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
479 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
480 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
481 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
482 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
483 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
484 base + HSIO_ANA_SERDES6G_IB_CFG1);
485
486 writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
487 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
488 HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
489 HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
490 HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
491 base + HSIO_ANA_SERDES6G_COMMON_CFG);
492 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
493 base + HSIO_DIG_SERDES6G_MISC_CFG);
494
495 writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
496 HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
497 HSIO_ANA_SERDES6G_OB_CFG_SR_H |
498 HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
499 HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
500 writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
501 HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
502 base + HSIO_ANA_SERDES6G_OB_CFG1);
503
504 writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
505 HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
506 HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
507 HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
508 base + HSIO_ANA_SERDES6G_DES_CFG);
509 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
510 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
511 base + HSIO_ANA_SERDES6G_PLL_CFG);
512
513 serdes6g_write(base, addr);
514
515 /* set pll_fsm_ena = 1 */
516 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
517 HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
518 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
519 base + HSIO_ANA_SERDES6G_PLL_CFG);
520
521 serdes6g_write(base, addr);
522
523 /* wait 20ms for pll bringup */
524 mdelay(20);
525
526 /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
527 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
528 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
529 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100530 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
Horatiu Vultur43be1972019-04-03 19:54:45 +0200531 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
532 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
533 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
534 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
535 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
536 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
537 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
538 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
539 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
540 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
541 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
542 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
543 base + HSIO_ANA_SERDES6G_IB_CFG);
544 writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
545
546 serdes6g_write(base, addr);
547
548 /* wait 60 for calibration */
549 mdelay(60);
550
551 /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
552 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
553 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
554 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100555 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
Horatiu Vultur43be1972019-04-03 19:54:45 +0200556 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
557 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
558 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
559 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
560 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
561 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
562 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
563 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
564 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
565 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
566 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
567 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
568 base + HSIO_ANA_SERDES6G_IB_CFG);
569 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
570 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
571 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
572 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
573 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
574 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
575 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
576 base + HSIO_ANA_SERDES6G_IB_CFG1);
577
578 serdes6g_write(base, addr);
579}
580
581static void serdes1g_write(void __iomem *base, u32 addr)
582{
583 u32 data;
584
585 writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
586 HSIO_MCB_SERDES1G_CFG_ADDR(addr),
587 base + HSIO_MCB_SERDES1G_CFG);
588
589 do {
590 data = readl(base + HSIO_MCB_SERDES1G_CFG);
591 } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
592}
593
594static void serdes1g_setup(void __iomem *base, uint32_t addr,
595 phy_interface_t interface)
596{
597 writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
598 writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
599 writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
600 writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
601 HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
602 HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
603 HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
604 HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
605 base + HSIO_ANA_SERDES1G_OB_CFG);
606 writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
607 HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
608 HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
609 HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
610 HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
611 HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
612 HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
613 base + HSIO_ANA_SERDES1G_IB_CFG);
614 writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
615 HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
616 HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
617 HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
618 base + HSIO_ANA_SERDES1G_DES_CFG);
619 writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
620 base + HSIO_DIG_SERDES1G_MISC_CFG);
621 writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
622 HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
623 HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
624 base + HSIO_ANA_SERDES1G_PLL_CFG);
625 writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
626 HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
627 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
628 base + HSIO_ANA_SERDES1G_COMMON_CFG);
629
630 serdes1g_write(base, addr);
631
632 setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
633 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
634
635 serdes1g_write(base, addr);
636
637 clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
638 HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
639
640 serdes1g_write(base, addr);
641}
642
643static int ram_init(u32 val, void __iomem *addr)
644{
645 writel(val, addr);
646
647 if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
648 printf("Timeout in memory reset, reg = 0x%08x\n", val);
649 return 1;
650 }
651
652 return 0;
653}
654
655static int jr2_switch_init(struct jr2_private *priv)
656{
657 /* Initialize memories */
658 ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
659 ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
660 ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
661 ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
662
663 /* Reset counters */
664 writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
665 writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
666
667 /* Enable switch-core and queue system */
668 writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
669
670 return 0;
671}
672
673static void jr2_switch_config(struct jr2_private *priv)
674{
675 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
676 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
677 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
678 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
679
680 writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
681 QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
682 priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
683}
684
685static int jr2_initialize(struct jr2_private *priv)
686{
687 int ret, i;
688
689 /* Initialize switch memories, enable core */
690 ret = jr2_switch_init(priv);
691 if (ret)
692 return ret;
693
694 jr2_switch_config(priv);
695
696 for (i = 0; i < MAX_PORT; i++)
697 jr2_port_init(priv, i);
698
699 jr2_cpu_capture_setup(priv);
700
701 return 0;
702}
703
704static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
705{
706 if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
707 LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
708 false, 2000, false))
709 return -ETIMEDOUT;
710
711 return 0;
712}
713
714static int jr2_mac_table_add(struct jr2_private *priv,
715 const unsigned char mac[ETH_ALEN], int pgid)
716{
717 u32 macl = 0, mach = 0;
718
719 /*
720 * Set the MAC address to handle and the vlan associated in a format
721 * understood by the hardware.
722 */
723 mach |= MAC_VID << 16;
724 mach |= ((u32)mac[0]) << 8;
725 mach |= ((u32)mac[1]) << 0;
726 macl |= ((u32)mac[2]) << 24;
727 macl |= ((u32)mac[3]) << 16;
728 macl |= ((u32)mac[4]) << 8;
729 macl |= ((u32)mac[5]) << 0;
730
731 writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
732 writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
733
734 writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
735 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
736 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
737 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
738 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
739 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
740 priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
741
742 writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
743 priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
744
745 return jr2_vlant_wait_for_completion(priv);
746}
747
748static int jr2_write_hwaddr(struct udevice *dev)
749{
750 struct jr2_private *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700751 struct eth_pdata *pdata = dev_get_plat(dev);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200752
753 return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
754}
755
756static void serdes_setup(struct jr2_private *priv)
757{
758 size_t mask;
759 int i = 0;
760
761 for (i = 0; i < MAX_PORT; ++i) {
762 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
763 continue;
764
765 mask = BIT(priv->ports[i].serdes_index);
766 if (priv->ports[i].serdes_index < SERDES1G_MAX) {
767 serdes1g_setup(priv->regs[HSIO], mask,
768 priv->ports[i].phy_mode);
769 } else {
770 mask >>= SERDES6G(0);
771 serdes6g_setup(priv->regs[HSIO], mask,
772 priv->ports[i].phy_mode);
773 }
774 }
775}
776
777static int jr2_start(struct udevice *dev)
778{
779 struct jr2_private *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700780 struct eth_pdata *pdata = dev_get_plat(dev);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200781 const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
782 0xff };
783 int ret;
784
785 ret = jr2_initialize(priv);
786 if (ret)
787 return ret;
788
789 /* Set MAC address tables entries for CPU redirection */
790 ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
791 if (ret)
792 return ret;
793
794 ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
795 if (ret)
796 return ret;
797
798 serdes_setup(priv);
799
800 return 0;
801}
802
803static void jr2_stop(struct udevice *dev)
804{
805}
806
807static int jr2_send(struct udevice *dev, void *packet, int length)
808{
809 struct jr2_private *priv = dev_get_priv(dev);
810 u32 ifh[IFH_LEN];
811 u32 *buf = packet;
812
813 memset(ifh, '\0', IFH_LEN);
814
815 /* Set DST PORT_MASK */
816 ifh[0] = htonl(0);
817 ifh[1] = htonl(0x1FFFFF);
818 ifh[2] = htonl(~0);
819 /* Set DST_MODE to INJECT and UPDATE_FCS */
820 ifh[5] = htonl(0x4c0);
821
822 return mscc_send(priv->regs[QS], jr2_regs_qs,
823 ifh, IFH_LEN, buf, length);
824}
825
826static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
827{
828 struct jr2_private *priv = dev_get_priv(dev);
829 u32 *rxbuf = (u32 *)net_rx_packets[0];
830 int byte_cnt = 0;
831
832 byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
833 false);
834
835 *packetp = net_rx_packets[0];
836
837 return byte_cnt;
838}
839
840static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
841{
842 int i = 0;
843
844 for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
845 if (miim[i].miim_base == base && miim[i].miim_size == size)
846 return miim[i].bus;
847
848 return NULL;
849}
850
851static void add_port_entry(struct jr2_private *priv, size_t index,
852 size_t phy_addr, struct mii_dev *bus,
853 u8 serdes_index, u8 phy_mode)
854{
855 priv->ports[index].phy_addr = phy_addr;
856 priv->ports[index].bus = bus;
857 priv->ports[index].serdes_index = serdes_index;
858 priv->ports[index].phy_mode = phy_mode;
859}
860
861static int jr2_probe(struct udevice *dev)
862{
863 struct jr2_private *priv = dev_get_priv(dev);
864 int i;
865 int ret;
866 struct resource res;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200867 phys_addr_t addr_base;
868 unsigned long addr_size;
869 ofnode eth_node, node, mdio_node;
870 size_t phy_addr;
871 struct mii_dev *bus;
872 struct ofnode_phandle_args phandle;
873 struct phy_device *phy;
Horatiu Vultur034ac242021-03-10 09:31:38 +0100874 u32 val;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200875
876 if (!priv)
877 return -EINVAL;
878
879 /* Get registers and map them to the private structure */
880 for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
881 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
882 if (!priv->regs[i]) {
883 debug
884 ("Error can't get regs base addresses for %s\n",
885 regs_names[i]);
886 return -ENOMEM;
887 }
888 }
889
Horatiu Vultur034ac242021-03-10 09:31:38 +0100890 val = readl(priv->regs[ICPU] + ICPU_RESET);
891 val |= ICPU_RESET_CORE_RST_PROTECT;
892 writel(val, priv->regs[ICPU] + ICPU_RESET);
893
894 val = readl(priv->regs[GCB] + PERF_SOFT_RST);
895 val |= PERF_SOFT_RST_SOFT_SWC_RST;
896 writel(val, priv->regs[GCB] + PERF_SOFT_RST);
897
898 while (readl(priv->regs[GCB] + PERF_SOFT_RST) & PERF_SOFT_RST_SOFT_SWC_RST)
899 ;
900
Horatiu Vultur43be1972019-04-03 19:54:45 +0200901 /* Initialize miim buses */
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200902 memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200903
904 /* iterate all the ports and find out on which bus they are */
905 i = 0;
906 eth_node = dev_read_first_subnode(dev);
907 for (node = ofnode_first_subnode(eth_node);
908 ofnode_valid(node);
909 node = ofnode_next_subnode(node)) {
910 if (ofnode_read_resource(node, 0, &res))
911 return -ENOMEM;
912 i = res.start;
913
914 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
915 0, 0, &phandle);
916 if (ret)
917 continue;
918
919 /* Get phy address on mdio bus */
920 if (ofnode_read_resource(phandle.node, 0, &res))
921 return -ENOMEM;
922 phy_addr = res.start;
923
924 /* Get mdio node */
925 mdio_node = ofnode_get_parent(phandle.node);
926
927 if (ofnode_read_resource(mdio_node, 0, &res))
928 return -ENOMEM;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200929
Patrick Delaunay2a28c6e2021-04-06 09:38:06 +0200930 addr_base = res.start;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200931 addr_size = res.end - res.start;
932
933 /* If the bus is new then create a new bus */
934 if (!get_mdiobus(addr_base, addr_size))
935 priv->bus[miim_count] =
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200936 mscc_mdiobus_init(miim, &miim_count, addr_base,
937 addr_size);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200938
939 /* Connect mdio bus with the port */
940 bus = get_mdiobus(addr_base, addr_size);
941
942 /* Get serdes info */
943 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
944 3, 0, &phandle);
945 if (ret)
946 return -ENOMEM;
947
948 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
949 phandle.args[2]);
950 }
951
952 for (i = 0; i < MAX_PORT; i++) {
953 if (!priv->ports[i].bus)
954 continue;
955
956 phy = phy_connect(priv->ports[i].bus,
957 priv->ports[i].phy_addr, dev,
Marek BehĂșn48631e42022-04-07 00:33:03 +0200958 PHY_INTERFACE_MODE_NA);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200959 if (phy)
960 board_phy_config(phy);
961 }
962
963 return 0;
964}
965
966static int jr2_remove(struct udevice *dev)
967{
968 struct jr2_private *priv = dev_get_priv(dev);
969 int i;
970
971 for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
972 mdio_unregister(priv->bus[i]);
973 mdio_free(priv->bus[i]);
974 }
975
976 return 0;
977}
978
979static const struct eth_ops jr2_ops = {
980 .start = jr2_start,
981 .stop = jr2_stop,
982 .send = jr2_send,
983 .recv = jr2_recv,
984 .write_hwaddr = jr2_write_hwaddr,
985};
986
987static const struct udevice_id mscc_jr2_ids[] = {
988 {.compatible = "mscc,vsc7454-switch" },
989 { /* Sentinel */ }
990};
991
992U_BOOT_DRIVER(jr2) = {
993 .name = "jr2-switch",
994 .id = UCLASS_ETH,
995 .of_match = mscc_jr2_ids,
996 .probe = jr2_probe,
997 .remove = jr2_remove,
998 .ops = &jr2_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700999 .priv_auto = sizeof(struct jr2_private),
Simon Glass71fa5b42020-12-03 16:55:18 -07001000 .plat_auto = sizeof(struct eth_pdata),
Horatiu Vultur43be1972019-04-03 19:54:45 +02001001};