blob: b6e6f6e5ec02022427dc5591867f27d352b540dc [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Macpaul Lin199c6252010-12-21 16:59:46 +08002/*
3 * Faraday FTGMAC100 Ethernet
4 *
5 * (C) Copyright 2009 Faraday Technology
6 * Po-Yu Chuang <ratbert@faraday-tech.com>
7 *
8 * (C) Copyright 2010 Andes Technology
9 * Macpaul Lin <macpaul@andestech.com>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010010 *
11 * Copyright (C) 2018, IBM Corporation.
Macpaul Lin199c6252010-12-21 16:59:46 +080012 */
13
Cédric Le Goater38b33e92018-10-29 07:06:31 +010014#include <dm.h>
15#include <miiphy.h>
Macpaul Lin199c6252010-12-21 16:59:46 +080016#include <malloc.h>
17#include <net.h>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010018#include <linux/io.h>
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +080019#include <asm/dma-mapping.h>
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010020#include <linux/iopoll.h>
Macpaul Lin199c6252010-12-21 16:59:46 +080021
22#include "ftgmac100.h"
23
24#define ETH_ZLEN 60
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +080025#define CFG_XBUF_SIZE 1536
Macpaul Lin199c6252010-12-21 16:59:46 +080026
Macpaul Lin199c6252010-12-21 16:59:46 +080027/* RBSR - hw default init value is also 0x640 */
28#define RBSR_DEFAULT_VALUE 0x640
29
30/* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
31#define PKTBUFSTX 4 /* must be power of 2 */
32
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010033/* Timeout for a mdio read/write operation */
34#define FTGMAC100_MDIO_TIMEOUT_USEC 10000
35
36/*
37 * MDC clock cycle threshold
38 *
39 * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
40 */
41#define MDC_CYCTHR 0x34
42
Cédric Le Goater38b33e92018-10-29 07:06:31 +010043/**
44 * struct ftgmac100_data - private data for the FTGMAC100 driver
45 *
46 * @iobase: The base address of the hardware registers
47 * @txdes: The array of transmit descriptors
48 * @rxdes: The array of receive descriptors
49 * @tx_index: Transmit descriptor index in @txdes
50 * @rx_index: Receive descriptor index in @rxdes
51 * @phy_addr: The PHY interface address to use
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010052 * @phydev: The PHY device backing the MAC
53 * @bus: The mdio bus
54 * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
55 * @max_speed: Maximum speed of Ethernet connection supported by MAC
Cédric Le Goater38b33e92018-10-29 07:06:31 +010056 */
Macpaul Lin199c6252010-12-21 16:59:46 +080057struct ftgmac100_data {
Cédric Le Goater38b33e92018-10-29 07:06:31 +010058 struct ftgmac100 *iobase;
59
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +080060 ulong txdes_dma;
61 struct ftgmac100_txdes *txdes;
62 ulong rxdes_dma;
63 struct ftgmac100_rxdes *rxdes;
Macpaul Lin199c6252010-12-21 16:59:46 +080064 int tx_index;
65 int rx_index;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010066
67 u32 phy_addr;
68 struct phy_device *phydev;
69 struct mii_dev *bus;
70 u32 phy_mode;
71 u32 max_speed;
Macpaul Lin199c6252010-12-21 16:59:46 +080072};
73
74/*
75 * struct mii_bus functions
76 */
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010077static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
78 int reg_addr)
Macpaul Lin199c6252010-12-21 16:59:46 +080079{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010080 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +010081 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +080082 int phycr;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010083 int data;
84 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +080085
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010086 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
87 FTGMAC100_PHYCR_PHYAD(phy_addr) |
88 FTGMAC100_PHYCR_REGAD(reg_addr) |
89 FTGMAC100_PHYCR_MIIRD;
Macpaul Lin199c6252010-12-21 16:59:46 +080090 writel(phycr, &ftgmac100->phycr);
91
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010092 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
93 !(phycr & FTGMAC100_PHYCR_MIIRD),
94 FTGMAC100_MDIO_TIMEOUT_USEC);
95 if (ret) {
96 pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
97 priv->phydev->dev->name, phy_addr, reg_addr);
98 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +080099 }
100
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100101 data = readl(&ftgmac100->phydata);
102
103 return FTGMAC100_PHYDATA_MIIRDATA(data);
Macpaul Lin199c6252010-12-21 16:59:46 +0800104}
105
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100106static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
107 int reg_addr, u16 value)
Macpaul Lin199c6252010-12-21 16:59:46 +0800108{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100109 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100110 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800111 int phycr;
112 int data;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100113 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800114
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100115 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
116 FTGMAC100_PHYCR_PHYAD(phy_addr) |
117 FTGMAC100_PHYCR_REGAD(reg_addr) |
118 FTGMAC100_PHYCR_MIIWR;
Macpaul Lin199c6252010-12-21 16:59:46 +0800119 data = FTGMAC100_PHYDATA_MIIWDATA(value);
120
121 writel(data, &ftgmac100->phydata);
122 writel(phycr, &ftgmac100->phycr);
123
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100124 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
125 !(phycr & FTGMAC100_PHYCR_MIIWR),
126 FTGMAC100_MDIO_TIMEOUT_USEC);
127 if (ret) {
128 pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
129 priv->phydev->dev->name, phy_addr, reg_addr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800130 }
131
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100132 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800133}
134
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100135static int ftgmac100_mdio_init(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800136{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100137 struct ftgmac100_data *priv = dev_get_priv(dev);
138 struct mii_dev *bus;
139 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800140
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100141 bus = mdio_alloc();
142 if (!bus)
143 return -ENOMEM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800144
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100145 bus->read = ftgmac100_mdio_read;
146 bus->write = ftgmac100_mdio_write;
147 bus->priv = priv;
Macpaul Lin199c6252010-12-21 16:59:46 +0800148
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100149 ret = mdio_register_seq(bus, dev->seq);
150 if (ret) {
151 free(bus);
152 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800153 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800154
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100155 priv->bus = bus;
Macpaul Lin199c6252010-12-21 16:59:46 +0800156
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100157 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800158}
159
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100160static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800161{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100162 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100163 struct phy_device *phydev = priv->phydev;
164 u32 maccr;
Macpaul Lin199c6252010-12-21 16:59:46 +0800165
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100166 if (!phydev->link) {
167 dev_err(phydev->dev, "No link\n");
168 return -EREMOTEIO;
169 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800170
171 /* read MAC control register and clear related bits */
172 maccr = readl(&ftgmac100->maccr) &
173 ~(FTGMAC100_MACCR_GIGA_MODE |
174 FTGMAC100_MACCR_FAST_MODE |
175 FTGMAC100_MACCR_FULLDUP);
176
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100177 if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
Macpaul Lin199c6252010-12-21 16:59:46 +0800178 maccr |= FTGMAC100_MACCR_GIGA_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800179
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100180 if (phydev->speed == 100)
Macpaul Lin199c6252010-12-21 16:59:46 +0800181 maccr |= FTGMAC100_MACCR_FAST_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800182
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100183 if (phydev->duplex)
184 maccr |= FTGMAC100_MACCR_FULLDUP;
Macpaul Lin199c6252010-12-21 16:59:46 +0800185
186 /* update MII config into maccr */
187 writel(maccr, &ftgmac100->maccr);
188
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100189 return 0;
190}
191
192static int ftgmac100_phy_init(struct udevice *dev)
193{
194 struct ftgmac100_data *priv = dev_get_priv(dev);
195 struct phy_device *phydev;
196 int ret;
197
198 phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
199 if (!phydev)
200 return -ENODEV;
201
202 phydev->supported &= PHY_GBIT_FEATURES;
203 if (priv->max_speed) {
204 ret = phy_set_supported(phydev, priv->max_speed);
205 if (ret)
206 return ret;
207 }
208 phydev->advertising = phydev->supported;
209 priv->phydev = phydev;
210 phy_config(phydev);
211
212 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800213}
214
215/*
216 * Reset MAC
217 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100218static void ftgmac100_reset(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800219{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100220 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800221
222 debug("%s()\n", __func__);
223
Cédric Le Goatercef951c2018-10-29 07:06:32 +0100224 setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
Macpaul Lin199c6252010-12-21 16:59:46 +0800225
226 while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
227 ;
228}
229
230/*
231 * Set MAC address
232 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100233static int ftgmac100_set_mac(struct ftgmac100_data *priv,
234 const unsigned char *mac)
Macpaul Lin199c6252010-12-21 16:59:46 +0800235{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100236 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800237 unsigned int maddr = mac[0] << 8 | mac[1];
238 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
239
240 debug("%s(%x %x)\n", __func__, maddr, laddr);
241
242 writel(maddr, &ftgmac100->mac_madr);
243 writel(laddr, &ftgmac100->mac_ladr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800244
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100245 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800246}
247
248/*
249 * disable transmitter, receiver
250 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100251static void ftgmac100_stop(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800252{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100253 struct ftgmac100_data *priv = dev_get_priv(dev);
254 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800255
256 debug("%s()\n", __func__);
257
258 writel(0, &ftgmac100->maccr);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100259
260 phy_shutdown(priv->phydev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800261}
262
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100263static int ftgmac100_start(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800264{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100265 struct eth_pdata *plat = dev_get_platdata(dev);
266 struct ftgmac100_data *priv = dev_get_priv(dev);
267 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100268 struct phy_device *phydev = priv->phydev;
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800269 struct ftgmac100_txdes *txdes;
270 struct ftgmac100_rxdes *rxdes;
Macpaul Lin199c6252010-12-21 16:59:46 +0800271 unsigned int maccr;
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800272 void *buf;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100273 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800274 int i;
275
276 debug("%s()\n", __func__);
277
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100278 ftgmac100_reset(priv);
279
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800280 if (!priv->txdes) {
281 txdes = dma_alloc_coherent(
282 sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
283 if (!txdes)
284 panic("ftgmac100: out of memory\n");
285 memset(txdes, 0, sizeof(*txdes) * PKTBUFSTX);
286 priv->txdes = txdes;
287 }
288 txdes = priv->txdes;
289
290 if (!priv->rxdes) {
291 rxdes = dma_alloc_coherent(
292 sizeof(*rxdes) * PKTBUFSRX, &priv->rxdes_dma);
293 if (!rxdes)
294 panic("ftgmac100: out of memory\n");
295 memset(rxdes, 0, sizeof(*rxdes) * PKTBUFSRX);
296 priv->rxdes = rxdes;
297 }
298 rxdes = priv->rxdes;
299
Macpaul Lin199c6252010-12-21 16:59:46 +0800300 /* set the ethernet address */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100301 ftgmac100_set_mac(priv, plat->enetaddr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800302
303 /* disable all interrupts */
304 writel(0, &ftgmac100->ier);
305
306 /* initialize descriptors */
307 priv->tx_index = 0;
308 priv->rx_index = 0;
309
310 txdes[PKTBUFSTX - 1].txdes0 = FTGMAC100_TXDES0_EDOTR;
311 rxdes[PKTBUFSRX - 1].rxdes0 = FTGMAC100_RXDES0_EDORR;
312
313 for (i = 0; i < PKTBUFSTX; i++) {
314 /* TXBUF_BADR */
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800315 if (!txdes[i].txdes2) {
316 buf = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
317 if (!buf)
318 panic("ftgmac100: out of memory\n");
319 txdes[i].txdes3 = virt_to_phys(buf);
320 txdes[i].txdes2 = (uint)buf;
321 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800322 txdes[i].txdes1 = 0;
323 }
324
325 for (i = 0; i < PKTBUFSRX; i++) {
326 /* RXBUF_BADR */
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800327 if (!rxdes[i].rxdes2) {
Joe Hershberger9f09a362015-04-08 01:41:06 -0500328 buf = net_rx_packets[i];
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800329 rxdes[i].rxdes3 = virt_to_phys(buf);
330 rxdes[i].rxdes2 = (uint)buf;
331 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800332 rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
333 }
334
335 /* transmit ring */
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800336 writel(priv->txdes_dma, &ftgmac100->txr_badr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800337
338 /* receive ring */
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800339 writel(priv->rxdes_dma, &ftgmac100->rxr_badr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800340
341 /* poll receive descriptor automatically */
342 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
343
344 /* config receive buffer size register */
345 writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE), &ftgmac100->rbsr);
346
347 /* enable transmitter, receiver */
348 maccr = FTGMAC100_MACCR_TXMAC_EN |
349 FTGMAC100_MACCR_RXMAC_EN |
350 FTGMAC100_MACCR_TXDMA_EN |
351 FTGMAC100_MACCR_RXDMA_EN |
352 FTGMAC100_MACCR_CRC_APD |
353 FTGMAC100_MACCR_FULLDUP |
354 FTGMAC100_MACCR_RX_RUNT |
355 FTGMAC100_MACCR_RX_BROADPKT;
356
357 writel(maccr, &ftgmac100->maccr);
358
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100359 ret = phy_startup(phydev);
360 if (ret) {
361 dev_err(phydev->dev, "Could not start PHY\n");
362 return ret;
363 }
364
365 ret = ftgmac100_phy_adjust_link(priv);
366 if (ret) {
367 dev_err(phydev->dev, "Could not adjust link\n");
368 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800369 }
370
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100371 printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
372 phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
373
Macpaul Lin199c6252010-12-21 16:59:46 +0800374 return 0;
375}
376
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100377static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
378{
379 struct ftgmac100_data *priv = dev_get_priv(dev);
380 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
381
382 /* Release buffer to DMA */
383 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
384
385 /* Move to next descriptor */
386 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
387
388 return 0;
389}
390
Macpaul Lin199c6252010-12-21 16:59:46 +0800391/*
392 * Get a data block via Ethernet
393 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100394static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
Macpaul Lin199c6252010-12-21 16:59:46 +0800395{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100396 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800397 struct ftgmac100_rxdes *curr_des;
398 unsigned short rxlen;
399
400 curr_des = &priv->rxdes[priv->rx_index];
401
402 if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
403 return -1;
404
405 if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
406 FTGMAC100_RXDES0_CRC_ERR |
407 FTGMAC100_RXDES0_FTL |
408 FTGMAC100_RXDES0_RUNT |
409 FTGMAC100_RXDES0_RX_ODD_NB)) {
410 return -1;
411 }
412
413 rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
414
415 debug("%s(): RX buffer %d, %x received\n",
416 __func__, priv->rx_index, rxlen);
417
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800418 /* invalidate d-cache */
419 dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);
420
Macpaul Lin199c6252010-12-21 16:59:46 +0800421 /* pass the packet up to the protocol layers. */
Joe Hershberger9f09a362015-04-08 01:41:06 -0500422 net_process_received_packet((void *)curr_des->rxdes2, rxlen);
Macpaul Lin199c6252010-12-21 16:59:46 +0800423
424 /* release buffer to DMA */
425 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
426
427 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
428
429 return 0;
430}
431
432/*
433 * Send a data block via Ethernet
434 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100435static int ftgmac100_send(struct udevice *dev, void *packet, int length)
Macpaul Lin199c6252010-12-21 16:59:46 +0800436{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100437 struct ftgmac100_data *priv = dev_get_priv(dev);
438 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800439 struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
Macpaul Lin199c6252010-12-21 16:59:46 +0800440
441 if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
442 debug("%s(): no TX descriptor available\n", __func__);
443 return -1;
444 }
445
446 debug("%s(%x, %x)\n", __func__, (int)packet, length);
447
448 length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
449
Kuo-Jung Sucd19bd32013-05-07 14:33:51 +0800450 memcpy((void *)curr_des->txdes2, (void *)packet, length);
451 dma_map_single((void *)curr_des->txdes2, length, DMA_TO_DEVICE);
Macpaul Lin199c6252010-12-21 16:59:46 +0800452
453 /* only one descriptor on TXBUF */
454 curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
455 curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
456 FTGMAC100_TXDES0_LTS |
457 FTGMAC100_TXDES0_TXBUF_SIZE(length) |
458 FTGMAC100_TXDES0_TXDMA_OWN ;
459
460 /* start transmit */
461 writel(1, &ftgmac100->txpd);
462
Macpaul Lin199c6252010-12-21 16:59:46 +0800463 debug("%s(): packet sent\n", __func__);
464
465 priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
466
467 return 0;
468}
469
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100470static int ftgmac100_write_hwaddr(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800471{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100472 struct eth_pdata *pdata = dev_get_platdata(dev);
473 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800474
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100475 return ftgmac100_set_mac(priv, pdata->enetaddr);
476}
Macpaul Lin199c6252010-12-21 16:59:46 +0800477
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100478static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
479{
480 struct eth_pdata *pdata = dev_get_platdata(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100481 const char *phy_mode;
Macpaul Lin199c6252010-12-21 16:59:46 +0800482
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100483 pdata->iobase = devfdt_get_addr(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100484 pdata->phy_interface = -1;
485 phy_mode = dev_read_string(dev, "phy-mode");
486 if (phy_mode)
487 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
488 if (pdata->phy_interface == -1) {
489 dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
490 return -EINVAL;
491 }
492
493 pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
494
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100495 return 0;
496}
Macpaul Lin199c6252010-12-21 16:59:46 +0800497
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100498static int ftgmac100_probe(struct udevice *dev)
499{
500 struct eth_pdata *pdata = dev_get_platdata(dev);
501 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100502 int ret;
Macpaul Linc56c5a32011-09-20 19:54:32 +0000503
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100504 priv->iobase = (struct ftgmac100 *)pdata->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100505 priv->phy_mode = pdata->phy_interface;
506 priv->max_speed = pdata->max_speed;
507 priv->phy_addr = 0;
508
509 ret = ftgmac100_mdio_init(dev);
510 if (ret) {
511 dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
512 goto out;
513 }
514
515 ret = ftgmac100_phy_init(dev);
516 if (ret) {
517 dev_err(dev, "Failed to initialize PHY: %d\n", ret);
518 goto out;
519 }
520
521out:
522 return ret;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100523}
Macpaul Lin199c6252010-12-21 16:59:46 +0800524
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100525static int ftgmac100_remove(struct udevice *dev)
526{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100527 struct ftgmac100_data *priv = dev_get_priv(dev);
528
529 free(priv->phydev);
530 mdio_unregister(priv->bus);
531 mdio_free(priv->bus);
532
Macpaul Lin199c6252010-12-21 16:59:46 +0800533 return 0;
534}
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100535
536static const struct eth_ops ftgmac100_ops = {
537 .start = ftgmac100_start,
538 .send = ftgmac100_send,
539 .recv = ftgmac100_recv,
540 .stop = ftgmac100_stop,
541 .free_pkt = ftgmac100_free_pkt,
542 .write_hwaddr = ftgmac100_write_hwaddr,
543};
544
545static const struct udevice_id ftgmac100_ids[] = {
546 { .compatible = "faraday,ftgmac100" },
547 { }
548};
549
550U_BOOT_DRIVER(ftgmac100) = {
551 .name = "ftgmac100",
552 .id = UCLASS_ETH,
553 .of_match = ftgmac100_ids,
554 .ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
555 .probe = ftgmac100_probe,
556 .remove = ftgmac100_remove,
557 .ops = &ftgmac100_ops,
558 .priv_auto_alloc_size = sizeof(struct ftgmac100_data),
559 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
560 .flags = DM_FLAG_ALLOC_PRIV_DMA,
561};