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