blob: a1c7ea054c16d2b2cb9c0a8367ceed8cc616b529 [file] [log] [blame]
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +05301/*
2 * (C) Copyright 2009
3 * Marvell Semiconductor <www.marvell.com>
4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
5 *
6 * (C) Copyright 2003
7 * Ingo Assmus <ingo.assmus@keymile.com>
8 *
9 * based on - Driver for MV64360X ethernet ports
10 * Copyright (C) 2002 rabeeh@galileo.co.il
11 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +020012 * SPDX-License-Identifier: GPL-2.0+
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053013 */
14
15#include <common.h>
16#include <net.h>
17#include <malloc.h>
18#include <miiphy.h>
Lei Wen298ae912011-10-18 20:11:42 +053019#include <asm/io.h>
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053020#include <asm/errno.h>
21#include <asm/types.h>
Lei Wen298ae912011-10-18 20:11:42 +053022#include <asm/system.h>
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053023#include <asm/byteorder.h>
Anatolij Gustschinc8b222e2011-10-29 10:09:22 +000024#include <asm/arch/cpu.h>
Albert Aribaude91d7d32010-07-12 22:24:28 +020025
26#if defined(CONFIG_KIRKWOOD)
Stefan Roesec2437842014-10-22 12:13:06 +020027#include <asm/arch/soc.h>
Albert Aribaud8a995232010-07-12 22:24:29 +020028#elif defined(CONFIG_ORION5X)
29#include <asm/arch/orion5x.h>
Sebastian Hesselbartha533a0c2012-12-04 09:32:01 +010030#elif defined(CONFIG_DOVE)
31#include <asm/arch/dove.h>
Albert Aribaude91d7d32010-07-12 22:24:28 +020032#endif
33
Albert Aribaud0d027d92010-07-12 22:24:27 +020034#include "mvgbe.h"
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053035
Albert Aribauda7564072010-07-05 20:15:25 +020036DECLARE_GLOBAL_DATA_PTR;
37
Luka Perkov95acd992013-11-11 07:27:53 +010038#ifndef CONFIG_MVGBE_PORTS
39# define CONFIG_MVGBE_PORTS {0, 0}
40#endif
41
Albert Aribaude91d7d32010-07-12 22:24:28 +020042#define MV_PHY_ADR_REQUEST 0xee
43#define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
Simon Kagstromab9ca512009-08-20 10:12:28 +020044
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +010045#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053046/*
47 * smi_reg_read - miiphy_read callback function.
48 *
49 * Returns 16bit phy register value, or 0xffff on error
50 */
Joe Hershberger1fbcbed2016-08-08 11:28:38 -050051static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
52 int reg_ofs)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053053{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -050054 u16 data = 0;
55 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Albert Aribaude91d7d32010-07-12 22:24:28 +020056 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
57 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053058 u32 smi_reg;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +020059 u32 timeout;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053060
61 /* Phyadr read request */
Albert Aribaude91d7d32010-07-12 22:24:28 +020062 if (phy_adr == MV_PHY_ADR_REQUEST &&
63 reg_ofs == MV_PHY_ADR_REQUEST) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053064 /* */
Joe Hershberger1fbcbed2016-08-08 11:28:38 -050065 data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
66 return data;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053067 }
68 /* check parameters */
69 if (phy_adr > PHYADR_MASK) {
70 printf("Err..(%s) Invalid PHY address %d\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -050071 __func__, phy_adr);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053072 return -EFAULT;
73 }
74 if (reg_ofs > PHYREG_MASK) {
75 printf("Err..(%s) Invalid register offset %d\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -050076 __func__, reg_ofs);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053077 return -EFAULT;
78 }
79
Albert Aribaude91d7d32010-07-12 22:24:28 +020080 timeout = MVGBE_PHY_SMI_TIMEOUT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053081 /* wait till the SMI is not busy */
82 do {
83 /* read smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +020084 smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053085 if (timeout-- == 0) {
Joe Hershberger9f09a362015-04-08 01:41:06 -050086 printf("Err..(%s) SMI busy timeout\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053087 return -EFAULT;
88 }
Albert Aribaude91d7d32010-07-12 22:24:28 +020089 } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053090
91 /* fill the phy address and regiser offset and read opcode */
Albert Aribaude91d7d32010-07-12 22:24:28 +020092 smi_reg = (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
93 | (reg_ofs << MVGBE_SMI_REG_ADDR_OFFS)
94 | MVGBE_PHY_SMI_OPCODE_READ;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053095
96 /* write the smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +020097 MVGBE_REG_WR(MVGBE_SMI_REG, smi_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +053098
99 /*wait till read value is ready */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200100 timeout = MVGBE_PHY_SMI_TIMEOUT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530101
102 do {
103 /* read smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200104 smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530105 if (timeout-- == 0) {
106 printf("Err..(%s) SMI read ready timeout\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500107 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530108 return -EFAULT;
109 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200110 } while (!(smi_reg & MVGBE_PHY_SMI_READ_VALID_MASK));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530111
112 /* Wait for the data to update in the SMI register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200113 for (timeout = 0; timeout < MVGBE_PHY_SMI_TIMEOUT; timeout++)
114 ;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530115
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500116 data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530117
Joe Hershberger9f09a362015-04-08 01:41:06 -0500118 debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500119 data);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530120
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500121 return data;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530122}
123
124/*
125 * smi_reg_write - imiiphy_write callback function.
126 *
127 * Returns 0 if write succeed, -EINVAL on bad parameters
128 * -ETIME on timeout
129 */
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500130static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
131 int reg_ofs, u16 data)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530132{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500133 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Albert Aribaude91d7d32010-07-12 22:24:28 +0200134 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
135 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530136 u32 smi_reg;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200137 u32 timeout;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530138
139 /* Phyadr write request*/
Albert Aribaude91d7d32010-07-12 22:24:28 +0200140 if (phy_adr == MV_PHY_ADR_REQUEST &&
141 reg_ofs == MV_PHY_ADR_REQUEST) {
142 MVGBE_REG_WR(regs->phyadr, data);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530143 return 0;
144 }
145
146 /* check parameters */
147 if (phy_adr > PHYADR_MASK) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500148 printf("Err..(%s) Invalid phy address\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530149 return -EINVAL;
150 }
151 if (reg_ofs > PHYREG_MASK) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500152 printf("Err..(%s) Invalid register offset\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530153 return -EINVAL;
154 }
155
156 /* wait till the SMI is not busy */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200157 timeout = MVGBE_PHY_SMI_TIMEOUT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530158 do {
159 /* read smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200160 smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530161 if (timeout-- == 0) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500162 printf("Err..(%s) SMI busy timeout\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530163 return -ETIME;
164 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200165 } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530166
167 /* fill the phy addr and reg offset and write opcode and data */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200168 smi_reg = (data << MVGBE_PHY_SMI_DATA_OFFS);
169 smi_reg |= (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
170 | (reg_ofs << MVGBE_SMI_REG_ADDR_OFFS);
171 smi_reg &= ~MVGBE_PHY_SMI_OPCODE_READ;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530172
173 /* write the smi register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200174 MVGBE_REG_WR(MVGBE_SMI_REG, smi_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530175
176 return 0;
177}
Stefan Bigler96455292012-03-26 00:02:13 +0000178#endif
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530179
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100180#if defined(CONFIG_PHYLIB)
181int mvgbe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
182 int reg_addr)
183{
184 u16 data;
185 int ret;
186 ret = smi_reg_read(bus->name, phy_addr, reg_addr, &data);
187 if (ret)
188 return ret;
189 return data;
190}
191
192int mvgbe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
193 int reg_addr, u16 data)
194{
195 return smi_reg_write(bus->name, phy_addr, reg_addr, data);
196}
197#endif
198
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530199/* Stop and checks all queues */
200static void stop_queue(u32 * qreg)
201{
202 u32 reg_data;
203
204 reg_data = readl(qreg);
205
206 if (reg_data & 0xFF) {
207 /* Issue stop command for active channels only */
208 writel((reg_data << 8), qreg);
209
210 /* Wait for all queue activity to terminate. */
211 do {
212 /*
213 * Check port cause register that all queues
214 * are stopped
215 */
216 reg_data = readl(qreg);
217 }
218 while (reg_data & 0xFF);
219 }
220}
221
222/*
223 * set_access_control - Config address decode parameters for Ethernet unit
224 *
225 * This function configures the address decode parameters for the Gigabit
226 * Ethernet Controller according the given parameters struct.
227 *
228 * @regs Register struct pointer.
229 * @param Address decode parameter struct.
230 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200231static void set_access_control(struct mvgbe_registers *regs,
232 struct mvgbe_winparam *param)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530233{
234 u32 access_prot_reg;
235
236 /* Set access control register */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200237 access_prot_reg = MVGBE_REG_RD(regs->epap);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530238 /* clear window permission */
239 access_prot_reg &= (~(3 << (param->win * 2)));
240 access_prot_reg |= (param->access_ctrl << (param->win * 2));
Albert Aribaude91d7d32010-07-12 22:24:28 +0200241 MVGBE_REG_WR(regs->epap, access_prot_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530242
243 /* Set window Size reg (SR) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200244 MVGBE_REG_WR(regs->barsz[param->win].size,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530245 (((param->size / 0x10000) - 1) << 16));
246
247 /* Set window Base address reg (BA) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200248 MVGBE_REG_WR(regs->barsz[param->win].bar,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530249 (param->target | param->attrib | param->base_addr));
250 /* High address remap reg (HARR) */
251 if (param->win < 4)
Albert Aribaude91d7d32010-07-12 22:24:28 +0200252 MVGBE_REG_WR(regs->ha_remap[param->win], param->high_addr);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530253
254 /* Base address enable reg (BARER) */
255 if (param->enable == 1)
Albert Aribaude91d7d32010-07-12 22:24:28 +0200256 MVGBE_REG_BITS_RESET(regs->bare, (1 << param->win));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530257 else
Albert Aribaude91d7d32010-07-12 22:24:28 +0200258 MVGBE_REG_BITS_SET(regs->bare, (1 << param->win));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530259}
260
Albert Aribaude91d7d32010-07-12 22:24:28 +0200261static void set_dram_access(struct mvgbe_registers *regs)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530262{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200263 struct mvgbe_winparam win_param;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530264 int i;
265
266 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
267 /* Set access parameters for DRAM bank i */
268 win_param.win = i; /* Use Ethernet window i */
269 /* Window target - DDR */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200270 win_param.target = MVGBE_TARGET_DRAM;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530271 /* Enable full access */
272 win_param.access_ctrl = EWIN_ACCESS_FULL;
273 win_param.high_addr = 0;
Albert Aribauda7564072010-07-05 20:15:25 +0200274 /* Get bank base and size */
275 win_param.base_addr = gd->bd->bi_dram[i].start;
276 win_param.size = gd->bd->bi_dram[i].size;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530277 if (win_param.size == 0)
278 win_param.enable = 0;
279 else
280 win_param.enable = 1; /* Enable the access */
281
282 /* Enable DRAM bank */
283 switch (i) {
284 case 0:
285 win_param.attrib = EBAR_DRAM_CS0;
286 break;
287 case 1:
288 win_param.attrib = EBAR_DRAM_CS1;
289 break;
290 case 2:
291 win_param.attrib = EBAR_DRAM_CS2;
292 break;
293 case 3:
294 win_param.attrib = EBAR_DRAM_CS3;
295 break;
296 default:
Albert Aribauda7564072010-07-05 20:15:25 +0200297 /* invalid bank, disable access */
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530298 win_param.enable = 0;
299 win_param.attrib = 0;
300 break;
301 }
302 /* Set the access control for address window(EPAPR) RD/WR */
303 set_access_control(regs, &win_param);
304 }
305}
306
307/*
308 * port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
309 *
310 * Go through all the DA filter tables (Unicast, Special Multicast & Other
311 * Multicast) and set each entry to 0.
312 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200313static void port_init_mac_tables(struct mvgbe_registers *regs)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530314{
315 int table_index;
316
317 /* Clear DA filter unicast table (Ex_dFUT) */
318 for (table_index = 0; table_index < 4; ++table_index)
Albert Aribaude91d7d32010-07-12 22:24:28 +0200319 MVGBE_REG_WR(regs->dfut[table_index], 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530320
321 for (table_index = 0; table_index < 64; ++table_index) {
322 /* Clear DA filter special multicast table (Ex_dFSMT) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200323 MVGBE_REG_WR(regs->dfsmt[table_index], 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530324 /* Clear DA filter other multicast table (Ex_dFOMT) */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200325 MVGBE_REG_WR(regs->dfomt[table_index], 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530326 }
327}
328
329/*
330 * port_uc_addr - This function Set the port unicast address table
331 *
332 * This function locates the proper entry in the Unicast table for the
333 * specified MAC nibble and sets its properties according to function
334 * parameters.
335 * This function add/removes MAC addresses from the port unicast address
336 * table.
337 *
338 * @uc_nibble Unicast MAC Address last nibble.
339 * @option 0 = Add, 1 = remove address.
340 *
341 * RETURN: 1 if output succeeded. 0 if option parameter is invalid.
342 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200343static int port_uc_addr(struct mvgbe_registers *regs, u8 uc_nibble,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530344 int option)
345{
346 u32 unicast_reg;
347 u32 tbl_offset;
348 u32 reg_offset;
349
350 /* Locate the Unicast table entry */
351 uc_nibble = (0xf & uc_nibble);
352 /* Register offset from unicast table base */
353 tbl_offset = (uc_nibble / 4);
354 /* Entry offset within the above register */
355 reg_offset = uc_nibble % 4;
356
357 switch (option) {
358 case REJECT_MAC_ADDR:
359 /*
360 * Clear accepts frame bit at specified unicast
361 * DA table entry
362 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200363 unicast_reg = MVGBE_REG_RD(regs->dfut[tbl_offset]);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530364 unicast_reg &= (0xFF << (8 * reg_offset));
Albert Aribaude91d7d32010-07-12 22:24:28 +0200365 MVGBE_REG_WR(regs->dfut[tbl_offset], unicast_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530366 break;
367 case ACCEPT_MAC_ADDR:
368 /* Set accepts frame bit at unicast DA filter table entry */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200369 unicast_reg = MVGBE_REG_RD(regs->dfut[tbl_offset]);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530370 unicast_reg &= (0xFF << (8 * reg_offset));
371 unicast_reg |= ((0x01 | (RXUQ << 1)) << (8 * reg_offset));
Albert Aribaude91d7d32010-07-12 22:24:28 +0200372 MVGBE_REG_WR(regs->dfut[tbl_offset], unicast_reg);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530373 break;
374 default:
375 return 0;
376 }
377 return 1;
378}
379
380/*
381 * port_uc_addr_set - This function Set the port Unicast address.
382 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200383static void port_uc_addr_set(struct mvgbe_registers *regs, u8 * p_addr)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530384{
385 u32 mac_h;
386 u32 mac_l;
387
388 mac_l = (p_addr[4] << 8) | (p_addr[5]);
389 mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
390 (p_addr[3] << 0);
391
Albert Aribaude91d7d32010-07-12 22:24:28 +0200392 MVGBE_REG_WR(regs->macal, mac_l);
393 MVGBE_REG_WR(regs->macah, mac_h);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530394
395 /* Accept frames of this address */
396 port_uc_addr(regs, p_addr[5], ACCEPT_MAC_ADDR);
397}
398
399/*
Albert Aribaude91d7d32010-07-12 22:24:28 +0200400 * mvgbe_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530401 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200402static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530403{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200404 struct mvgbe_rxdesc *p_rx_desc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530405 int i;
406
407 /* initialize the Rx descriptors ring */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200408 p_rx_desc = dmvgbe->p_rxdesc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530409 for (i = 0; i < RINGSZ; i++) {
410 p_rx_desc->cmd_sts =
Albert Aribaude91d7d32010-07-12 22:24:28 +0200411 MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530412 p_rx_desc->buf_size = PKTSIZE_ALIGN;
413 p_rx_desc->byte_cnt = 0;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200414 p_rx_desc->buf_ptr = dmvgbe->p_rxbuf + i * PKTSIZE_ALIGN;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530415 if (i == (RINGSZ - 1))
Albert Aribaude91d7d32010-07-12 22:24:28 +0200416 p_rx_desc->nxtdesc_p = dmvgbe->p_rxdesc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530417 else {
Albert Aribaude91d7d32010-07-12 22:24:28 +0200418 p_rx_desc->nxtdesc_p = (struct mvgbe_rxdesc *)
419 ((u32) p_rx_desc + MV_RXQ_DESC_ALIGNED_SIZE);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530420 p_rx_desc = p_rx_desc->nxtdesc_p;
421 }
422 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200423 dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530424}
425
Albert Aribaude91d7d32010-07-12 22:24:28 +0200426static int mvgbe_init(struct eth_device *dev)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530427{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200428 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
429 struct mvgbe_registers *regs = dmvgbe->regs;
Sascha Silbe0984d642013-08-11 17:08:23 +0200430#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
431 !defined(CONFIG_PHYLIB) && \
432 defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200433 int i;
Prafulla Wadaskar9841dec2009-09-09 15:59:19 +0530434#endif
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530435 /* setup RX rings */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200436 mvgbe_init_rx_desc_ring(dmvgbe);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530437
438 /* Clear the ethernet port interrupts */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200439 MVGBE_REG_WR(regs->ic, 0);
440 MVGBE_REG_WR(regs->ice, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530441 /* Unmask RX buffer and TX end interrupt */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200442 MVGBE_REG_WR(regs->pim, INT_CAUSE_UNMASK_ALL);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530443 /* Unmask phy and link status changes interrupts */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200444 MVGBE_REG_WR(regs->peim, INT_CAUSE_UNMASK_ALL_EXT);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530445
446 set_dram_access(regs);
447 port_init_mac_tables(regs);
Albert Aribaude91d7d32010-07-12 22:24:28 +0200448 port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530449
450 /* Assign port configuration and command. */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200451 MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
452 MVGBE_REG_WR(regs->pxcx, PORT_CFG_EXTEND_VALUE);
453 MVGBE_REG_WR(regs->psc0, PORT_SERIAL_CONTROL_VALUE);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530454
455 /* Assign port SDMA configuration */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200456 MVGBE_REG_WR(regs->sdc, PORT_SDMA_CFG_VALUE);
457 MVGBE_REG_WR(regs->tqx[0].qxttbc, QTKNBKT_DEF_VAL);
458 MVGBE_REG_WR(regs->tqx[0].tqxtbc,
459 (QMTBS_DEF_VAL << 16) | QTKNRT_DEF_VAL);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530460 /* Turn off the port/RXUQ bandwidth limitation */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200461 MVGBE_REG_WR(regs->pmtu, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530462
463 /* Set maximum receive buffer to 9700 bytes */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200464 MVGBE_REG_WR(regs->psc0, MVGBE_MAX_RX_PACKET_9700BYTE
465 | (MVGBE_REG_RD(regs->psc0) & MRU_MASK));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530466
Prafulla Wadaskar60ee8a22010-04-06 21:33:08 +0530467 /* Enable port initially */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200468 MVGBE_REG_BITS_SET(regs->psc0, MVGBE_SERIAL_PORT_EN);
Prafulla Wadaskar60ee8a22010-04-06 21:33:08 +0530469
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530470 /*
471 * Set ethernet MTU for leaky bucket mechanism to 0 - this will
472 * disable the leaky bucket mechanism .
473 */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200474 MVGBE_REG_WR(regs->pmtu, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530475
476 /* Assignment of Rx CRDB of given RXUQ */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200477 MVGBE_REG_WR(regs->rxcdp[RXUQ], (u32) dmvgbe->p_rxdesc_curr);
Albert Aribaudcc2b8e32010-07-10 15:41:29 +0200478 /* ensure previous write is done before enabling Rx DMA */
479 isb();
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530480 /* Enable port Rx. */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200481 MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530482
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100483#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
484 !defined(CONFIG_PHYLIB) && \
485 defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200486 /* Wait up to 5s for the link status */
487 for (i = 0; i < 5; i++) {
488 u16 phyadr;
489
Albert Aribaude91d7d32010-07-12 22:24:28 +0200490 miiphy_read(dev->name, MV_PHY_ADR_REQUEST,
491 MV_PHY_ADR_REQUEST, &phyadr);
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200492 /* Return if we get link up */
493 if (miiphy_link(dev->name, phyadr))
494 return 0;
495 udelay(1000000);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530496 }
Simon Kagstrom15cc5a62009-08-20 10:13:06 +0200497
498 printf("No link on %s\n", dev->name);
499 return -1;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530500#endif
501 return 0;
502}
503
Albert Aribaude91d7d32010-07-12 22:24:28 +0200504static int mvgbe_halt(struct eth_device *dev)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530505{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200506 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
507 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530508
509 /* Disable all gigE address decoder */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200510 MVGBE_REG_WR(regs->bare, 0x3f);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530511
512 stop_queue(&regs->tqc);
513 stop_queue(&regs->rqc);
514
Prafulla Wadaskar60ee8a22010-04-06 21:33:08 +0530515 /* Disable port */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200516 MVGBE_REG_BITS_RESET(regs->psc0, MVGBE_SERIAL_PORT_EN);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530517 /* Set port is not reset */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200518 MVGBE_REG_BITS_RESET(regs->psc1, 1 << 4);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530519#ifdef CONFIG_SYS_MII_MODE
520 /* Set MMI interface up */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200521 MVGBE_REG_BITS_RESET(regs->psc1, 1 << 3);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530522#endif
523 /* Disable & mask ethernet port interrupts */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200524 MVGBE_REG_WR(regs->ic, 0);
525 MVGBE_REG_WR(regs->ice, 0);
526 MVGBE_REG_WR(regs->pim, 0);
527 MVGBE_REG_WR(regs->peim, 0);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530528
529 return 0;
530}
531
Albert Aribaude91d7d32010-07-12 22:24:28 +0200532static int mvgbe_write_hwaddr(struct eth_device *dev)
Prafulla Wadaskar7dae2eb2010-04-06 22:21:33 +0530533{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200534 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
535 struct mvgbe_registers *regs = dmvgbe->regs;
Prafulla Wadaskar7dae2eb2010-04-06 22:21:33 +0530536
537 /* Programs net device MAC address after initialization */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200538 port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
Prafulla Wadaskar7dae2eb2010-04-06 22:21:33 +0530539 return 0;
540}
541
Joe Hershbergere4e04882012-05-22 18:36:19 +0000542static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530543{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200544 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
545 struct mvgbe_registers *regs = dmvgbe->regs;
546 struct mvgbe_txdesc *p_txdesc = dmvgbe->p_txdesc;
Simon Kagstrome9220b32009-08-20 10:14:11 +0200547 void *p = (void *)dataptr;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200548 u32 cmd_sts;
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000549 u32 txuq0_reg_addr;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530550
Simon Kagstrome9220b32009-08-20 10:14:11 +0200551 /* Copy buffer if it's misaligned */
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530552 if ((u32) dataptr & 0x07) {
Simon Kagstrome9220b32009-08-20 10:14:11 +0200553 if (datasize > PKTSIZE_ALIGN) {
554 printf("Non-aligned data too large (%d)\n",
555 datasize);
556 return -1;
557 }
558
Albert Aribaude91d7d32010-07-12 22:24:28 +0200559 memcpy(dmvgbe->p_aligned_txbuf, p, datasize);
560 p = dmvgbe->p_aligned_txbuf;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530561 }
Simon Kagstrome9220b32009-08-20 10:14:11 +0200562
Albert Aribaude91d7d32010-07-12 22:24:28 +0200563 p_txdesc->cmd_sts = MVGBE_ZERO_PADDING | MVGBE_GEN_CRC;
564 p_txdesc->cmd_sts |= MVGBE_TX_FIRST_DESC | MVGBE_TX_LAST_DESC;
565 p_txdesc->cmd_sts |= MVGBE_BUFFER_OWNED_BY_DMA;
566 p_txdesc->cmd_sts |= MVGBE_TX_EN_INTERRUPT;
Simon Kagstrome9220b32009-08-20 10:14:11 +0200567 p_txdesc->buf_ptr = (u8 *) p;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530568 p_txdesc->byte_cnt = datasize;
569
Albert Aribaudcc2b8e32010-07-10 15:41:29 +0200570 /* Set this tc desc as zeroth TXUQ */
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000571 txuq0_reg_addr = (u32)&regs->tcqdp[TXUQ];
572 writel((u32) p_txdesc, txuq0_reg_addr);
Albert Aribaudcc2b8e32010-07-10 15:41:29 +0200573
574 /* ensure tx desc writes above are performed before we start Tx DMA */
575 isb();
576
577 /* Apply send command using zeroth TXUQ */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200578 MVGBE_REG_WR(regs->tqc, (1 << TXUQ));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530579
580 /*
581 * wait for packet xmit completion
582 */
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200583 cmd_sts = readl(&p_txdesc->cmd_sts);
Albert Aribaude91d7d32010-07-12 22:24:28 +0200584 while (cmd_sts & MVGBE_BUFFER_OWNED_BY_DMA) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530585 /* return fail if error is detected */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200586 if ((cmd_sts & (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME)) ==
587 (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME) &&
588 cmd_sts & (MVGBE_UR_ERROR | MVGBE_RL_ERROR)) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500589 printf("Err..(%s) in xmit packet\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530590 return -1;
591 }
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200592 cmd_sts = readl(&p_txdesc->cmd_sts);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530593 };
594 return 0;
595}
596
Albert Aribaude91d7d32010-07-12 22:24:28 +0200597static int mvgbe_recv(struct eth_device *dev)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530598{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200599 struct mvgbe_device *dmvgbe = to_mvgbe(dev);
600 struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr;
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200601 u32 cmd_sts;
602 u32 timeout = 0;
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000603 u32 rxdesc_curr_addr;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530604
605 /* wait untill rx packet available or timeout */
606 do {
Albert Aribaude91d7d32010-07-12 22:24:28 +0200607 if (timeout < MVGBE_PHY_SMI_TIMEOUT)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530608 timeout++;
609 else {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500610 debug("%s time out...\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530611 return -1;
612 }
Albert Aribaude91d7d32010-07-12 22:24:28 +0200613 } while (readl(&p_rxdesc_curr->cmd_sts) & MVGBE_BUFFER_OWNED_BY_DMA);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530614
615 if (p_rxdesc_curr->byte_cnt != 0) {
616 debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500617 __func__, (u32) p_rxdesc_curr->byte_cnt,
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530618 (u32) p_rxdesc_curr->buf_ptr,
619 (u32) p_rxdesc_curr->cmd_sts);
620 }
621
622 /*
623 * In case received a packet without first/last bits on
624 * OR the error summary bit is on,
625 * the packets needs to be dropeed.
626 */
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200627 cmd_sts = readl(&p_rxdesc_curr->cmd_sts);
628
629 if ((cmd_sts &
Albert Aribaude91d7d32010-07-12 22:24:28 +0200630 (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC))
631 != (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC)) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530632
633 printf("Err..(%s) Dropping packet spread on"
Joe Hershberger9f09a362015-04-08 01:41:06 -0500634 " multiple descriptors\n", __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530635
Albert Aribaude91d7d32010-07-12 22:24:28 +0200636 } else if (cmd_sts & MVGBE_ERROR_SUMMARY) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530637
638 printf("Err..(%s) Dropping packet with errors\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500639 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530640
641 } else {
642 /* !!! call higher layer processing */
643 debug("%s: Sending Received packet to"
Joe Hershberger9f09a362015-04-08 01:41:06 -0500644 " upper layer (net_process_received_packet)\n",
645 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530646
647 /* let the upper layer handle the packet */
Joe Hershberger9f09a362015-04-08 01:41:06 -0500648 net_process_received_packet((p_rxdesc_curr->buf_ptr +
649 RX_BUF_OFFSET),
650 (int)(p_rxdesc_curr->byte_cnt -
651 RX_BUF_OFFSET));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530652 }
653 /*
654 * free these descriptors and point next in the ring
655 */
656 p_rxdesc_curr->cmd_sts =
Albert Aribaude91d7d32010-07-12 22:24:28 +0200657 MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530658 p_rxdesc_curr->buf_size = PKTSIZE_ALIGN;
659 p_rxdesc_curr->byte_cnt = 0;
660
Anatolij Gustschinda42f242011-11-19 08:59:36 +0000661 rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr;
662 writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr);
Simon Kagstrom4d0941c2009-07-08 13:03:18 +0200663
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530664 return 0;
665}
666
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100667#if defined(CONFIG_PHYLIB)
668int mvgbe_phylib_init(struct eth_device *dev, int phyid)
669{
670 struct mii_dev *bus;
671 struct phy_device *phydev;
672 int ret;
673
674 bus = mdio_alloc();
675 if (!bus) {
676 printf("mdio_alloc failed\n");
677 return -ENOMEM;
678 }
679 bus->read = mvgbe_phy_read;
680 bus->write = mvgbe_phy_write;
Ben Whitten34fd6c92015-12-30 13:05:58 +0000681 strcpy(bus->name, dev->name);
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100682
683 ret = mdio_register(bus);
684 if (ret) {
685 printf("mdio_register failed\n");
686 free(bus);
687 return -ENOMEM;
688 }
689
690 /* Set phy address of the port */
691 mvgbe_phy_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
692
693 phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
694 if (!phydev) {
695 printf("phy_connect failed\n");
696 return -ENODEV;
697 }
698
699 phy_config(phydev);
700 phy_startup(phydev);
701
702 return 0;
703}
704#endif
705
Albert Aribaude91d7d32010-07-12 22:24:28 +0200706int mvgbe_initialize(bd_t *bis)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530707{
Albert Aribaude91d7d32010-07-12 22:24:28 +0200708 struct mvgbe_device *dmvgbe;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530709 struct eth_device *dev;
710 int devnum;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200711 u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530712
Albert Aribaude91d7d32010-07-12 22:24:28 +0200713 for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530714 /*skip if port is configured not to use */
715 if (used_ports[devnum] == 0)
716 continue;
717
Albert Aribaude91d7d32010-07-12 22:24:28 +0200718 dmvgbe = malloc(sizeof(struct mvgbe_device));
719
720 if (!dmvgbe)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530721 goto error1;
722
Albert Aribaude91d7d32010-07-12 22:24:28 +0200723 memset(dmvgbe, 0, sizeof(struct mvgbe_device));
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530724
Albert Aribaude91d7d32010-07-12 22:24:28 +0200725 dmvgbe->p_rxdesc =
726 (struct mvgbe_rxdesc *)memalign(PKTALIGN,
727 MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1);
728
729 if (!dmvgbe->p_rxdesc)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530730 goto error2;
731
Albert Aribaude91d7d32010-07-12 22:24:28 +0200732 dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN,
733 RINGSZ*PKTSIZE_ALIGN + 1);
734
735 if (!dmvgbe->p_rxbuf)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530736 goto error3;
737
Albert Aribaude91d7d32010-07-12 22:24:28 +0200738 dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
739
740 if (!dmvgbe->p_aligned_txbuf)
Simon Kagstrome9220b32009-08-20 10:14:11 +0200741 goto error4;
742
Albert Aribaude91d7d32010-07-12 22:24:28 +0200743 dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign(
744 PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
745
746 if (!dmvgbe->p_txdesc) {
747 free(dmvgbe->p_aligned_txbuf);
748error4:
749 free(dmvgbe->p_rxbuf);
750error3:
751 free(dmvgbe->p_rxdesc);
752error2:
753 free(dmvgbe);
754error1:
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530755 printf("Err.. %s Failed to allocate memory\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500756 __func__);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530757 return -1;
758 }
759
Albert Aribaude91d7d32010-07-12 22:24:28 +0200760 dev = &dmvgbe->dev;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530761
Mike Frysinger6b300dc2011-11-10 14:11:04 +0000762 /* must be less than sizeof(dev->name) */
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530763 sprintf(dev->name, "egiga%d", devnum);
764
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530765 switch (devnum) {
766 case 0:
Albert Aribaude91d7d32010-07-12 22:24:28 +0200767 dmvgbe->regs = (void *)MVGBE0_BASE;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530768 break;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200769#if defined(MVGBE1_BASE)
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530770 case 1:
Albert Aribaude91d7d32010-07-12 22:24:28 +0200771 dmvgbe->regs = (void *)MVGBE1_BASE;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530772 break;
Albert Aribaude91d7d32010-07-12 22:24:28 +0200773#endif
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530774 default: /* this should never happen */
775 printf("Err..(%s) Invalid device number %d\n",
Joe Hershberger9f09a362015-04-08 01:41:06 -0500776 __func__, devnum);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530777 return -1;
778 }
779
Albert Aribaude91d7d32010-07-12 22:24:28 +0200780 dev->init = (void *)mvgbe_init;
781 dev->halt = (void *)mvgbe_halt;
782 dev->send = (void *)mvgbe_send;
783 dev->recv = (void *)mvgbe_recv;
784 dev->write_hwaddr = (void *)mvgbe_write_hwaddr;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530785
786 eth_register(dev);
787
Sebastian Hesselbarth94a483c2012-12-04 09:32:00 +0100788#if defined(CONFIG_PHYLIB)
789 mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
790#elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500791 int retval;
792 struct mii_dev *mdiodev = mdio_alloc();
793 if (!mdiodev)
794 return -ENOMEM;
795 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
796 mdiodev->read = smi_reg_read;
797 mdiodev->write = smi_reg_write;
798
799 retval = mdio_register(mdiodev);
800 if (retval < 0)
801 return retval;
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530802 /* Set phy address of the port */
Albert Aribaude91d7d32010-07-12 22:24:28 +0200803 miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
804 MV_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum);
Prafulla Wadaskarb7a280d2009-06-14 22:33:46 +0530805#endif
806 }
807 return 0;
Prafulla Wadaskar12618ef2009-07-01 20:34:51 +0200808}