blob: 925888e0765a214fedded4673b2cde8f6b4ed72c [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
Horatiu Vultur43be1972019-04-03 19:54:45 +02006#include <config.h>
7#include <dm.h>
Simon Glass9bc15642020-02-03 07:36:16 -07008#include <malloc.h>
Horatiu Vultur43be1972019-04-03 19:54:45 +02009#include <dm/of_access.h>
10#include <dm/of_addr.h>
11#include <fdt_support.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060012#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060013#include <linux/delay.h>
Horatiu Vultur43be1972019-04-03 19:54:45 +020014#include <linux/io.h>
15#include <linux/ioport.h>
16#include <miiphy.h>
17#include <net.h>
18#include <wait_bit.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060019#include <linux/printk.h>
Horatiu Vultur43be1972019-04-03 19:54:45 +020020
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;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200372 u32 ib1_tsdet = 0;
373 u32 ob_lev = 0;
374 u32 ob_ena_cas = 0;
375 u32 ob_ena1v_mode = 0;
376 u32 des_bw_ana = 0;
377 u32 pll_fsm_ctrl_data = 0;
378
379 switch (interface) {
380 case PHY_INTERFACE_MODE_SGMII:
381 ib_if_mode = 1;
382 ib_qrate = 1;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200383 ib1_tsdet = 3;
384 ob_lev = 48;
385 ob_ena_cas = 2;
386 ob_ena1v_mode = 1;
387 des_bw_ana = 3;
388 pll_fsm_ctrl_data = 60;
389 break;
390 case PHY_INTERFACE_MODE_QSGMII:
391 ib_if_mode = 3;
392 ib1_tsdet = 16;
393 ob_lev = 24;
394 des_bw_ana = 5;
395 pll_fsm_ctrl_data = 120;
396 break;
397 default:
398 pr_err("Interface not supported\n");
399 return;
400 }
401
402 if (interface == PHY_INTERFACE_MODE_QSGMII)
403 writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
404
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100405 writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
406 HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
407 HSIO_ANA_SERDES6G_OB_CFG_SR_H |
408 HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
409 HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
410
Horatiu Vultur43be1972019-04-03 19:54:45 +0200411 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
412 base + HSIO_ANA_SERDES6G_COMMON_CFG);
413 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
414 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
415 base + HSIO_ANA_SERDES6G_PLL_CFG);
416 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
417 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
418 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
419 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
420 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
421 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
422 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
423 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
424 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
425 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
426 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
427 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
428 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
429 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
430 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
431 base + HSIO_ANA_SERDES6G_IB_CFG);
432 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
433 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
434 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
435 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
436 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
437 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
438 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
439 base + HSIO_ANA_SERDES6G_IB_CFG1);
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100440
441 writel(HSIO_ANA_SERDES6G_IB_CFG2_UREG(4) |
442 HSIO_ANA_SERDES6G_IB_CFG2_UMAX(2) |
443 HSIO_ANA_SERDES6G_IB_CFG2_TCALV(12) |
444 HSIO_ANA_SERDES6G_IB_CFG2_OCALS(32) |
445 HSIO_ANA_SERDES6G_IB_CFG2_OINFS(7) |
446 HSIO_ANA_SERDES6G_IB_CFG2_OINFI(0x1f) |
447 HSIO_ANA_SERDES6G_IB_CFG2_TINFV(3),
448 base + HSIO_ANA_SERDES6G_IB_CFG2);
449
450 writel(HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(0x1f) |
451 HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(1) |
452 HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(0x1f),
453 base + HSIO_ANA_SERDES6G_IB_CFG3);
454
Horatiu Vultur43be1972019-04-03 19:54:45 +0200455 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
456 base + HSIO_DIG_SERDES6G_MISC_CFG);
457
458 serdes6g_write(base, addr);
459
460 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
461 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
462 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
463 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
464 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
465 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
466 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
467 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
468 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
469 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
470 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
471 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
472 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
473 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
474 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
475 base + HSIO_ANA_SERDES6G_IB_CFG);
476 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
477 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
478 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
479 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
480 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
481 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
482 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
483 base + HSIO_ANA_SERDES6G_IB_CFG1);
484
485 writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
486 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
487 HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
488 HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
489 HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
490 base + HSIO_ANA_SERDES6G_COMMON_CFG);
491 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
492 base + HSIO_DIG_SERDES6G_MISC_CFG);
493
494 writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
495 HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
496 HSIO_ANA_SERDES6G_OB_CFG_SR_H |
497 HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
498 HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
499 writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
500 HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
501 base + HSIO_ANA_SERDES6G_OB_CFG1);
502
503 writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
504 HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
505 HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
506 HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
507 base + HSIO_ANA_SERDES6G_DES_CFG);
508 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
509 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
510 base + HSIO_ANA_SERDES6G_PLL_CFG);
511
512 serdes6g_write(base, addr);
513
514 /* set pll_fsm_ena = 1 */
515 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
516 HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
517 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
518 base + HSIO_ANA_SERDES6G_PLL_CFG);
519
520 serdes6g_write(base, addr);
521
522 /* wait 20ms for pll bringup */
523 mdelay(20);
524
525 /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
526 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
527 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
528 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100529 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
Horatiu Vultur43be1972019-04-03 19:54:45 +0200530 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
531 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
532 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
533 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
534 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
535 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
536 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
537 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
538 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
539 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
540 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
541 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
542 base + HSIO_ANA_SERDES6G_IB_CFG);
543 writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
544
545 serdes6g_write(base, addr);
546
547 /* wait 60 for calibration */
548 mdelay(60);
549
550 /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
551 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
552 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
553 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
Horatiu Vulture49a0f32021-03-10 09:31:39 +0100554 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
Horatiu Vultur43be1972019-04-03 19:54:45 +0200555 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
556 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
557 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
558 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
559 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
560 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
561 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
562 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
563 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
564 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
565 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
566 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
567 base + HSIO_ANA_SERDES6G_IB_CFG);
568 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
569 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
570 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
571 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
572 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
573 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
574 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
575 base + HSIO_ANA_SERDES6G_IB_CFG1);
576
577 serdes6g_write(base, addr);
578}
579
580static void serdes1g_write(void __iomem *base, u32 addr)
581{
582 u32 data;
583
584 writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
585 HSIO_MCB_SERDES1G_CFG_ADDR(addr),
586 base + HSIO_MCB_SERDES1G_CFG);
587
588 do {
589 data = readl(base + HSIO_MCB_SERDES1G_CFG);
590 } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
591}
592
593static void serdes1g_setup(void __iomem *base, uint32_t addr,
594 phy_interface_t interface)
595{
596 writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
597 writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
598 writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
599 writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
600 HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
601 HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
602 HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
603 HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
604 base + HSIO_ANA_SERDES1G_OB_CFG);
605 writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
606 HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
607 HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
608 HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
609 HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
610 HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
611 HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
612 base + HSIO_ANA_SERDES1G_IB_CFG);
613 writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
614 HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
615 HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
616 HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
617 base + HSIO_ANA_SERDES1G_DES_CFG);
618 writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
619 base + HSIO_DIG_SERDES1G_MISC_CFG);
620 writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
621 HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
622 HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
623 base + HSIO_ANA_SERDES1G_PLL_CFG);
624 writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
625 HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
626 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
627 base + HSIO_ANA_SERDES1G_COMMON_CFG);
628
629 serdes1g_write(base, addr);
630
631 setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
632 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
633
634 serdes1g_write(base, addr);
635
636 clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
637 HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
638
639 serdes1g_write(base, addr);
640}
641
642static int ram_init(u32 val, void __iomem *addr)
643{
644 writel(val, addr);
645
646 if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
647 printf("Timeout in memory reset, reg = 0x%08x\n", val);
648 return 1;
649 }
650
651 return 0;
652}
653
654static int jr2_switch_init(struct jr2_private *priv)
655{
656 /* Initialize memories */
657 ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
658 ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
659 ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
660 ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
661
662 /* Reset counters */
663 writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
664 writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
665
666 /* Enable switch-core and queue system */
667 writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
668
669 return 0;
670}
671
672static void jr2_switch_config(struct jr2_private *priv)
673{
674 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
675 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
676 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
677 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
678
679 writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
680 QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
681 priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
682}
683
684static int jr2_initialize(struct jr2_private *priv)
685{
686 int ret, i;
687
688 /* Initialize switch memories, enable core */
689 ret = jr2_switch_init(priv);
690 if (ret)
691 return ret;
692
693 jr2_switch_config(priv);
694
695 for (i = 0; i < MAX_PORT; i++)
696 jr2_port_init(priv, i);
697
698 jr2_cpu_capture_setup(priv);
699
700 return 0;
701}
702
703static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
704{
705 if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
706 LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
707 false, 2000, false))
708 return -ETIMEDOUT;
709
710 return 0;
711}
712
713static int jr2_mac_table_add(struct jr2_private *priv,
714 const unsigned char mac[ETH_ALEN], int pgid)
715{
716 u32 macl = 0, mach = 0;
717
718 /*
719 * Set the MAC address to handle and the vlan associated in a format
720 * understood by the hardware.
721 */
722 mach |= MAC_VID << 16;
723 mach |= ((u32)mac[0]) << 8;
724 mach |= ((u32)mac[1]) << 0;
725 macl |= ((u32)mac[2]) << 24;
726 macl |= ((u32)mac[3]) << 16;
727 macl |= ((u32)mac[4]) << 8;
728 macl |= ((u32)mac[5]) << 0;
729
730 writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
731 writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
732
733 writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
734 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
735 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
736 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
737 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
738 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
739 priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
740
741 writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
742 priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
743
744 return jr2_vlant_wait_for_completion(priv);
745}
746
747static int jr2_write_hwaddr(struct udevice *dev)
748{
749 struct jr2_private *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700750 struct eth_pdata *pdata = dev_get_plat(dev);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200751
752 return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
753}
754
755static void serdes_setup(struct jr2_private *priv)
756{
757 size_t mask;
758 int i = 0;
759
760 for (i = 0; i < MAX_PORT; ++i) {
761 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
762 continue;
763
764 mask = BIT(priv->ports[i].serdes_index);
765 if (priv->ports[i].serdes_index < SERDES1G_MAX) {
766 serdes1g_setup(priv->regs[HSIO], mask,
767 priv->ports[i].phy_mode);
768 } else {
769 mask >>= SERDES6G(0);
770 serdes6g_setup(priv->regs[HSIO], mask,
771 priv->ports[i].phy_mode);
772 }
773 }
774}
775
776static int jr2_start(struct udevice *dev)
777{
778 struct jr2_private *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700779 struct eth_pdata *pdata = dev_get_plat(dev);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200780 const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
781 0xff };
782 int ret;
783
784 ret = jr2_initialize(priv);
785 if (ret)
786 return ret;
787
788 /* Set MAC address tables entries for CPU redirection */
789 ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
790 if (ret)
791 return ret;
792
793 ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
794 if (ret)
795 return ret;
796
797 serdes_setup(priv);
798
799 return 0;
800}
801
802static void jr2_stop(struct udevice *dev)
803{
804}
805
806static int jr2_send(struct udevice *dev, void *packet, int length)
807{
808 struct jr2_private *priv = dev_get_priv(dev);
809 u32 ifh[IFH_LEN];
810 u32 *buf = packet;
811
812 memset(ifh, '\0', IFH_LEN);
813
814 /* Set DST PORT_MASK */
815 ifh[0] = htonl(0);
816 ifh[1] = htonl(0x1FFFFF);
817 ifh[2] = htonl(~0);
818 /* Set DST_MODE to INJECT and UPDATE_FCS */
819 ifh[5] = htonl(0x4c0);
820
821 return mscc_send(priv->regs[QS], jr2_regs_qs,
822 ifh, IFH_LEN, buf, length);
823}
824
825static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
826{
827 struct jr2_private *priv = dev_get_priv(dev);
828 u32 *rxbuf = (u32 *)net_rx_packets[0];
829 int byte_cnt = 0;
830
831 byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
832 false);
833
834 *packetp = net_rx_packets[0];
835
836 return byte_cnt;
837}
838
839static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
840{
841 int i = 0;
842
843 for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
844 if (miim[i].miim_base == base && miim[i].miim_size == size)
845 return miim[i].bus;
846
847 return NULL;
848}
849
850static void add_port_entry(struct jr2_private *priv, size_t index,
851 size_t phy_addr, struct mii_dev *bus,
852 u8 serdes_index, u8 phy_mode)
853{
854 priv->ports[index].phy_addr = phy_addr;
855 priv->ports[index].bus = bus;
856 priv->ports[index].serdes_index = serdes_index;
857 priv->ports[index].phy_mode = phy_mode;
858}
859
860static int jr2_probe(struct udevice *dev)
861{
862 struct jr2_private *priv = dev_get_priv(dev);
863 int i;
864 int ret;
865 struct resource res;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200866 phys_addr_t addr_base;
867 unsigned long addr_size;
868 ofnode eth_node, node, mdio_node;
869 size_t phy_addr;
870 struct mii_dev *bus;
871 struct ofnode_phandle_args phandle;
872 struct phy_device *phy;
Horatiu Vultur034ac242021-03-10 09:31:38 +0100873 u32 val;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200874
875 if (!priv)
876 return -EINVAL;
877
878 /* Get registers and map them to the private structure */
879 for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
880 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
881 if (!priv->regs[i]) {
882 debug
883 ("Error can't get regs base addresses for %s\n",
884 regs_names[i]);
885 return -ENOMEM;
886 }
887 }
888
Horatiu Vultur034ac242021-03-10 09:31:38 +0100889 val = readl(priv->regs[ICPU] + ICPU_RESET);
890 val |= ICPU_RESET_CORE_RST_PROTECT;
891 writel(val, priv->regs[ICPU] + ICPU_RESET);
892
893 val = readl(priv->regs[GCB] + PERF_SOFT_RST);
894 val |= PERF_SOFT_RST_SOFT_SWC_RST;
895 writel(val, priv->regs[GCB] + PERF_SOFT_RST);
896
897 while (readl(priv->regs[GCB] + PERF_SOFT_RST) & PERF_SOFT_RST_SOFT_SWC_RST)
898 ;
899
Horatiu Vultur43be1972019-04-03 19:54:45 +0200900 /* Initialize miim buses */
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200901 memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200902
903 /* iterate all the ports and find out on which bus they are */
904 i = 0;
905 eth_node = dev_read_first_subnode(dev);
906 for (node = ofnode_first_subnode(eth_node);
907 ofnode_valid(node);
908 node = ofnode_next_subnode(node)) {
909 if (ofnode_read_resource(node, 0, &res))
910 return -ENOMEM;
911 i = res.start;
912
913 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
914 0, 0, &phandle);
915 if (ret)
916 continue;
917
918 /* Get phy address on mdio bus */
919 if (ofnode_read_resource(phandle.node, 0, &res))
920 return -ENOMEM;
921 phy_addr = res.start;
922
923 /* Get mdio node */
924 mdio_node = ofnode_get_parent(phandle.node);
925
926 if (ofnode_read_resource(mdio_node, 0, &res))
927 return -ENOMEM;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200928
Patrick Delaunay2a28c6e2021-04-06 09:38:06 +0200929 addr_base = res.start;
Horatiu Vultur43be1972019-04-03 19:54:45 +0200930 addr_size = res.end - res.start;
931
932 /* If the bus is new then create a new bus */
933 if (!get_mdiobus(addr_base, addr_size))
934 priv->bus[miim_count] =
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200935 mscc_mdiobus_init(miim, &miim_count, addr_base,
936 addr_size);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200937
938 /* Connect mdio bus with the port */
939 bus = get_mdiobus(addr_base, addr_size);
940
941 /* Get serdes info */
942 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
943 3, 0, &phandle);
944 if (ret)
945 return -ENOMEM;
946
947 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
948 phandle.args[2]);
949 }
950
951 for (i = 0; i < MAX_PORT; i++) {
952 if (!priv->ports[i].bus)
953 continue;
954
955 phy = phy_connect(priv->ports[i].bus,
956 priv->ports[i].phy_addr, dev,
Marek BehĂșn48631e42022-04-07 00:33:03 +0200957 PHY_INTERFACE_MODE_NA);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200958 if (phy)
959 board_phy_config(phy);
960 }
961
962 return 0;
963}
964
965static int jr2_remove(struct udevice *dev)
966{
967 struct jr2_private *priv = dev_get_priv(dev);
968 int i;
969
970 for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
971 mdio_unregister(priv->bus[i]);
972 mdio_free(priv->bus[i]);
973 }
974
975 return 0;
976}
977
978static const struct eth_ops jr2_ops = {
979 .start = jr2_start,
980 .stop = jr2_stop,
981 .send = jr2_send,
982 .recv = jr2_recv,
983 .write_hwaddr = jr2_write_hwaddr,
984};
985
986static const struct udevice_id mscc_jr2_ids[] = {
987 {.compatible = "mscc,vsc7454-switch" },
988 { /* Sentinel */ }
989};
990
991U_BOOT_DRIVER(jr2) = {
992 .name = "jr2-switch",
993 .id = UCLASS_ETH,
994 .of_match = mscc_jr2_ids,
995 .probe = jr2_probe,
996 .remove = jr2_remove,
997 .ops = &jr2_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700998 .priv_auto = sizeof(struct jr2_private),
Simon Glass71fa5b42020-12-03 16:55:18 -0700999 .plat_auto = sizeof(struct eth_pdata),
Horatiu Vultur43be1972019-04-03 19:54:45 +02001000};