3 * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * Designware ethernet IP driver for u-boot
31 #include <linux/err.h>
33 #include "designware.h"
35 static void tx_descs_init(struct eth_device *dev)
37 struct dw_eth_dev *priv = dev->priv;
38 struct eth_dma_regs *dma_p = priv->dma_regs_p;
39 struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
40 char *txbuffs = &priv->txbuffs[0];
41 struct dmamacdescr *desc_p;
44 for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
45 desc_p = &desc_table_p[idx];
46 desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
47 desc_p->dmamac_next = &desc_table_p[idx + 1];
49 #if defined(CONFIG_DW_ALTDESCRIPTOR)
50 desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
51 DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
52 DESC_TXSTS_TXCHECKINSCTRL | \
53 DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
55 desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
56 desc_p->dmamac_cntl = 0;
57 desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
59 desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
60 desc_p->txrx_status = 0;
64 /* Correcting the last pointer of the chain */
65 desc_p->dmamac_next = &desc_table_p[0];
67 writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
70 static void rx_descs_init(struct eth_device *dev)
72 struct dw_eth_dev *priv = dev->priv;
73 struct eth_dma_regs *dma_p = priv->dma_regs_p;
74 struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
75 char *rxbuffs = &priv->rxbuffs[0];
76 struct dmamacdescr *desc_p;
79 for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
80 desc_p = &desc_table_p[idx];
81 desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
82 desc_p->dmamac_next = &desc_table_p[idx + 1];
85 (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
88 desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
91 /* Correcting the last pointer of the chain */
92 desc_p->dmamac_next = &desc_table_p[0];
94 writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
97 static void descs_init(struct eth_device *dev)
103 static int mac_reset(struct eth_device *dev)
105 struct dw_eth_dev *priv = dev->priv;
106 struct eth_mac_regs *mac_p = priv->mac_regs_p;
107 struct eth_dma_regs *dma_p = priv->dma_regs_p;
109 int timeout = CONFIG_MACRESET_TIMEOUT;
111 writel(DMAMAC_SRST, &dma_p->busmode);
112 writel(MII_PORTSELECT, &mac_p->conf);
115 if (!(readl(&dma_p->busmode) & DMAMAC_SRST))
123 static int dw_write_hwaddr(struct eth_device *dev)
125 struct dw_eth_dev *priv = dev->priv;
126 struct eth_mac_regs *mac_p = priv->mac_regs_p;
127 u32 macid_lo, macid_hi;
128 u8 *mac_id = &dev->enetaddr[0];
130 macid_lo = mac_id[0] + (mac_id[1] << 8) + \
131 (mac_id[2] << 16) + (mac_id[3] << 24);
132 macid_hi = mac_id[4] + (mac_id[5] << 8);
134 writel(macid_hi, &mac_p->macaddr0hi);
135 writel(macid_lo, &mac_p->macaddr0lo);
140 static int dw_eth_init(struct eth_device *dev, bd_t *bis)
142 struct dw_eth_dev *priv = dev->priv;
143 struct eth_mac_regs *mac_p = priv->mac_regs_p;
144 struct eth_dma_regs *dma_p = priv->dma_regs_p;
147 /* Reset ethernet hardware */
148 if (mac_reset(dev) < 0)
151 /* Resore the HW MAC address as it has been lost during MAC reset */
152 dw_write_hwaddr(dev);
154 writel(FIXEDBURST | PRIORXTX_41 | BURST_16,
157 writel(FLUSHTXFIFO | readl(&dma_p->opmode), &dma_p->opmode);
158 writel(STOREFORWARD | TXSECONDFRAME, &dma_p->opmode);
160 conf = FRAMEBURSTENABLE | DISABLERXOWN;
162 if (priv->speed != SPEED_1000M)
163 conf |= MII_PORTSELECT;
165 if (priv->duplex == FULL_DUPLEX)
166 conf |= FULLDPLXMODE;
168 writel(conf, &mac_p->conf);
173 * Start/Enable xfer at dma as well as mac level
175 writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode);
176 writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode);
178 writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
183 static int dw_eth_send(struct eth_device *dev, volatile void *packet,
186 struct dw_eth_dev *priv = dev->priv;
187 struct eth_dma_regs *dma_p = priv->dma_regs_p;
188 u32 desc_num = priv->tx_currdescnum;
189 struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
191 /* Check if the descriptor is owned by CPU */
192 if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
193 printf("CPU not owner of tx frame\n");
197 memcpy((void *)desc_p->dmamac_addr, (void *)packet, length);
199 #if defined(CONFIG_DW_ALTDESCRIPTOR)
200 desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
201 desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
202 DESC_TXCTRL_SIZE1MASK;
204 desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
205 desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
207 desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
208 DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
211 desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
214 /* Test the wrap-around condition. */
215 if (++desc_num >= CONFIG_TX_DESCR_NUM)
218 priv->tx_currdescnum = desc_num;
220 /* Start the transmission */
221 writel(POLL_DATA, &dma_p->txpolldemand);
226 static int dw_eth_recv(struct eth_device *dev)
228 struct dw_eth_dev *priv = dev->priv;
229 u32 desc_num = priv->rx_currdescnum;
230 struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
232 u32 status = desc_p->txrx_status;
235 /* Check if the owner is the CPU */
236 if (!(status & DESC_RXSTS_OWNBYDMA)) {
238 length = (status & DESC_RXSTS_FRMLENMSK) >> \
239 DESC_RXSTS_FRMLENSHFT;
241 NetReceive(desc_p->dmamac_addr, length);
244 * Make the current descriptor valid again and go to
247 desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
249 /* Test the wrap-around condition. */
250 if (++desc_num >= CONFIG_RX_DESCR_NUM)
254 priv->rx_currdescnum = desc_num;
259 static void dw_eth_halt(struct eth_device *dev)
261 struct dw_eth_dev *priv = dev->priv;
264 priv->tx_currdescnum = priv->rx_currdescnum = 0;
267 static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val)
269 struct dw_eth_dev *priv = dev->priv;
270 struct eth_mac_regs *mac_p = priv->mac_regs_p;
272 int timeout = CONFIG_MDIO_TIMEOUT;
274 miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
275 ((reg << MIIREGSHIFT) & MII_REGMSK);
277 writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
280 if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
281 *val = readl(&mac_p->miidata);
290 static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val)
292 struct dw_eth_dev *priv = dev->priv;
293 struct eth_mac_regs *mac_p = priv->mac_regs_p;
295 int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
298 writel(val, &mac_p->miidata);
299 miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
300 ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
302 writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
305 if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
312 /* Needed as a fix for ST-Phy */
313 eth_mdio_read(dev, addr, reg, &value);
318 #if defined(CONFIG_DW_SEARCH_PHY)
319 static int find_phy(struct eth_device *dev)
325 eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
326 oldctrl = ctrl & BMCR_ANENABLE;
328 ctrl ^= BMCR_ANENABLE;
329 eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl);
330 eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
331 ctrl &= BMCR_ANENABLE;
333 if (ctrl == oldctrl) {
336 ctrl ^= BMCR_ANENABLE;
337 eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl);
341 } while (phy_addr < 32);
347 static int dw_reset_phy(struct eth_device *dev)
349 struct dw_eth_dev *priv = dev->priv;
351 int timeout = CONFIG_PHYRESET_TIMEOUT;
352 u32 phy_addr = priv->address;
354 eth_mdio_write(dev, phy_addr, MII_BMCR, BMCR_RESET);
356 eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
357 if (!(ctrl & BMCR_RESET))
365 #ifdef CONFIG_PHY_RESET_DELAY
366 udelay(CONFIG_PHY_RESET_DELAY);
371 static int configure_phy(struct eth_device *dev)
373 struct dw_eth_dev *priv = dev->priv;
376 #if defined(CONFIG_DW_AUTONEG)
384 #if defined(CONFIG_DW_SEARCH_PHY)
385 phy_addr = find_phy(dev);
387 priv->address = phy_addr;
391 phy_addr = priv->address;
393 if (dw_reset_phy(dev) < 0)
396 #if defined(CONFIG_DW_AUTONEG)
397 bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_SPEED100 | \
398 BMCR_FULLDPLX | BMCR_SPEED1000;
400 bmcr = BMCR_SPEED100 | BMCR_FULLDPLX;
402 #if defined(CONFIG_DW_SPEED10M)
403 bmcr &= ~BMCR_SPEED100;
405 #if defined(CONFIG_DW_DUPLEXHALF)
406 bmcr &= ~BMCR_FULLDPLX;
409 if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0)
412 /* Read the phy status register and populate priv structure */
413 #if defined(CONFIG_DW_AUTONEG)
414 timeout = CONFIG_AUTONEG_TIMEOUT;
416 eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
417 if (bmsr & BMSR_ANEGCOMPLETE)
422 eth_mdio_read(dev, phy_addr, MII_LPA, &anlpar);
423 eth_mdio_read(dev, phy_addr, MII_STAT1000, &btsr);
425 if (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
426 priv->speed = SPEED_1000M;
427 if (btsr & PHY_1000BTSR_1000FD)
428 priv->duplex = FULL_DUPLEX;
430 priv->duplex = HALF_DUPLEX;
432 if (anlpar & LPA_100)
433 priv->speed = SPEED_100M;
435 priv->speed = SPEED_10M;
437 if (anlpar & (LPA_10FULL | LPA_100FULL))
438 priv->duplex = FULL_DUPLEX;
440 priv->duplex = HALF_DUPLEX;
443 if (eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl) < 0)
446 if (ctrl & BMCR_FULLDPLX)
447 priv->duplex = FULL_DUPLEX;
449 priv->duplex = HALF_DUPLEX;
451 if (ctrl & BMCR_SPEED1000)
452 priv->speed = SPEED_1000M;
453 else if (ctrl & BMCR_SPEED100)
454 priv->speed = SPEED_100M;
456 priv->speed = SPEED_10M;
461 #if defined(CONFIG_MII)
462 static int dw_mii_read(const char *devname, u8 addr, u8 reg, u16 *val)
464 struct eth_device *dev;
466 dev = eth_get_dev_by_name(devname);
468 eth_mdio_read(dev, addr, reg, val);
473 static int dw_mii_write(const char *devname, u8 addr, u8 reg, u16 val)
475 struct eth_device *dev;
477 dev = eth_get_dev_by_name(devname);
479 eth_mdio_write(dev, addr, reg, val);
485 int designware_initialize(u32 id, ulong base_addr, u32 phy_addr)
487 struct eth_device *dev;
488 struct dw_eth_dev *priv;
490 dev = (struct eth_device *) malloc(sizeof(struct eth_device));
495 * Since the priv structure contains the descriptors which need a strict
496 * buswidth alignment, memalign is used to allocate memory
498 priv = (struct dw_eth_dev *) memalign(16, sizeof(struct dw_eth_dev));
504 memset(dev, 0, sizeof(struct eth_device));
505 memset(priv, 0, sizeof(struct dw_eth_dev));
507 sprintf(dev->name, "mii%d", id);
508 dev->iobase = (int)base_addr;
511 eth_getenv_enetaddr_by_index("eth", id, &dev->enetaddr[0]);
514 priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
515 priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
517 priv->address = phy_addr;
519 if (mac_reset(dev) < 0)
522 if (configure_phy(dev) < 0) {
523 printf("Phy could not be configured\n");
527 dev->init = dw_eth_init;
528 dev->send = dw_eth_send;
529 dev->recv = dw_eth_recv;
530 dev->halt = dw_eth_halt;
531 dev->write_hwaddr = dw_write_hwaddr;
535 #if defined(CONFIG_MII)
536 miiphy_register(dev->name, dw_mii_read, dw_mii_write);