xref: /OK3568_Linux_fs/u-boot/drivers/net/xilinx_ll_temac.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Xilinx xps_ll_temac ethernet driver for u-boot
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * supports SDMA or FIFO access and MDIO bus communication
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2011 - 2012 Stephan Linz <linz@li-pro.net>
7*4882a593Smuzhiyun  * Copyright (C) 2008 - 2011 Michal Simek <monstr@monstr.eu>
8*4882a593Smuzhiyun  * Copyright (C) 2008 - 2011 PetaLogix
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Based on Yoshio Kashiwagi kashiwagi@co-nss.co.jp driver
11*4882a593Smuzhiyun  * Copyright (C) 2008 Nissin Systems Co.,Ltd.
12*4882a593Smuzhiyun  * March 2008 created
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * [0]: http://www.xilinx.com/support/documentation
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
19*4882a593Smuzhiyun  * [A]:	[0]/application_notes/xapp1041.pdf
20*4882a593Smuzhiyun  */
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include <config.h>
23*4882a593Smuzhiyun #include <common.h>
24*4882a593Smuzhiyun #include <net.h>
25*4882a593Smuzhiyun #include <netdev.h>
26*4882a593Smuzhiyun #include <malloc.h>
27*4882a593Smuzhiyun #include <asm/io.h>
28*4882a593Smuzhiyun #include <miiphy.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include "xilinx_ll_temac.h"
31*4882a593Smuzhiyun #include "xilinx_ll_temac_fifo.h"
32*4882a593Smuzhiyun #include "xilinx_ll_temac_sdma.h"
33*4882a593Smuzhiyun #include "xilinx_ll_temac_mdio.h"
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #if !defined(CONFIG_MII)
36*4882a593Smuzhiyun # error "LL_TEMAC requires MII -- missing CONFIG_MII"
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #if !defined(CONFIG_PHYLIB)
40*4882a593Smuzhiyun # error "LL_TEMAC requires PHYLIB -- missing CONFIG_PHYLIB"
41*4882a593Smuzhiyun #endif
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun struct ll_temac_info {
44*4882a593Smuzhiyun 	int			flags;
45*4882a593Smuzhiyun 	unsigned long		base_addr;
46*4882a593Smuzhiyun 	unsigned long		ctrl_addr;
47*4882a593Smuzhiyun 	char			*devname;
48*4882a593Smuzhiyun 	unsigned int		phyaddr;
49*4882a593Smuzhiyun 	char			*mdio_busname;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun /* Ethernet interface ready status */
ll_temac_check_status(struct temac_reg * regs,u32 mask)53*4882a593Smuzhiyun int ll_temac_check_status(struct temac_reg *regs, u32 mask)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	unsigned timeout = 50;	/* 1usec * 50 = 50usec */
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	/*
58*4882a593Smuzhiyun 	 * Quote from LL TEMAC documentation: The bits in the RDY
59*4882a593Smuzhiyun 	 * register are asserted when there is no access in progress.
60*4882a593Smuzhiyun 	 * When an access is in progress, a bit corresponding to the
61*4882a593Smuzhiyun 	 * type of access is automatically de-asserted. The bit is
62*4882a593Smuzhiyun 	 * automatically re-asserted when the access is complete.
63*4882a593Smuzhiyun 	 */
64*4882a593Smuzhiyun 	while (timeout && (!(in_be32(&regs->rdy) & mask))) {
65*4882a593Smuzhiyun 		timeout--;
66*4882a593Smuzhiyun 		udelay(1);
67*4882a593Smuzhiyun 	}
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	if (!timeout) {
70*4882a593Smuzhiyun 		printf("%s: Timeout on 0x%08x @%p\n", __func__,
71*4882a593Smuzhiyun 				mask, &regs->rdy);
72*4882a593Smuzhiyun 		return 1;
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	return 0;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun  * Indirect write to ll_temac.
80*4882a593Smuzhiyun  *
81*4882a593Smuzhiyun  * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
82*4882a593Smuzhiyun  * page 23, second paragraph, The use of CTL0 register or CTL1 register
83*4882a593Smuzhiyun  */
ll_temac_indirect_set(struct temac_reg * regs,u16 regn,u32 reg_data)84*4882a593Smuzhiyun int ll_temac_indirect_set(struct temac_reg *regs, u16 regn, u32 reg_data)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	out_be32(&regs->lsw, (reg_data & MLSW_MASK));
87*4882a593Smuzhiyun 	out_be32(&regs->ctl, CTL_WEN | (regn & CTL_ADDR_MASK));
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	if (ll_temac_check_status(regs, RSE_CFG_WR))
90*4882a593Smuzhiyun 		return 0;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	return 1;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun  * Indirect read from ll_temac.
97*4882a593Smuzhiyun  *
98*4882a593Smuzhiyun  * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
99*4882a593Smuzhiyun  * page 23, second paragraph, The use of CTL0 register or CTL1 register
100*4882a593Smuzhiyun  */
ll_temac_indirect_get(struct temac_reg * regs,u16 regn,u32 * reg_data)101*4882a593Smuzhiyun int ll_temac_indirect_get(struct temac_reg *regs, u16 regn, u32* reg_data)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	out_be32(&regs->ctl, (regn & CTL_ADDR_MASK));
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	if (ll_temac_check_status(regs, RSE_CFG_RR))
106*4882a593Smuzhiyun 		return 0;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	*reg_data = in_be32(&regs->lsw) & MLSW_MASK;
109*4882a593Smuzhiyun 	return 1;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun /* setting sub-controller and ll_temac to proper setting */
ll_temac_setup_ctrl(struct eth_device * dev)113*4882a593Smuzhiyun static int ll_temac_setup_ctrl(struct eth_device *dev)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	struct ll_temac *ll_temac = dev->priv;
116*4882a593Smuzhiyun 	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	if (ll_temac->ctrlreset && ll_temac->ctrlreset(dev))
119*4882a593Smuzhiyun 		return 0;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (ll_temac->ctrlinit && ll_temac->ctrlinit(dev))
122*4882a593Smuzhiyun 		return 0;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* Promiscuous mode disable */
125*4882a593Smuzhiyun 	if (!ll_temac_indirect_set(regs, TEMAC_AFM, 0))
126*4882a593Smuzhiyun 		return 0;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	/* Enable Receiver - RX bit */
129*4882a593Smuzhiyun 	if (!ll_temac_indirect_set(regs, TEMAC_RCW1, RCW1_RX))
130*4882a593Smuzhiyun 		return 0;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	/* Enable Transmitter - TX bit */
133*4882a593Smuzhiyun 	if (!ll_temac_indirect_set(regs, TEMAC_TC, TC_TX))
134*4882a593Smuzhiyun 		return 0;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	return 1;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun /*
140*4882a593Smuzhiyun  * Configure ll_temac based on negotiated speed and duplex
141*4882a593Smuzhiyun  * reported by PHY handling code
142*4882a593Smuzhiyun  */
ll_temac_adjust_link(struct eth_device * dev)143*4882a593Smuzhiyun static int ll_temac_adjust_link(struct eth_device *dev)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	unsigned int speed, emmc_reg;
146*4882a593Smuzhiyun 	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
147*4882a593Smuzhiyun 	struct ll_temac *ll_temac = dev->priv;
148*4882a593Smuzhiyun 	struct phy_device *phydev = ll_temac->phydev;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	if (!phydev->link) {
151*4882a593Smuzhiyun 		printf("%s: No link.\n", phydev->dev->name);
152*4882a593Smuzhiyun 		return 0;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	switch (phydev->speed) {
156*4882a593Smuzhiyun 	case 1000:
157*4882a593Smuzhiyun 		speed = EMMC_LSPD_1000;
158*4882a593Smuzhiyun 		break;
159*4882a593Smuzhiyun 	case 100:
160*4882a593Smuzhiyun 		speed = EMMC_LSPD_100;
161*4882a593Smuzhiyun 		break;
162*4882a593Smuzhiyun 	case 10:
163*4882a593Smuzhiyun 		speed = EMMC_LSPD_10;
164*4882a593Smuzhiyun 		break;
165*4882a593Smuzhiyun 	default:
166*4882a593Smuzhiyun 		return 0;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	if (!ll_temac_indirect_get(regs, TEMAC_EMMC, &emmc_reg))
170*4882a593Smuzhiyun 		return 0;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	emmc_reg &= ~EMMC_LSPD_MASK;
173*4882a593Smuzhiyun 	emmc_reg |= speed;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (!ll_temac_indirect_set(regs, TEMAC_EMMC, emmc_reg))
176*4882a593Smuzhiyun 		return 0;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	printf("%s: PHY is %s with %dbase%s, %s%s\n",
179*4882a593Smuzhiyun 			dev->name, phydev->drv->name,
180*4882a593Smuzhiyun 			phydev->speed, (phydev->port == PORT_TP) ? "T" : "X",
181*4882a593Smuzhiyun 			(phydev->duplex) ? "FDX" : "HDX",
182*4882a593Smuzhiyun 			(phydev->port == PORT_OTHER) ? ", unkown mode" : "");
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	return 1;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /* setup mac addr */
ll_temac_setup_mac_addr(struct eth_device * dev)188*4882a593Smuzhiyun static int ll_temac_setup_mac_addr(struct eth_device *dev)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
191*4882a593Smuzhiyun 	u32 val;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/* set up unicast MAC address filter */
194*4882a593Smuzhiyun 	val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
195*4882a593Smuzhiyun 			(dev->enetaddr[1] << 8) | (dev->enetaddr[0]));
196*4882a593Smuzhiyun 	val &= UAW0_UADDR_MASK;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	if (!ll_temac_indirect_set(regs, TEMAC_UAW0, val))
199*4882a593Smuzhiyun 		return 1;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	val = ((dev->enetaddr[5] << 8) | dev->enetaddr[4]);
202*4882a593Smuzhiyun 	val &= UAW1_UADDR_MASK;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	if (!ll_temac_indirect_set(regs, TEMAC_UAW1, val))
205*4882a593Smuzhiyun 		return 1;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	return 0;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun /* halt device */
ll_temac_halt(struct eth_device * dev)211*4882a593Smuzhiyun static void ll_temac_halt(struct eth_device *dev)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	struct ll_temac *ll_temac = dev->priv;
214*4882a593Smuzhiyun 	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	/* Disable Receiver */
217*4882a593Smuzhiyun 	ll_temac_indirect_set(regs, TEMAC_RCW0, 0);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	/* Disable Transmitter */
220*4882a593Smuzhiyun 	ll_temac_indirect_set(regs, TEMAC_TC, 0);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	if (ll_temac->ctrlhalt)
223*4882a593Smuzhiyun 		ll_temac->ctrlhalt(dev);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/* Shut down the PHY, as needed */
226*4882a593Smuzhiyun 	phy_shutdown(ll_temac->phydev);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
ll_temac_init(struct eth_device * dev,bd_t * bis)229*4882a593Smuzhiyun static int ll_temac_init(struct eth_device *dev, bd_t *bis)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	struct ll_temac *ll_temac = dev->priv;
232*4882a593Smuzhiyun 	int ret;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08lx.\n",
235*4882a593Smuzhiyun 		dev->name, dev->index, dev->iobase);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	if (!ll_temac_setup_ctrl(dev))
238*4882a593Smuzhiyun 		return -1;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	/* Start up the PHY */
241*4882a593Smuzhiyun 	ret = phy_startup(ll_temac->phydev);
242*4882a593Smuzhiyun 	if (ret) {
243*4882a593Smuzhiyun 		printf("%s: Could not initialize PHY %s\n",
244*4882a593Smuzhiyun 		       dev->name, ll_temac->phydev->dev->name);
245*4882a593Smuzhiyun 		return ret;
246*4882a593Smuzhiyun 	}
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (!ll_temac_adjust_link(dev)) {
249*4882a593Smuzhiyun 		ll_temac_halt(dev);
250*4882a593Smuzhiyun 		return -1;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	/* If there's no link, fail */
254*4882a593Smuzhiyun 	return ll_temac->phydev->link ? 0 : -1;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun /*
258*4882a593Smuzhiyun  * Discover which PHY is attached to the device, and configure it
259*4882a593Smuzhiyun  * properly.  If the PHY is not recognized, then return 0
260*4882a593Smuzhiyun  * (failure).  Otherwise, return 1
261*4882a593Smuzhiyun  */
ll_temac_phy_init(struct eth_device * dev)262*4882a593Smuzhiyun static int ll_temac_phy_init(struct eth_device *dev)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	struct ll_temac *ll_temac = dev->priv;
265*4882a593Smuzhiyun 	struct phy_device *phydev;
266*4882a593Smuzhiyun 	unsigned int supported = PHY_GBIT_FEATURES;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	/* interface - look at driver/net/tsec.c */
269*4882a593Smuzhiyun 	phydev = phy_connect(ll_temac->bus, ll_temac->phyaddr,
270*4882a593Smuzhiyun 			dev, PHY_INTERFACE_MODE_NONE);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	phydev->supported &= supported;
273*4882a593Smuzhiyun 	phydev->advertising = phydev->supported;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	ll_temac->phydev = phydev;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	phy_config(phydev);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	return 1;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun /*
283*4882a593Smuzhiyun  * Initialize a single ll_temac devices
284*4882a593Smuzhiyun  *
285*4882a593Smuzhiyun  * Returns the result of ll_temac phy interface that were initialized
286*4882a593Smuzhiyun  */
xilinx_ll_temac_initialize(bd_t * bis,struct ll_temac_info * devinf)287*4882a593Smuzhiyun int xilinx_ll_temac_initialize(bd_t *bis, struct ll_temac_info *devinf)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	struct eth_device *dev;
290*4882a593Smuzhiyun 	struct ll_temac *ll_temac;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	dev = calloc(1, sizeof(*dev));
293*4882a593Smuzhiyun 	if (dev == NULL)
294*4882a593Smuzhiyun 		return 0;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	ll_temac = calloc(1, sizeof(struct ll_temac));
297*4882a593Smuzhiyun 	if (ll_temac == NULL) {
298*4882a593Smuzhiyun 		free(dev);
299*4882a593Smuzhiyun 		return 0;
300*4882a593Smuzhiyun 	}
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	/* use given name or generate its own unique name */
303*4882a593Smuzhiyun 	if (devinf->devname) {
304*4882a593Smuzhiyun 		strncpy(dev->name, devinf->devname, sizeof(dev->name));
305*4882a593Smuzhiyun 	} else {
306*4882a593Smuzhiyun 		snprintf(dev->name, sizeof(dev->name), "ll_tem.%lx",
307*4882a593Smuzhiyun 			 devinf->base_addr);
308*4882a593Smuzhiyun 		devinf->devname = dev->name;
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	dev->iobase = devinf->base_addr;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	dev->priv = ll_temac;
314*4882a593Smuzhiyun 	dev->init = ll_temac_init;
315*4882a593Smuzhiyun 	dev->halt = ll_temac_halt;
316*4882a593Smuzhiyun 	dev->write_hwaddr = ll_temac_setup_mac_addr;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	ll_temac->ctrladdr = devinf->ctrl_addr;
319*4882a593Smuzhiyun 	if (devinf->flags & XILINX_LL_TEMAC_M_SDMA_PLB) {
320*4882a593Smuzhiyun 		ll_temac_collect_xlplb_sdma_reg_addr(dev);
321*4882a593Smuzhiyun 		ll_temac->in32 = ll_temac_xlplb_in32;
322*4882a593Smuzhiyun 		ll_temac->out32 = ll_temac_xlplb_out32;
323*4882a593Smuzhiyun 		ll_temac->ctrlinit = ll_temac_init_sdma;
324*4882a593Smuzhiyun 		ll_temac->ctrlhalt = ll_temac_halt_sdma;
325*4882a593Smuzhiyun 		ll_temac->ctrlreset = ll_temac_reset_sdma;
326*4882a593Smuzhiyun 		dev->recv = ll_temac_recv_sdma;
327*4882a593Smuzhiyun 		dev->send = ll_temac_send_sdma;
328*4882a593Smuzhiyun 	} else {
329*4882a593Smuzhiyun 		ll_temac->in32 = NULL;
330*4882a593Smuzhiyun 		ll_temac->out32 = NULL;
331*4882a593Smuzhiyun 		ll_temac->ctrlinit = NULL;
332*4882a593Smuzhiyun 		ll_temac->ctrlhalt = NULL;
333*4882a593Smuzhiyun 		ll_temac->ctrlreset = ll_temac_reset_fifo;
334*4882a593Smuzhiyun 		dev->recv = ll_temac_recv_fifo;
335*4882a593Smuzhiyun 		dev->send = ll_temac_send_fifo;
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	/* Link to specified MDIO bus */
339*4882a593Smuzhiyun 	strncpy(ll_temac->mdio_busname, devinf->mdio_busname, MDIO_NAME_LEN);
340*4882a593Smuzhiyun 	ll_temac->bus = miiphy_get_dev_by_name(ll_temac->mdio_busname);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	/* Looking for a valid PHY address if it is not yet set */
343*4882a593Smuzhiyun 	if (devinf->phyaddr == -1)
344*4882a593Smuzhiyun 		ll_temac->phyaddr = ll_temac_phy_addr(ll_temac->bus);
345*4882a593Smuzhiyun 	else
346*4882a593Smuzhiyun 		ll_temac->phyaddr = devinf->phyaddr;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	eth_register(dev);
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	/* Try to initialize PHY here, and return */
351*4882a593Smuzhiyun 	return ll_temac_phy_init(dev);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun /*
355*4882a593Smuzhiyun  * Initialize a single ll_temac device with its mdio bus behind ll_temac
356*4882a593Smuzhiyun  *
357*4882a593Smuzhiyun  * Returns 1 if the ll_temac device and the mdio bus were initialized
358*4882a593Smuzhiyun  * otherwise returns 0
359*4882a593Smuzhiyun  */
xilinx_ll_temac_eth_init(bd_t * bis,unsigned long base_addr,int flags,unsigned long ctrl_addr)360*4882a593Smuzhiyun int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
361*4882a593Smuzhiyun 							unsigned long ctrl_addr)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	struct ll_temac_info devinf;
364*4882a593Smuzhiyun 	struct ll_temac_mdio_info mdioinf;
365*4882a593Smuzhiyun 	int ret;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	/* prepare the internal driver informations */
368*4882a593Smuzhiyun 	devinf.flags = flags;
369*4882a593Smuzhiyun 	devinf.base_addr = base_addr;
370*4882a593Smuzhiyun 	devinf.ctrl_addr = ctrl_addr;
371*4882a593Smuzhiyun 	devinf.devname = NULL;
372*4882a593Smuzhiyun 	devinf.phyaddr = -1;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	mdioinf.name = devinf.mdio_busname = NULL;
375*4882a593Smuzhiyun 	mdioinf.regs = (struct temac_reg *)devinf.base_addr;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	ret = xilinx_ll_temac_mdio_initialize(bis, &mdioinf);
378*4882a593Smuzhiyun 	if (ret >= 0) {
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 		/*
381*4882a593Smuzhiyun 		 * If there was no MDIO bus name then take over the
382*4882a593Smuzhiyun 		 * new automaticaly generated by the MDIO init code.
383*4882a593Smuzhiyun 		 */
384*4882a593Smuzhiyun 		if (mdioinf.name != devinf.mdio_busname)
385*4882a593Smuzhiyun 			devinf.mdio_busname = mdioinf.name;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 		ret = xilinx_ll_temac_initialize(bis, &devinf);
388*4882a593Smuzhiyun 		if (ret > 0)
389*4882a593Smuzhiyun 			return 1;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	return 0;
394*4882a593Smuzhiyun }
395