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