blob: 4e1aff6e3a86f70ca492c0ca7cd7d73a6ddadf45 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +05302/*
3 * (C) Copyright 2009
4 * Marvell Semiconductor <www.marvell.com>
5 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
6 *
7 * (C) Copyright 2003
8 * Ingo Assmus <ingo.assmus@keymile.com>
9 *
10 * based on - Driver for MV64360X ethernet ports
11 * Copyright (C) 2002 rabeeh@galileo.co.il
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053012 */
13
14#include <common.h>
15#include <net.h>
16#include <malloc.h>
17#include <miiphy.h>
Lei Wen298ae912011-10-18 20:11:42 +053018#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090019#include <linux/errno.h>
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053020#include <asm/types.h>
Lei Wen298ae912011-10-18 20:11:42 +053021#include <asm/system.h>
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053022#include <asm/byteorder.h>
Anatolij Gustschinc8b222e2011-10-29 10:09:22 +000023#include <asm/arch/cpu.h>
Albert Aribaude91d7d32010-07-12 22:24:28 +020024
25#if defined(CONFIG_KIRKWOOD)
Stefan Roesec2437842014-10-22 12:13:06 +020026#include <asm/arch/soc.h>
Albert Aribaud8a995232010-07-12 22:24:29 +020027#elif defined(CONFIG_ORION5X)
28#include <asm/arch/orion5x.h>
Albert Aribaude91d7d32010-07-12 22:24:28 +020029#endif
30
Albert Aribaud0d027d92010-07-12 22:24:27 +020031#include "mvgbe.h"
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053032
Albert Aribauda7564072010-07-05 20:15:25 +020033DECLARE_GLOBAL_DATA_PTR;
34
Luka Perkov95acd992013-11-11 07:27:53 +010035#ifndef CONFIG_MVGBE_PORTS
36# define CONFIG_MVGBE_PORTS {0, 0}
37#endif
38
Albert Aribaude91d7d32010-07-12 22:24:28 +020039#define MV_PHY_ADR_REQUEST 0xee
40#define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
Simon Kagstromab9ca512009-08-20 10:12:28 +020041
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +010042#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053043/*
44 * smi_reg_read - miiphy_read callback function.
45 *
46 * Returns 16bit phy register value, or 0xffff on error
47 */
Joe Hershberger1fbcbed2016-08-08 11:28:38 -050048static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
49 int reg_ofs)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053050{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -050051 u16 data = 0;
52 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Albert Aribaude91d7d32010-07-12 22:24:28 +020053 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
54 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053055 u32 smi_reg;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +020056 u32 timeout;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053057
58 /* Phyadr read request */
Albert Aribaude91d7d32010-07-12 22:24:28 +020059 if (phy_adr == MV_PHY_ADR_REQUEST &&
60 reg_ofs == MV_PHY_ADR_REQUEST) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053061 /* */
Joe Hershberger1fbcbed2016-08-08 11:28:38 -050062 data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
63 return data;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053064 }
65 /* check parameters */
66 if (phy_adr > PHYADR_MASK) {
67 printf("Err..(%s) Invalid PHY address %d\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -050068 __func__, phy_adr);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053069 return -EFAULT;
70 }
71 if (reg_ofs > PHYREG_MASK) {
72 printf("Err..(%s) Invalid register offset %d\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -050073 __func__, reg_ofs);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053074 return -EFAULT;
75 }
76
Albert Aribaude91d7d32010-07-12 22:24:28 +020077 timeout = MVGBE_PHY_SMI_TIMEOUT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053078 /* wait till the SMI is not busy */
79 do {
80 /* read smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +020081 smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053082 if (timeout-- == 0) {
Joe Hershberger9f09a362015-04-08 01:41:06 -050083 printf("Err..(%s) SMI busy timeout\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053084 return -EFAULT;
85 }
Albert Aribaude91d7d32010-07-12 22:24:28 +020086 } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053087
88 /* fill the phy address and regiser offset and read opcode */
Albert Aribaude91d7d32010-07-12 22:24:28 +020089 smi_reg = (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
90 | (reg_ofs << MVGBE_SMI_REG_ADDR_OFFS)
91 | MVGBE_PHY_SMI_OPCODE_READ;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053092
93 /* write the smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +020094 MVGBE_REG_WR(MVGBE_SMI_REG, smi_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053095
96 /*wait till read value is ready */
Albert Aribaude91d7d32010-07-12 22:24:28 +020097 timeout = MVGBE_PHY_SMI_TIMEOUT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053098
99 do {
100 /* read smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200101 smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530102 if (timeout-- == 0) {
103 printf("Err..(%s) SMI read ready timeout\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500104 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530105 return -EFAULT;
106 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200107 } while (!(smi_reg & MVGBE_PHY_SMI_READ_VALID_MASK));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530108
109 /* Wait for the data to update in the SMI register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200110 for (timeout = 0; timeout < MVGBE_PHY_SMI_TIMEOUT; timeout++)
111 ;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530112
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500113 data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530114
Joe Hershberger9f09a362015-04-08 01:41:06 -0500115 debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500116 data);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530117
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500118 return data;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530119}
120
121/*
122 * smi_reg_write - imiiphy_write callback function.
123 *
124 * Returns 0 if write succeed, -EINVAL on bad parameters
125 * -ETIME on timeout
126 */
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500127static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
128 int reg_ofs, u16 data)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530129{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500130 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Albert Aribaude91d7d32010-07-12 22:24:28 +0200131 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
132 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530133 u32 smi_reg;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200134 u32 timeout;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530135
136 /* Phyadr write request*/
Albert Aribaude91d7d32010-07-12 22:24:28 +0200137 if (phy_adr == MV_PHY_ADR_REQUEST &&
138 reg_ofs == MV_PHY_ADR_REQUEST) {
139 MVGBE_REG_WR(regs->phyadr, data);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530140 return 0;
141 }
142
143 /* check parameters */
144 if (phy_adr > PHYADR_MASK) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500145 printf("Err..(%s) Invalid phy address\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530146 return -EINVAL;
147 }
148 if (reg_ofs > PHYREG_MASK) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500149 printf("Err..(%s) Invalid register offset\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530150 return -EINVAL;
151 }
152
153 /* wait till the SMI is not busy */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200154 timeout = MVGBE_PHY_SMI_TIMEOUT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530155 do {
156 /* read smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200157 smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530158 if (timeout-- == 0) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500159 printf("Err..(%s) SMI busy timeout\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530160 return -ETIME;
161 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200162 } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530163
164 /* fill the phy addr and reg offset and write opcode and data */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200165 smi_reg = (data << MVGBE_PHY_SMI_DATA_OFFS);
166 smi_reg |= (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
167 | (reg_ofs << MVGBE_SMI_REG_ADDR_OFFS);
168 smi_reg &= ~MVGBE_PHY_SMI_OPCODE_READ;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530169
170 /* write the smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200171 MVGBE_REG_WR(MVGBE_SMI_REG, smi_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530172
173 return 0;
174}
Stefan Bigler96455292012-03-26 00:02:13 +0000175#endif
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530176
177/* Stop and checks all queues */
178static void stop_queue(u32 * qreg)
179{
180 u32 reg_data;
181
182 reg_data = readl(qreg);
183
184 if (reg_data & 0xFF) {
185 /* Issue stop command for active channels only */
186 writel((reg_data << 8), qreg);
187
188 /* Wait for all queue activity to terminate. */
189 do {
190 /*
191 * Check port cause register that all queues
192 * are stopped
193 */
194 reg_data = readl(qreg);
195 }
196 while (reg_data & 0xFF);
197 }
198}
199
200/*
201 * set_access_control - Config address decode parameters for Ethernet unit
202 *
203 * This function configures the address decode parameters for the Gigabit
204 * Ethernet Controller according the given parameters struct.
205 *
206 * @regs Register struct pointer.
207 * @param Address decode parameter struct.
208 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200209static void set_access_control(struct mvgbe_registers *regs,
210 struct mvgbe_winparam *param)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530211{
212 u32 access_prot_reg;
213
214 /* Set access control register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200215 access_prot_reg = MVGBE_REG_RD(regs->epap);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530216 /* clear window permission */
217 access_prot_reg &= (~(3 << (param->win * 2)));
218 access_prot_reg |= (param->access_ctrl << (param->win * 2));
Albert Aribaude91d7d32010-07-12 22:24:28 +0200219 MVGBE_REG_WR(regs->epap, access_prot_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530220
221 /* Set window Size reg (SR) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200222 MVGBE_REG_WR(regs->barsz[param->win].size,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530223 (((param->size / 0x10000) - 1) << 16));
224
225 /* Set window Base address reg (BA) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200226 MVGBE_REG_WR(regs->barsz[param->win].bar,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530227 (param->target | param->attrib | param->base_addr));
228 /* High address remap reg (HARR) */
229 if (param->win < 4)
Albert Aribaude91d7d32010-07-12 22:24:28 +0200230 MVGBE_REG_WR(regs->ha_remap[param->win], param->high_addr);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530231
232 /* Base address enable reg (BARER) */
233 if (param->enable == 1)
Albert Aribaude91d7d32010-07-12 22:24:28 +0200234 MVGBE_REG_BITS_RESET(regs->bare, (1 << param->win));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530235 else
Albert Aribaude91d7d32010-07-12 22:24:28 +0200236 MVGBE_REG_BITS_SET(regs->bare, (1 << param->win));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530237}
238
Albert Aribaude91d7d32010-07-12 22:24:28 +0200239static void set_dram_access(struct mvgbe_registers *regs)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530240{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200241 struct mvgbe_winparam win_param;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530242 int i;
243
244 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
245 /* Set access parameters for DRAM bank i */
246 win_param.win = i; /* Use Ethernet window i */
247 /* Window target - DDR */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200248 win_param.target = MVGBE_TARGET_DRAM;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530249 /* Enable full access */
250 win_param.access_ctrl = EWIN_ACCESS_FULL;
251 win_param.high_addr = 0;
Albert Aribauda7564072010-07-05 20:15:25 +0200252 /* Get bank base and size */
253 win_param.base_addr = gd->bd->bi_dram[i].start;
254 win_param.size = gd->bd->bi_dram[i].size;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530255 if (win_param.size == 0)
256 win_param.enable = 0;
257 else
258 win_param.enable = 1; /* Enable the access */
259
260 /* Enable DRAM bank */
261 switch (i) {
262 case 0:
263 win_param.attrib = EBAR_DRAM_CS0;
264 break;
265 case 1:
266 win_param.attrib = EBAR_DRAM_CS1;
267 break;
268 case 2:
269 win_param.attrib = EBAR_DRAM_CS2;
270 break;
271 case 3:
272 win_param.attrib = EBAR_DRAM_CS3;
273 break;
274 default:
Albert Aribauda7564072010-07-05 20:15:25 +0200275 /* invalid bank, disable access */
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530276 win_param.enable = 0;
277 win_param.attrib = 0;
278 break;
279 }
280 /* Set the access control for address window(EPAPR) RD/WR */
281 set_access_control(regs, &win_param);
282 }
283}
284
285/*
286 * port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
287 *
288 * Go through all the DA filter tables (Unicast, Special Multicast & Other
289 * Multicast) and set each entry to 0.
290 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200291static void port_init_mac_tables(struct mvgbe_registers *regs)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530292{
293 int table_index;
294
295 /* Clear DA filter unicast table (Ex_dFUT) */
296 for (table_index = 0; table_index < 4; ++table_index)
Albert Aribaude91d7d32010-07-12 22:24:28 +0200297 MVGBE_REG_WR(regs->dfut[table_index], 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530298
299 for (table_index = 0; table_index < 64; ++table_index) {
300 /* Clear DA filter special multicast table (Ex_dFSMT) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200301 MVGBE_REG_WR(regs->dfsmt[table_index], 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530302 /* Clear DA filter other multicast table (Ex_dFOMT) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200303 MVGBE_REG_WR(regs->dfomt[table_index], 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530304 }
305}
306
307/*
308 * port_uc_addr - This function Set the port unicast address table
309 *
310 * This function locates the proper entry in the Unicast table for the
311 * specified MAC nibble and sets its properties according to function
312 * parameters.
313 * This function add/removes MAC addresses from the port unicast address
314 * table.
315 *
316 * @uc_nibble Unicast MAC Address last nibble.
317 * @option 0 = Add, 1 = remove address.
318 *
319 * RETURN: 1 if output succeeded. 0 if option parameter is invalid.
320 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200321static int port_uc_addr(struct mvgbe_registers *regs, u8 uc_nibble,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530322 int option)
323{
324 u32 unicast_reg;
325 u32 tbl_offset;
326 u32 reg_offset;
327
328 /* Locate the Unicast table entry */
329 uc_nibble = (0xf & uc_nibble);
330 /* Register offset from unicast table base */
331 tbl_offset = (uc_nibble / 4);
332 /* Entry offset within the above register */
333 reg_offset = uc_nibble % 4;
334
335 switch (option) {
336 case REJECT_MAC_ADDR:
337 /*
338 * Clear accepts frame bit at specified unicast
339 * DA table entry
340 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200341 unicast_reg = MVGBE_REG_RD(regs->dfut[tbl_offset]);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530342 unicast_reg &= (0xFF << (8 * reg_offset));
Albert Aribaude91d7d32010-07-12 22:24:28 +0200343 MVGBE_REG_WR(regs->dfut[tbl_offset], unicast_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530344 break;
345 case ACCEPT_MAC_ADDR:
346 /* Set accepts frame bit at unicast DA filter table entry */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200347 unicast_reg = MVGBE_REG_RD(regs->dfut[tbl_offset]);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530348 unicast_reg &= (0xFF << (8 * reg_offset));
349 unicast_reg |= ((0x01 | (RXUQ << 1)) << (8 * reg_offset));
Albert Aribaude91d7d32010-07-12 22:24:28 +0200350 MVGBE_REG_WR(regs->dfut[tbl_offset], unicast_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530351 break;
352 default:
353 return 0;
354 }
355 return 1;
356}
357
358/*
359 * port_uc_addr_set - This function Set the port Unicast address.
360 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200361static void port_uc_addr_set(struct mvgbe_registers *regs, u8 * p_addr)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530362{
363 u32 mac_h;
364 u32 mac_l;
365
366 mac_l = (p_addr[4] << 8) | (p_addr[5]);
367 mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
368 (p_addr[3] << 0);
369
Albert Aribaude91d7d32010-07-12 22:24:28 +0200370 MVGBE_REG_WR(regs->macal, mac_l);
371 MVGBE_REG_WR(regs->macah, mac_h);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530372
373 /* Accept frames of this address */
374 port_uc_addr(regs, p_addr[5], ACCEPT_MAC_ADDR);
375}
376
377/*
Albert Aribaude91d7d32010-07-12 22:24:28 +0200378 * mvgbe_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530379 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200380static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530381{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200382 struct mvgbe_rxdesc *p_rx_desc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530383 int i;
384
385 /* initialize the Rx descriptors ring */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200386 p_rx_desc = dmvgbe->p_rxdesc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530387 for (i = 0; i < RINGSZ; i++) {
388 p_rx_desc->cmd_sts =
Albert Aribaude91d7d32010-07-12 22:24:28 +0200389 MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530390 p_rx_desc->buf_size = PKTSIZE_ALIGN;
391 p_rx_desc->byte_cnt = 0;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200392 p_rx_desc->buf_ptr = dmvgbe->p_rxbuf + i * PKTSIZE_ALIGN;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530393 if (i == (RINGSZ - 1))
Albert Aribaude91d7d32010-07-12 22:24:28 +0200394 p_rx_desc->nxtdesc_p = dmvgbe->p_rxdesc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530395 else {
Albert Aribaude91d7d32010-07-12 22:24:28 +0200396 p_rx_desc->nxtdesc_p = (struct mvgbe_rxdesc *)
397 ((u32) p_rx_desc + MV_RXQ_DESC_ALIGNED_SIZE);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530398 p_rx_desc = p_rx_desc->nxtdesc_p;
399 }
400 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200401 dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530402}
403
Albert Aribaude91d7d32010-07-12 22:24:28 +0200404static int mvgbe_init(struct eth_device *dev)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530405{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200406 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
407 struct mvgbe_registers *regs = dmvgbe->regs;
Sascha Silbe0984d642013-08-11 17:08:23 +0200408#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
409 !defined(CONFIG_PHYLIB) && \
410 defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200411 int i;
Prafulla Wadaskar9841dec2009-09-09 15:59:19 +0530412#endif
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530413 /* setup RX rings */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200414 mvgbe_init_rx_desc_ring(dmvgbe);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530415
416 /* Clear the ethernet port interrupts */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200417 MVGBE_REG_WR(regs->ic, 0);
418 MVGBE_REG_WR(regs->ice, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530419 /* Unmask RX buffer and TX end interrupt */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200420 MVGBE_REG_WR(regs->pim, INT_CAUSE_UNMASK_ALL);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530421 /* Unmask phy and link status changes interrupts */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200422 MVGBE_REG_WR(regs->peim, INT_CAUSE_UNMASK_ALL_EXT);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530423
424 set_dram_access(regs);
425 port_init_mac_tables(regs);
Albert Aribaude91d7d32010-07-12 22:24:28 +0200426 port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530427
428 /* Assign port configuration and command. */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200429 MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
430 MVGBE_REG_WR(regs->pxcx, PORT_CFG_EXTEND_VALUE);
431 MVGBE_REG_WR(regs->psc0, PORT_SERIAL_CONTROL_VALUE);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530432
433 /* Assign port SDMA configuration */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200434 MVGBE_REG_WR(regs->sdc, PORT_SDMA_CFG_VALUE);
435 MVGBE_REG_WR(regs->tqx[0].qxttbc, QTKNBKT_DEF_VAL);
436 MVGBE_REG_WR(regs->tqx[0].tqxtbc,
437 (QMTBS_DEF_VAL << 16) | QTKNRT_DEF_VAL);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530438 /* Turn off the port/RXUQ bandwidth limitation */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200439 MVGBE_REG_WR(regs->pmtu, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530440
441 /* Set maximum receive buffer to 9700 bytes */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200442 MVGBE_REG_WR(regs->psc0, MVGBE_MAX_RX_PACKET_9700BYTE
443 | (MVGBE_REG_RD(regs->psc0) & MRU_MASK));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530444
Prafulla Wadaskar60ee8a22010-04-06 21:33:08 +0530445 /* Enable port initially */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200446 MVGBE_REG_BITS_SET(regs->psc0, MVGBE_SERIAL_PORT_EN);
Prafulla Wadaskar60ee8a22010-04-06 21:33:08 +0530447
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530448 /*
449 * Set ethernet MTU for leaky bucket mechanism to 0 - this will
450 * disable the leaky bucket mechanism .
451 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200452 MVGBE_REG_WR(regs->pmtu, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530453
454 /* Assignment of Rx CRDB of given RXUQ */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200455 MVGBE_REG_WR(regs->rxcdp[RXUQ], (u32) dmvgbe->p_rxdesc_curr);
Albert Aribaudcc2b8e32010-07-10 15:41:29 +0200456 /* ensure previous write is done before enabling Rx DMA */
457 isb();
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530458 /* Enable port Rx. */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200459 MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530460
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100461#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
462 !defined(CONFIG_PHYLIB) && \
463 defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200464 /* Wait up to 5s for the link status */
465 for (i = 0; i < 5; i++) {
466 u16 phyadr;
467
Albert Aribaude91d7d32010-07-12 22:24:28 +0200468 miiphy_read(dev->name, MV_PHY_ADR_REQUEST,
469 MV_PHY_ADR_REQUEST, &phyadr);
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200470 /* Return if we get link up */
471 if (miiphy_link(dev->name, phyadr))
472 return 0;
473 udelay(1000000);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530474 }
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200475
476 printf("No link on %s\n", dev->name);
477 return -1;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530478#endif
479 return 0;
480}
481
Albert Aribaude91d7d32010-07-12 22:24:28 +0200482static int mvgbe_halt(struct eth_device *dev)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530483{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200484 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
485 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530486
487 /* Disable all gigE address decoder */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200488 MVGBE_REG_WR(regs->bare, 0x3f);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530489
490 stop_queue(&regs->tqc);
491 stop_queue(&regs->rqc);
492
Prafulla Wadaskar60ee8a22010-04-06 21:33:08 +0530493 /* Disable port */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200494 MVGBE_REG_BITS_RESET(regs->psc0, MVGBE_SERIAL_PORT_EN);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530495 /* Set port is not reset */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200496 MVGBE_REG_BITS_RESET(regs->psc1, 1 << 4);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530497#ifdef CONFIG_SYS_MII_MODE
498 /* Set MMI interface up */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200499 MVGBE_REG_BITS_RESET(regs->psc1, 1 << 3);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530500#endif
501 /* Disable & mask ethernet port interrupts */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200502 MVGBE_REG_WR(regs->ic, 0);
503 MVGBE_REG_WR(regs->ice, 0);
504 MVGBE_REG_WR(regs->pim, 0);
505 MVGBE_REG_WR(regs->peim, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530506
507 return 0;
508}
509
Albert Aribaude91d7d32010-07-12 22:24:28 +0200510static int mvgbe_write_hwaddr(struct eth_device *dev)
Prafulla Wadaskar7dae2eb2010-04-06 22:21:33 +0530511{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200512 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
513 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskar7dae2eb2010-04-06 22:21:33 +0530514
515 /* Programs net device MAC address after initialization */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200516 port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
Prafulla Wadaskar7dae2eb2010-04-06 22:21:33 +0530517 return 0;
518}
519
Joe Hershbergere4e04882012-05-22 18:36:19 +0000520static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530521{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200522 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
523 struct mvgbe_registers *regs = dmvgbe->regs;
524 struct mvgbe_txdesc *p_txdesc = dmvgbe->p_txdesc;
Simon Kagstrome9220b32009-08-20 10:14:11 +0200525 void *p = (void *)dataptr;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200526 u32 cmd_sts;
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000527 u32 txuq0_reg_addr;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530528
Simon Kagstrome9220b32009-08-20 10:14:11 +0200529 /* Copy buffer if it's misaligned */
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530530 if ((u32) dataptr & 0x07) {
Simon Kagstrome9220b32009-08-20 10:14:11 +0200531 if (datasize > PKTSIZE_ALIGN) {
532 printf("Non-aligned data too large (%d)\n",
533 datasize);
534 return -1;
535 }
536
Albert Aribaude91d7d32010-07-12 22:24:28 +0200537 memcpy(dmvgbe->p_aligned_txbuf, p, datasize);
538 p = dmvgbe->p_aligned_txbuf;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530539 }
Simon Kagstrome9220b32009-08-20 10:14:11 +0200540
Albert Aribaude91d7d32010-07-12 22:24:28 +0200541 p_txdesc->cmd_sts = MVGBE_ZERO_PADDING | MVGBE_GEN_CRC;
542 p_txdesc->cmd_sts |= MVGBE_TX_FIRST_DESC | MVGBE_TX_LAST_DESC;
543 p_txdesc->cmd_sts |= MVGBE_BUFFER_OWNED_BY_DMA;
544 p_txdesc->cmd_sts |= MVGBE_TX_EN_INTERRUPT;
Simon Kagstrome9220b32009-08-20 10:14:11 +0200545 p_txdesc->buf_ptr = (u8 *) p;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530546 p_txdesc->byte_cnt = datasize;
547
Albert Aribaudcc2b8e32010-07-10 15:41:29 +0200548 /* Set this tc desc as zeroth TXUQ */
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000549 txuq0_reg_addr = (u32)&regs->tcqdp[TXUQ];
550 writel((u32) p_txdesc, txuq0_reg_addr);
Albert Aribaudcc2b8e32010-07-10 15:41:29 +0200551
552 /* ensure tx desc writes above are performed before we start Tx DMA */
553 isb();
554
555 /* Apply send command using zeroth TXUQ */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200556 MVGBE_REG_WR(regs->tqc, (1 << TXUQ));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530557
558 /*
559 * wait for packet xmit completion
560 */
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200561 cmd_sts = readl(&p_txdesc->cmd_sts);
Albert Aribaude91d7d32010-07-12 22:24:28 +0200562 while (cmd_sts & MVGBE_BUFFER_OWNED_BY_DMA) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530563 /* return fail if error is detected */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200564 if ((cmd_sts & (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME)) ==
565 (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME) &&
566 cmd_sts & (MVGBE_UR_ERROR | MVGBE_RL_ERROR)) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500567 printf("Err..(%s) in xmit packet\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530568 return -1;
569 }
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200570 cmd_sts = readl(&p_txdesc->cmd_sts);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530571 };
572 return 0;
573}
574
Albert Aribaude91d7d32010-07-12 22:24:28 +0200575static int mvgbe_recv(struct eth_device *dev)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530576{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200577 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
578 struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200579 u32 cmd_sts;
580 u32 timeout = 0;
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000581 u32 rxdesc_curr_addr;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530582
583 /* wait untill rx packet available or timeout */
584 do {
Albert Aribaude91d7d32010-07-12 22:24:28 +0200585 if (timeout < MVGBE_PHY_SMI_TIMEOUT)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530586 timeout++;
587 else {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500588 debug("%s time out...\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530589 return -1;
590 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200591 } while (readl(&p_rxdesc_curr->cmd_sts) & MVGBE_BUFFER_OWNED_BY_DMA);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530592
593 if (p_rxdesc_curr->byte_cnt != 0) {
594 debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500595 __func__, (u32) p_rxdesc_curr->byte_cnt,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530596 (u32) p_rxdesc_curr->buf_ptr,
597 (u32) p_rxdesc_curr->cmd_sts);
598 }
599
600 /*
601 * In case received a packet without first/last bits on
602 * OR the error summary bit is on,
603 * the packets needs to be dropeed.
604 */
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200605 cmd_sts = readl(&p_rxdesc_curr->cmd_sts);
606
607 if ((cmd_sts &
Albert Aribaude91d7d32010-07-12 22:24:28 +0200608 (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC))
609 != (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC)) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530610
611 printf("Err..(%s) Dropping packet spread on"
Joe Hershberger9f09a362015-04-08 01:41:06 -0500612 " multiple descriptors\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530613
Albert Aribaude91d7d32010-07-12 22:24:28 +0200614 } else if (cmd_sts & MVGBE_ERROR_SUMMARY) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530615
616 printf("Err..(%s) Dropping packet with errors\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500617 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530618
619 } else {
620 /* !!! call higher layer processing */
621 debug("%s: Sending Received packet to"
Joe Hershberger9f09a362015-04-08 01:41:06 -0500622 " upper layer (net_process_received_packet)\n",
623 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530624
625 /* let the upper layer handle the packet */
Joe Hershberger9f09a362015-04-08 01:41:06 -0500626 net_process_received_packet((p_rxdesc_curr->buf_ptr +
627 RX_BUF_OFFSET),
628 (int)(p_rxdesc_curr->byte_cnt -
629 RX_BUF_OFFSET));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530630 }
631 /*
632 * free these descriptors and point next in the ring
633 */
634 p_rxdesc_curr->cmd_sts =
Albert Aribaude91d7d32010-07-12 22:24:28 +0200635 MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530636 p_rxdesc_curr->buf_size = PKTSIZE_ALIGN;
637 p_rxdesc_curr->byte_cnt = 0;
638
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000639 rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr;
640 writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr);
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200641
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530642 return 0;
643}
644
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100645#if defined(CONFIG_PHYLIB)
646int mvgbe_phylib_init(struct eth_device *dev, int phyid)
647{
648 struct mii_dev *bus;
649 struct phy_device *phydev;
650 int ret;
651
652 bus = mdio_alloc();
653 if (!bus) {
654 printf("mdio_alloc failed\n");
655 return -ENOMEM;
656 }
Chris Packhamcee2fa32016-11-01 10:48:32 +1300657 bus->read = smi_reg_read;
658 bus->write = smi_reg_write;
Ben Whitten34fd6c92015-12-30 13:05:58 +0000659 strcpy(bus->name, dev->name);
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100660
661 ret = mdio_register(bus);
662 if (ret) {
663 printf("mdio_register failed\n");
664 free(bus);
665 return -ENOMEM;
666 }
667
668 /* Set phy address of the port */
Chris Packhamcee2fa32016-11-01 10:48:32 +1300669 smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100670
671 phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
672 if (!phydev) {
673 printf("phy_connect failed\n");
674 return -ENODEV;
675 }
676
677 phy_config(phydev);
678 phy_startup(phydev);
679
680 return 0;
681}
682#endif
683
Albert Aribaude91d7d32010-07-12 22:24:28 +0200684int mvgbe_initialize(bd_t *bis)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530685{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200686 struct mvgbe_device *dmvgbe;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530687 struct eth_device *dev;
688 int devnum;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200689 u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530690
Albert Aribaude91d7d32010-07-12 22:24:28 +0200691 for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530692 /*skip if port is configured not to use */
693 if (used_ports[devnum] == 0)
694 continue;
695
Albert Aribaude91d7d32010-07-12 22:24:28 +0200696 dmvgbe = malloc(sizeof(struct mvgbe_device));
697
698 if (!dmvgbe)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530699 goto error1;
700
Albert Aribaude91d7d32010-07-12 22:24:28 +0200701 memset(dmvgbe, 0, sizeof(struct mvgbe_device));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530702
Albert Aribaude91d7d32010-07-12 22:24:28 +0200703 dmvgbe->p_rxdesc =
704 (struct mvgbe_rxdesc *)memalign(PKTALIGN,
705 MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1);
706
707 if (!dmvgbe->p_rxdesc)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530708 goto error2;
709
Albert Aribaude91d7d32010-07-12 22:24:28 +0200710 dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN,
711 RINGSZ*PKTSIZE_ALIGN + 1);
712
713 if (!dmvgbe->p_rxbuf)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530714 goto error3;
715
Albert Aribaude91d7d32010-07-12 22:24:28 +0200716 dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
717
718 if (!dmvgbe->p_aligned_txbuf)
Simon Kagstrome9220b32009-08-20 10:14:11 +0200719 goto error4;
720
Albert Aribaude91d7d32010-07-12 22:24:28 +0200721 dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign(
722 PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
723
724 if (!dmvgbe->p_txdesc) {
725 free(dmvgbe->p_aligned_txbuf);
726error4:
727 free(dmvgbe->p_rxbuf);
728error3:
729 free(dmvgbe->p_rxdesc);
730error2:
731 free(dmvgbe);
732error1:
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530733 printf("Err.. %s Failed to allocate memory\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500734 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530735 return -1;
736 }
737
Albert Aribaude91d7d32010-07-12 22:24:28 +0200738 dev = &dmvgbe->dev;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530739
Mike Frysinger6b300dc2011-11-10 14:11:04 +0000740 /* must be less than sizeof(dev->name) */
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530741 sprintf(dev->name, "egiga%d", devnum);
742
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530743 switch (devnum) {
744 case 0:
Albert Aribaude91d7d32010-07-12 22:24:28 +0200745 dmvgbe->regs = (void *)MVGBE0_BASE;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530746 break;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200747#if defined(MVGBE1_BASE)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530748 case 1:
Albert Aribaude91d7d32010-07-12 22:24:28 +0200749 dmvgbe->regs = (void *)MVGBE1_BASE;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530750 break;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200751#endif
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530752 default: /* this should never happen */
753 printf("Err..(%s) Invalid device number %d\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500754 __func__, devnum);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530755 return -1;
756 }
757
Albert Aribaude91d7d32010-07-12 22:24:28 +0200758 dev->init = (void *)mvgbe_init;
759 dev->halt = (void *)mvgbe_halt;
760 dev->send = (void *)mvgbe_send;
761 dev->recv = (void *)mvgbe_recv;
762 dev->write_hwaddr = (void *)mvgbe_write_hwaddr;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530763
764 eth_register(dev);
765
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100766#if defined(CONFIG_PHYLIB)
767 mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
768#elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500769 int retval;
770 struct mii_dev *mdiodev = mdio_alloc();
771 if (!mdiodev)
772 return -ENOMEM;
773 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
774 mdiodev->read = smi_reg_read;
775 mdiodev->write = smi_reg_write;
776
777 retval = mdio_register(mdiodev);
778 if (retval < 0)
779 return retval;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530780 /* Set phy address of the port */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200781 miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
782 MV_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530783#endif
784 }
785 return 0;
Prafulla Wadaskar12618ef2009-07-01 20:34:51 +0200786}