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