blob: 1c9a401de81e62a1fcff825ef700e9565864aa22 [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",
238 "qfwd", "qs", "qsys", "rew",
239};
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,
255};
256
257#define JR2_MIIM_BUS_COUNT 3
258
259struct jr2_phy_port_t {
260 size_t phy_addr;
261 struct mii_dev *bus;
262 u8 serdes_index;
263 u8 phy_mode;
264};
265
266struct jr2_private {
267 void __iomem *regs[REGS_NAMES_COUNT];
268 struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
269 struct jr2_phy_port_t ports[MAX_PORT];
270};
271
Horatiu Vultur43be1972019-04-03 19:54:45 +0200272static const unsigned long jr2_regs_qs[] = {
273 [MSCC_QS_XTR_RD] = 0x8,
274 [MSCC_QS_XTR_FLUSH] = 0x18,
275 [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
276 [MSCC_QS_INJ_WR] = 0x2c,
277 [MSCC_QS_INJ_CTRL] = 0x34,
278};
279
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200280static struct mscc_miim_dev miim[JR2_MIIM_BUS_COUNT];
Horatiu Vultur43be1972019-04-03 19:54:45 +0200281static int miim_count = -1;
282
Horatiu Vultur43be1972019-04-03 19:54:45 +0200283static void jr2_cpu_capture_setup(struct jr2_private *priv)
284{
285 /* ASM: No preamble and IFH prefix on CPU injected frames */
286 writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
287 ASM_CFG_PORT_INJ_FORMAT_CFG(1),
288 priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
289
290 /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
291 writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
292
293 /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
294 writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
295
296 /* Enable CPU port for any frame transfer */
297 setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
298 QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
299
300 /* Send a copy to CPU when found as forwarding entry */
301 setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
302 ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
303}
304
305static void jr2_port_init(struct jr2_private *priv, int port)
306{
307 void __iomem *regs = priv->regs[port];
308
309 /* Enable PCS */
310 writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
311 regs + DEV_PCS1G_CFG_PCS1G_CFG);
312
313 /* Disable Signal Detect */
314 writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
315
316 /* Enable MAC RX and TX */
317 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
318 DEV_MAC_CFG_MAC_ENA_TX_ENA,
319 regs + DEV_MAC_CFG_MAC_ENA);
320
321 /* Clear sgmii_mode_ena */
322 writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
323
324 /*
325 * Clear sw_resolve_ena(bit 0) and set adv_ability to
326 * something meaningful just in case
327 */
328 writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
329 regs + DEV_PCS1G_CFG_PCS1G_ANEG);
330
331 /* Set MAC IFG Gaps */
332 writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
333 DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
334 DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
335 regs + DEV_MAC_CFG_MAC_IFG);
336
337 /* Set link speed and release all resets */
338 writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
339 regs + DEV_DEV_CFG_DEV_RST_CTRL);
340
341 /* Make VLAN aware for CPU traffic */
342 writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
343 ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
344 MAC_VID,
345 priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
346
347 /* Enable CPU port for any frame transfer */
348 setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
349 QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
350}
351
352static void serdes6g_write(void __iomem *base, u32 addr)
353{
354 u32 data;
355
356 writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
357 HSIO_MCB_SERDES6G_CFG_ADDR(addr),
358 base + HSIO_MCB_SERDES6G_CFG);
359
360 do {
361 data = readl(base + HSIO_MCB_SERDES6G_CFG);
362 } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
363}
364
365static void serdes6g_setup(void __iomem *base, uint32_t addr,
366 phy_interface_t interface)
367{
368 u32 ib_if_mode = 0;
369 u32 ib_qrate = 0;
370 u32 ib_cal_ena = 0;
371 u32 ib1_tsdet = 0;
372 u32 ob_lev = 0;
373 u32 ob_ena_cas = 0;
374 u32 ob_ena1v_mode = 0;
375 u32 des_bw_ana = 0;
376 u32 pll_fsm_ctrl_data = 0;
377
378 switch (interface) {
379 case PHY_INTERFACE_MODE_SGMII:
380 ib_if_mode = 1;
381 ib_qrate = 1;
382 ib_cal_ena = 1;
383 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
405 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
406 base + HSIO_ANA_SERDES6G_COMMON_CFG);
407 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
408 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
409 base + HSIO_ANA_SERDES6G_PLL_CFG);
410 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
411 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
412 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
413 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
414 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
415 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
416 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
417 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
418 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
419 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
420 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
421 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
422 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
423 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
424 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
425 base + HSIO_ANA_SERDES6G_IB_CFG);
426 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
427 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
428 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
429 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
430 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
431 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
432 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
433 base + HSIO_ANA_SERDES6G_IB_CFG1);
434 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
435 base + HSIO_DIG_SERDES6G_MISC_CFG);
436
437 serdes6g_write(base, addr);
438
439 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
440 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
441 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
442 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
443 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
444 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
445 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
446 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
447 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
448 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
449 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
450 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
451 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
452 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
453 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
454 base + HSIO_ANA_SERDES6G_IB_CFG);
455 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
456 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
457 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
458 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
459 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
460 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
461 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
462 base + HSIO_ANA_SERDES6G_IB_CFG1);
463
464 writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
465 writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
466 HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
467 HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
468 HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
469 base + HSIO_ANA_SERDES6G_COMMON_CFG);
470 writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
471 base + HSIO_DIG_SERDES6G_MISC_CFG);
472
473 writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
474 HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
475 HSIO_ANA_SERDES6G_OB_CFG_SR_H |
476 HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
477 HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
478 writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
479 HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
480 base + HSIO_ANA_SERDES6G_OB_CFG1);
481
482 writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
483 HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
484 HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
485 HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
486 base + HSIO_ANA_SERDES6G_DES_CFG);
487 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
488 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
489 base + HSIO_ANA_SERDES6G_PLL_CFG);
490
491 serdes6g_write(base, addr);
492
493 /* set pll_fsm_ena = 1 */
494 writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
495 HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
496 HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
497 base + HSIO_ANA_SERDES6G_PLL_CFG);
498
499 serdes6g_write(base, addr);
500
501 /* wait 20ms for pll bringup */
502 mdelay(20);
503
504 /* start IB calibration by setting ib_cal_ena and clearing lane_rst */
505 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
506 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
507 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
508 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
509 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
510 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
511 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
512 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
513 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
514 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
515 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
516 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
517 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
518 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
519 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
520 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
521 base + HSIO_ANA_SERDES6G_IB_CFG);
522 writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
523
524 serdes6g_write(base, addr);
525
526 /* wait 60 for calibration */
527 mdelay(60);
528
529 /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
530 writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
531 HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
532 HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
533 HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
534 HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
535 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
536 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
537 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
538 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
539 HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
540 HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
541 HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
542 HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
543 HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
544 HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
545 HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
546 base + HSIO_ANA_SERDES6G_IB_CFG);
547 writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
548 HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
549 HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
550 HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
551 HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
552 HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
553 HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
554 base + HSIO_ANA_SERDES6G_IB_CFG1);
555
556 serdes6g_write(base, addr);
557}
558
559static void serdes1g_write(void __iomem *base, u32 addr)
560{
561 u32 data;
562
563 writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
564 HSIO_MCB_SERDES1G_CFG_ADDR(addr),
565 base + HSIO_MCB_SERDES1G_CFG);
566
567 do {
568 data = readl(base + HSIO_MCB_SERDES1G_CFG);
569 } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
570}
571
572static void serdes1g_setup(void __iomem *base, uint32_t addr,
573 phy_interface_t interface)
574{
575 writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
576 writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
577 writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
578 writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
579 HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
580 HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
581 HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
582 HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
583 base + HSIO_ANA_SERDES1G_OB_CFG);
584 writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
585 HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
586 HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
587 HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
588 HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
589 HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
590 HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
591 base + HSIO_ANA_SERDES1G_IB_CFG);
592 writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
593 HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
594 HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
595 HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
596 base + HSIO_ANA_SERDES1G_DES_CFG);
597 writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
598 base + HSIO_DIG_SERDES1G_MISC_CFG);
599 writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
600 HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
601 HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
602 base + HSIO_ANA_SERDES1G_PLL_CFG);
603 writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
604 HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
605 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
606 base + HSIO_ANA_SERDES1G_COMMON_CFG);
607
608 serdes1g_write(base, addr);
609
610 setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
611 HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
612
613 serdes1g_write(base, addr);
614
615 clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
616 HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
617
618 serdes1g_write(base, addr);
619}
620
621static int ram_init(u32 val, void __iomem *addr)
622{
623 writel(val, addr);
624
625 if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
626 printf("Timeout in memory reset, reg = 0x%08x\n", val);
627 return 1;
628 }
629
630 return 0;
631}
632
633static int jr2_switch_init(struct jr2_private *priv)
634{
635 /* Initialize memories */
636 ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
637 ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
638 ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
639 ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
640
641 /* Reset counters */
642 writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
643 writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
644
645 /* Enable switch-core and queue system */
646 writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
647
648 return 0;
649}
650
651static void jr2_switch_config(struct jr2_private *priv)
652{
653 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
654 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
655 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
656 writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
657
658 writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
659 QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
660 priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
661}
662
663static int jr2_initialize(struct jr2_private *priv)
664{
665 int ret, i;
666
667 /* Initialize switch memories, enable core */
668 ret = jr2_switch_init(priv);
669 if (ret)
670 return ret;
671
672 jr2_switch_config(priv);
673
674 for (i = 0; i < MAX_PORT; i++)
675 jr2_port_init(priv, i);
676
677 jr2_cpu_capture_setup(priv);
678
679 return 0;
680}
681
682static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
683{
684 if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
685 LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
686 false, 2000, false))
687 return -ETIMEDOUT;
688
689 return 0;
690}
691
692static int jr2_mac_table_add(struct jr2_private *priv,
693 const unsigned char mac[ETH_ALEN], int pgid)
694{
695 u32 macl = 0, mach = 0;
696
697 /*
698 * Set the MAC address to handle and the vlan associated in a format
699 * understood by the hardware.
700 */
701 mach |= MAC_VID << 16;
702 mach |= ((u32)mac[0]) << 8;
703 mach |= ((u32)mac[1]) << 0;
704 macl |= ((u32)mac[2]) << 24;
705 macl |= ((u32)mac[3]) << 16;
706 macl |= ((u32)mac[4]) << 8;
707 macl |= ((u32)mac[5]) << 0;
708
709 writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
710 writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
711
712 writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
713 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
714 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
715 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
716 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
717 LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
718 priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
719
720 writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
721 priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
722
723 return jr2_vlant_wait_for_completion(priv);
724}
725
726static int jr2_write_hwaddr(struct udevice *dev)
727{
728 struct jr2_private *priv = dev_get_priv(dev);
729 struct eth_pdata *pdata = dev_get_platdata(dev);
730
731 return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
732}
733
734static void serdes_setup(struct jr2_private *priv)
735{
736 size_t mask;
737 int i = 0;
738
739 for (i = 0; i < MAX_PORT; ++i) {
740 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
741 continue;
742
743 mask = BIT(priv->ports[i].serdes_index);
744 if (priv->ports[i].serdes_index < SERDES1G_MAX) {
745 serdes1g_setup(priv->regs[HSIO], mask,
746 priv->ports[i].phy_mode);
747 } else {
748 mask >>= SERDES6G(0);
749 serdes6g_setup(priv->regs[HSIO], mask,
750 priv->ports[i].phy_mode);
751 }
752 }
753}
754
755static int jr2_start(struct udevice *dev)
756{
757 struct jr2_private *priv = dev_get_priv(dev);
758 struct eth_pdata *pdata = dev_get_platdata(dev);
759 const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
760 0xff };
761 int ret;
762
763 ret = jr2_initialize(priv);
764 if (ret)
765 return ret;
766
767 /* Set MAC address tables entries for CPU redirection */
768 ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
769 if (ret)
770 return ret;
771
772 ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
773 if (ret)
774 return ret;
775
776 serdes_setup(priv);
777
778 return 0;
779}
780
781static void jr2_stop(struct udevice *dev)
782{
783}
784
785static int jr2_send(struct udevice *dev, void *packet, int length)
786{
787 struct jr2_private *priv = dev_get_priv(dev);
788 u32 ifh[IFH_LEN];
789 u32 *buf = packet;
790
791 memset(ifh, '\0', IFH_LEN);
792
793 /* Set DST PORT_MASK */
794 ifh[0] = htonl(0);
795 ifh[1] = htonl(0x1FFFFF);
796 ifh[2] = htonl(~0);
797 /* Set DST_MODE to INJECT and UPDATE_FCS */
798 ifh[5] = htonl(0x4c0);
799
800 return mscc_send(priv->regs[QS], jr2_regs_qs,
801 ifh, IFH_LEN, buf, length);
802}
803
804static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
805{
806 struct jr2_private *priv = dev_get_priv(dev);
807 u32 *rxbuf = (u32 *)net_rx_packets[0];
808 int byte_cnt = 0;
809
810 byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
811 false);
812
813 *packetp = net_rx_packets[0];
814
815 return byte_cnt;
816}
817
818static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
819{
820 int i = 0;
821
822 for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
823 if (miim[i].miim_base == base && miim[i].miim_size == size)
824 return miim[i].bus;
825
826 return NULL;
827}
828
829static void add_port_entry(struct jr2_private *priv, size_t index,
830 size_t phy_addr, struct mii_dev *bus,
831 u8 serdes_index, u8 phy_mode)
832{
833 priv->ports[index].phy_addr = phy_addr;
834 priv->ports[index].bus = bus;
835 priv->ports[index].serdes_index = serdes_index;
836 priv->ports[index].phy_mode = phy_mode;
837}
838
839static int jr2_probe(struct udevice *dev)
840{
841 struct jr2_private *priv = dev_get_priv(dev);
842 int i;
843 int ret;
844 struct resource res;
845 fdt32_t faddr;
846 phys_addr_t addr_base;
847 unsigned long addr_size;
848 ofnode eth_node, node, mdio_node;
849 size_t phy_addr;
850 struct mii_dev *bus;
851 struct ofnode_phandle_args phandle;
852 struct phy_device *phy;
853
854 if (!priv)
855 return -EINVAL;
856
857 /* Get registers and map them to the private structure */
858 for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
859 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
860 if (!priv->regs[i]) {
861 debug
862 ("Error can't get regs base addresses for %s\n",
863 regs_names[i]);
864 return -ENOMEM;
865 }
866 }
867
868 /* Initialize miim buses */
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200869 memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200870
871 /* iterate all the ports and find out on which bus they are */
872 i = 0;
873 eth_node = dev_read_first_subnode(dev);
874 for (node = ofnode_first_subnode(eth_node);
875 ofnode_valid(node);
876 node = ofnode_next_subnode(node)) {
877 if (ofnode_read_resource(node, 0, &res))
878 return -ENOMEM;
879 i = res.start;
880
881 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
882 0, 0, &phandle);
883 if (ret)
884 continue;
885
886 /* Get phy address on mdio bus */
887 if (ofnode_read_resource(phandle.node, 0, &res))
888 return -ENOMEM;
889 phy_addr = res.start;
890
891 /* Get mdio node */
892 mdio_node = ofnode_get_parent(phandle.node);
893
894 if (ofnode_read_resource(mdio_node, 0, &res))
895 return -ENOMEM;
896 faddr = cpu_to_fdt32(res.start);
897
898 addr_base = ofnode_translate_address(mdio_node, &faddr);
899 addr_size = res.end - res.start;
900
901 /* If the bus is new then create a new bus */
902 if (!get_mdiobus(addr_base, addr_size))
903 priv->bus[miim_count] =
Horatiu Vultur6fbf1612019-06-09 15:27:29 +0200904 mscc_mdiobus_init(miim, &miim_count, addr_base,
905 addr_size);
Horatiu Vultur43be1972019-04-03 19:54:45 +0200906
907 /* Connect mdio bus with the port */
908 bus = get_mdiobus(addr_base, addr_size);
909
910 /* Get serdes info */
911 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
912 3, 0, &phandle);
913 if (ret)
914 return -ENOMEM;
915
916 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
917 phandle.args[2]);
918 }
919
920 for (i = 0; i < MAX_PORT; i++) {
921 if (!priv->ports[i].bus)
922 continue;
923
924 phy = phy_connect(priv->ports[i].bus,
925 priv->ports[i].phy_addr, dev,
926 PHY_INTERFACE_MODE_NONE);
927 if (phy)
928 board_phy_config(phy);
929 }
930
931 return 0;
932}
933
934static int jr2_remove(struct udevice *dev)
935{
936 struct jr2_private *priv = dev_get_priv(dev);
937 int i;
938
939 for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
940 mdio_unregister(priv->bus[i]);
941 mdio_free(priv->bus[i]);
942 }
943
944 return 0;
945}
946
947static const struct eth_ops jr2_ops = {
948 .start = jr2_start,
949 .stop = jr2_stop,
950 .send = jr2_send,
951 .recv = jr2_recv,
952 .write_hwaddr = jr2_write_hwaddr,
953};
954
955static const struct udevice_id mscc_jr2_ids[] = {
956 {.compatible = "mscc,vsc7454-switch" },
957 { /* Sentinel */ }
958};
959
960U_BOOT_DRIVER(jr2) = {
961 .name = "jr2-switch",
962 .id = UCLASS_ETH,
963 .of_match = mscc_jr2_ids,
964 .probe = jr2_probe,
965 .remove = jr2_remove,
966 .ops = &jr2_ops,
967 .priv_auto_alloc_size = sizeof(struct jr2_private),
968 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
969};