blob: 92c38a81bd352b9311f7087bc67545c14b0f8a93 [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 Goater6afa3f12018-10-29 07:06:36 +010014#include <clk.h>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010015#include <dm.h>
16#include <miiphy.h>
Macpaul Lin199c6252010-12-21 16:59:46 +080017#include <net.h>
Cédric Le Goater9bcb6652018-10-29 07:06:35 +010018#include <wait_bit.h>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010019#include <linux/io.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
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010024/* Min frame ethernet frame size without FCS */
25#define ETH_ZLEN 60
Macpaul Lin199c6252010-12-21 16:59:46 +080026
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010027/* Receive Buffer Size Register - HW default is 0x640 */
28#define FTGMAC100_RBSR_DEFAULT 0x640
Macpaul Lin199c6252010-12-21 16:59:46 +080029
30/* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
31#define PKTBUFSTX 4 /* must be power of 2 */
32
Cédric Le Goater9bcb6652018-10-29 07:06:35 +010033/* Timeout for transmit */
34#define FTGMAC100_TX_TIMEOUT_MS 1000
35
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010036/* Timeout for a mdio read/write operation */
37#define FTGMAC100_MDIO_TIMEOUT_USEC 10000
38
39/*
40 * MDC clock cycle threshold
41 *
42 * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
43 */
44#define MDC_CYCTHR 0x34
45
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010046/*
47 * ftgmac100 model variants
48 */
49enum ftgmac100_model {
50 FTGMAC100_MODEL_FARADAY,
51 FTGMAC100_MODEL_ASPEED,
52};
53
Cédric Le Goater38b33e92018-10-29 07:06:31 +010054/**
55 * struct ftgmac100_data - private data for the FTGMAC100 driver
56 *
57 * @iobase: The base address of the hardware registers
58 * @txdes: The array of transmit descriptors
59 * @rxdes: The array of receive descriptors
60 * @tx_index: Transmit descriptor index in @txdes
61 * @rx_index: Receive descriptor index in @rxdes
62 * @phy_addr: The PHY interface address to use
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010063 * @phydev: The PHY device backing the MAC
64 * @bus: The mdio bus
65 * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
66 * @max_speed: Maximum speed of Ethernet connection supported by MAC
Cédric Le Goater6afa3f12018-10-29 07:06:36 +010067 * @clks: The bulk of clocks assigned to the device in the DT
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010068 * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
69 * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
Cédric Le Goater38b33e92018-10-29 07:06:31 +010070 */
Macpaul Lin199c6252010-12-21 16:59:46 +080071struct ftgmac100_data {
Cédric Le Goater38b33e92018-10-29 07:06:31 +010072 struct ftgmac100 *iobase;
73
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010074 struct ftgmac100_txdes txdes[PKTBUFSTX];
75 struct ftgmac100_rxdes rxdes[PKTBUFSRX];
Macpaul Lin199c6252010-12-21 16:59:46 +080076 int tx_index;
77 int rx_index;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010078
79 u32 phy_addr;
80 struct phy_device *phydev;
81 struct mii_dev *bus;
82 u32 phy_mode;
83 u32 max_speed;
Cédric Le Goater6afa3f12018-10-29 07:06:36 +010084
85 struct clk_bulk clks;
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010086
87 /* End of RX/TX ring buffer bits. Depend on model */
88 u32 rxdes0_edorr_mask;
89 u32 txdes0_edotr_mask;
Macpaul Lin199c6252010-12-21 16:59:46 +080090};
91
92/*
93 * struct mii_bus functions
94 */
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010095static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
96 int reg_addr)
Macpaul Lin199c6252010-12-21 16:59:46 +080097{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010098 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +010099 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800100 int phycr;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100101 int data;
102 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800103
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100104 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
105 FTGMAC100_PHYCR_PHYAD(phy_addr) |
106 FTGMAC100_PHYCR_REGAD(reg_addr) |
107 FTGMAC100_PHYCR_MIIRD;
Macpaul Lin199c6252010-12-21 16:59:46 +0800108 writel(phycr, &ftgmac100->phycr);
109
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100110 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
111 !(phycr & FTGMAC100_PHYCR_MIIRD),
112 FTGMAC100_MDIO_TIMEOUT_USEC);
113 if (ret) {
114 pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
115 priv->phydev->dev->name, phy_addr, reg_addr);
116 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800117 }
118
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100119 data = readl(&ftgmac100->phydata);
120
121 return FTGMAC100_PHYDATA_MIIRDATA(data);
Macpaul Lin199c6252010-12-21 16:59:46 +0800122}
123
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100124static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
125 int reg_addr, u16 value)
Macpaul Lin199c6252010-12-21 16:59:46 +0800126{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100127 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100128 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800129 int phycr;
130 int data;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100131 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800132
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100133 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
134 FTGMAC100_PHYCR_PHYAD(phy_addr) |
135 FTGMAC100_PHYCR_REGAD(reg_addr) |
136 FTGMAC100_PHYCR_MIIWR;
Macpaul Lin199c6252010-12-21 16:59:46 +0800137 data = FTGMAC100_PHYDATA_MIIWDATA(value);
138
139 writel(data, &ftgmac100->phydata);
140 writel(phycr, &ftgmac100->phycr);
141
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100142 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
143 !(phycr & FTGMAC100_PHYCR_MIIWR),
144 FTGMAC100_MDIO_TIMEOUT_USEC);
145 if (ret) {
146 pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
147 priv->phydev->dev->name, phy_addr, reg_addr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800148 }
149
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100150 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800151}
152
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100153static int ftgmac100_mdio_init(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800154{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100155 struct ftgmac100_data *priv = dev_get_priv(dev);
156 struct mii_dev *bus;
157 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800158
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100159 bus = mdio_alloc();
160 if (!bus)
161 return -ENOMEM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800162
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100163 bus->read = ftgmac100_mdio_read;
164 bus->write = ftgmac100_mdio_write;
165 bus->priv = priv;
Macpaul Lin199c6252010-12-21 16:59:46 +0800166
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100167 ret = mdio_register_seq(bus, dev->seq);
168 if (ret) {
169 free(bus);
170 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800171 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800172
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100173 priv->bus = bus;
Macpaul Lin199c6252010-12-21 16:59:46 +0800174
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100175 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800176}
177
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100178static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800179{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100180 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100181 struct phy_device *phydev = priv->phydev;
182 u32 maccr;
Macpaul Lin199c6252010-12-21 16:59:46 +0800183
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100184 if (!phydev->link) {
185 dev_err(phydev->dev, "No link\n");
186 return -EREMOTEIO;
187 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800188
189 /* read MAC control register and clear related bits */
190 maccr = readl(&ftgmac100->maccr) &
191 ~(FTGMAC100_MACCR_GIGA_MODE |
192 FTGMAC100_MACCR_FAST_MODE |
193 FTGMAC100_MACCR_FULLDUP);
194
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100195 if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
Macpaul Lin199c6252010-12-21 16:59:46 +0800196 maccr |= FTGMAC100_MACCR_GIGA_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800197
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100198 if (phydev->speed == 100)
Macpaul Lin199c6252010-12-21 16:59:46 +0800199 maccr |= FTGMAC100_MACCR_FAST_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800200
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100201 if (phydev->duplex)
202 maccr |= FTGMAC100_MACCR_FULLDUP;
Macpaul Lin199c6252010-12-21 16:59:46 +0800203
204 /* update MII config into maccr */
205 writel(maccr, &ftgmac100->maccr);
206
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100207 return 0;
208}
209
210static int ftgmac100_phy_init(struct udevice *dev)
211{
212 struct ftgmac100_data *priv = dev_get_priv(dev);
213 struct phy_device *phydev;
214 int ret;
215
216 phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
217 if (!phydev)
218 return -ENODEV;
219
220 phydev->supported &= PHY_GBIT_FEATURES;
221 if (priv->max_speed) {
222 ret = phy_set_supported(phydev, priv->max_speed);
223 if (ret)
224 return ret;
225 }
226 phydev->advertising = phydev->supported;
227 priv->phydev = phydev;
228 phy_config(phydev);
229
230 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800231}
232
233/*
234 * Reset MAC
235 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100236static void ftgmac100_reset(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800237{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100238 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800239
240 debug("%s()\n", __func__);
241
Cédric Le Goatercef951c2018-10-29 07:06:32 +0100242 setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
Macpaul Lin199c6252010-12-21 16:59:46 +0800243
244 while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
245 ;
246}
247
248/*
249 * Set MAC address
250 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100251static int ftgmac100_set_mac(struct ftgmac100_data *priv,
252 const unsigned char *mac)
Macpaul Lin199c6252010-12-21 16:59:46 +0800253{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100254 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800255 unsigned int maddr = mac[0] << 8 | mac[1];
256 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
257
258 debug("%s(%x %x)\n", __func__, maddr, laddr);
259
260 writel(maddr, &ftgmac100->mac_madr);
261 writel(laddr, &ftgmac100->mac_ladr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800262
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100263 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800264}
265
266/*
267 * disable transmitter, receiver
268 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100269static void ftgmac100_stop(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800270{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100271 struct ftgmac100_data *priv = dev_get_priv(dev);
272 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800273
274 debug("%s()\n", __func__);
275
276 writel(0, &ftgmac100->maccr);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100277
278 phy_shutdown(priv->phydev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800279}
280
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100281static int ftgmac100_start(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800282{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100283 struct eth_pdata *plat = dev_get_platdata(dev);
284 struct ftgmac100_data *priv = dev_get_priv(dev);
285 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100286 struct phy_device *phydev = priv->phydev;
Macpaul Lin199c6252010-12-21 16:59:46 +0800287 unsigned int maccr;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100288 ulong start, end;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100289 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800290 int i;
291
292 debug("%s()\n", __func__);
293
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100294 ftgmac100_reset(priv);
295
Macpaul Lin199c6252010-12-21 16:59:46 +0800296 /* set the ethernet address */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100297 ftgmac100_set_mac(priv, plat->enetaddr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800298
299 /* disable all interrupts */
300 writel(0, &ftgmac100->ier);
301
302 /* initialize descriptors */
303 priv->tx_index = 0;
304 priv->rx_index = 0;
305
Macpaul Lin199c6252010-12-21 16:59:46 +0800306 for (i = 0; i < PKTBUFSTX; i++) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100307 priv->txdes[i].txdes3 = 0;
308 priv->txdes[i].txdes0 = 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800309 }
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100310 priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100311
312 start = (ulong)&priv->txdes[0];
313 end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
314 flush_dcache_range(start, end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800315
316 for (i = 0; i < PKTBUFSRX; i++) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100317 priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
318 priv->rxdes[i].rxdes0 = 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800319 }
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100320 priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100321
322 start = (ulong)&priv->rxdes[0];
323 end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
324 flush_dcache_range(start, end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800325
326 /* transmit ring */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100327 writel((u32)priv->txdes, &ftgmac100->txr_badr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800328
329 /* receive ring */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100330 writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800331
332 /* poll receive descriptor automatically */
333 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
334
335 /* config receive buffer size register */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100336 writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800337
338 /* enable transmitter, receiver */
339 maccr = FTGMAC100_MACCR_TXMAC_EN |
340 FTGMAC100_MACCR_RXMAC_EN |
341 FTGMAC100_MACCR_TXDMA_EN |
342 FTGMAC100_MACCR_RXDMA_EN |
343 FTGMAC100_MACCR_CRC_APD |
344 FTGMAC100_MACCR_FULLDUP |
345 FTGMAC100_MACCR_RX_RUNT |
346 FTGMAC100_MACCR_RX_BROADPKT;
347
348 writel(maccr, &ftgmac100->maccr);
349
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100350 ret = phy_startup(phydev);
351 if (ret) {
352 dev_err(phydev->dev, "Could not start PHY\n");
353 return ret;
354 }
355
356 ret = ftgmac100_phy_adjust_link(priv);
357 if (ret) {
358 dev_err(phydev->dev, "Could not adjust link\n");
359 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800360 }
361
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100362 printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
363 phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
364
Macpaul Lin199c6252010-12-21 16:59:46 +0800365 return 0;
366}
367
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100368static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
369{
370 struct ftgmac100_data *priv = dev_get_priv(dev);
371 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100372 ulong des_start = (ulong)curr_des;
373 ulong des_end = des_start +
374 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100375
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100376 /* Release buffer to DMA and flush descriptor */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100377 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100378 flush_dcache_range(des_start, des_end);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100379
380 /* Move to next descriptor */
381 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
382
383 return 0;
384}
385
Macpaul Lin199c6252010-12-21 16:59:46 +0800386/*
387 * Get a data block via Ethernet
388 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100389static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
Macpaul Lin199c6252010-12-21 16:59:46 +0800390{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100391 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100392 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Macpaul Lin199c6252010-12-21 16:59:46 +0800393 unsigned short rxlen;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100394 ulong des_start = (ulong)curr_des;
395 ulong des_end = des_start +
396 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
397 ulong data_start = curr_des->rxdes3;
398 ulong data_end;
Macpaul Lin199c6252010-12-21 16:59:46 +0800399
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100400 invalidate_dcache_range(des_start, des_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800401
402 if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100403 return -EAGAIN;
Macpaul Lin199c6252010-12-21 16:59:46 +0800404
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)) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100410 return -EAGAIN;
Macpaul Lin199c6252010-12-21 16:59:46 +0800411 }
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
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100418 /* Invalidate received data */
419 data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
420 invalidate_dcache_range(data_start, data_end);
421 *packetp = (uchar *)data_start;
Macpaul Lin199c6252010-12-21 16:59:46 +0800422
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100423 return rxlen;
Macpaul Lin199c6252010-12-21 16:59:46 +0800424}
425
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100426static u32 ftgmac100_read_txdesc(const void *desc)
427{
428 const struct ftgmac100_txdes *txdes = desc;
429 ulong des_start = (ulong)txdes;
430 ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
431
432 invalidate_dcache_range(des_start, des_end);
433
434 return txdes->txdes0;
435}
436
437BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
438
Macpaul Lin199c6252010-12-21 16:59:46 +0800439/*
440 * Send a data block via Ethernet
441 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100442static int ftgmac100_send(struct udevice *dev, void *packet, int length)
Macpaul Lin199c6252010-12-21 16:59:46 +0800443{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100444 struct ftgmac100_data *priv = dev_get_priv(dev);
445 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800446 struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100447 ulong des_start = (ulong)curr_des;
448 ulong des_end = des_start +
449 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
450 ulong data_start;
451 ulong data_end;
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100452 int rc;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100453
454 invalidate_dcache_range(des_start, des_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800455
456 if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100457 dev_err(dev, "no TX descriptor available\n");
458 return -EPERM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800459 }
460
461 debug("%s(%x, %x)\n", __func__, (int)packet, length);
462
463 length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
464
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100465 curr_des->txdes3 = (unsigned int)packet;
466
467 /* Flush data to be sent */
468 data_start = curr_des->txdes3;
469 data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
470 flush_dcache_range(data_start, data_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800471
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100472 /* Only one segment on TXBUF */
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100473 curr_des->txdes0 &= priv->txdes0_edotr_mask;
Macpaul Lin199c6252010-12-21 16:59:46 +0800474 curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
475 FTGMAC100_TXDES0_LTS |
476 FTGMAC100_TXDES0_TXBUF_SIZE(length) |
477 FTGMAC100_TXDES0_TXDMA_OWN ;
478
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100479 /* Flush modified buffer descriptor */
480 flush_dcache_range(des_start, des_end);
481
482 /* Start transmit */
Macpaul Lin199c6252010-12-21 16:59:46 +0800483 writel(1, &ftgmac100->txpd);
484
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100485 rc = wait_for_bit_ftgmac100_txdone(curr_des,
486 FTGMAC100_TXDES0_TXDMA_OWN, false,
487 FTGMAC100_TX_TIMEOUT_MS, true);
488 if (rc)
489 return rc;
490
Macpaul Lin199c6252010-12-21 16:59:46 +0800491 debug("%s(): packet sent\n", __func__);
492
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100493 /* Move to next descriptor */
Macpaul Lin199c6252010-12-21 16:59:46 +0800494 priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
495
496 return 0;
497}
498
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100499static int ftgmac100_write_hwaddr(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800500{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100501 struct eth_pdata *pdata = dev_get_platdata(dev);
502 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800503
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100504 return ftgmac100_set_mac(priv, pdata->enetaddr);
505}
Macpaul Lin199c6252010-12-21 16:59:46 +0800506
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100507static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
508{
509 struct eth_pdata *pdata = dev_get_platdata(dev);
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100510 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100511 const char *phy_mode;
Macpaul Lin199c6252010-12-21 16:59:46 +0800512
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100513 pdata->iobase = devfdt_get_addr(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100514 pdata->phy_interface = -1;
515 phy_mode = dev_read_string(dev, "phy-mode");
516 if (phy_mode)
517 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
518 if (pdata->phy_interface == -1) {
519 dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
520 return -EINVAL;
521 }
522
523 pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
524
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100525 if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
526 priv->rxdes0_edorr_mask = BIT(30);
527 priv->txdes0_edotr_mask = BIT(30);
528 } else {
529 priv->rxdes0_edorr_mask = BIT(15);
530 priv->txdes0_edotr_mask = BIT(15);
531 }
532
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100533 return clk_get_bulk(dev, &priv->clks);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100534}
Macpaul Lin199c6252010-12-21 16:59:46 +0800535
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100536static int ftgmac100_probe(struct udevice *dev)
537{
538 struct eth_pdata *pdata = dev_get_platdata(dev);
539 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100540 int ret;
Macpaul Linc56c5a32011-09-20 19:54:32 +0000541
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100542 priv->iobase = (struct ftgmac100 *)pdata->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100543 priv->phy_mode = pdata->phy_interface;
544 priv->max_speed = pdata->max_speed;
545 priv->phy_addr = 0;
546
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100547 ret = clk_enable_bulk(&priv->clks);
548 if (ret)
549 goto out;
550
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100551 ret = ftgmac100_mdio_init(dev);
552 if (ret) {
553 dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
554 goto out;
555 }
556
557 ret = ftgmac100_phy_init(dev);
558 if (ret) {
559 dev_err(dev, "Failed to initialize PHY: %d\n", ret);
560 goto out;
561 }
562
563out:
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100564 if (ret)
565 clk_release_bulk(&priv->clks);
566
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100567 return ret;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100568}
Macpaul Lin199c6252010-12-21 16:59:46 +0800569
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100570static int ftgmac100_remove(struct udevice *dev)
571{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100572 struct ftgmac100_data *priv = dev_get_priv(dev);
573
574 free(priv->phydev);
575 mdio_unregister(priv->bus);
576 mdio_free(priv->bus);
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100577 clk_release_bulk(&priv->clks);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100578
Macpaul Lin199c6252010-12-21 16:59:46 +0800579 return 0;
580}
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100581
582static const struct eth_ops ftgmac100_ops = {
583 .start = ftgmac100_start,
584 .send = ftgmac100_send,
585 .recv = ftgmac100_recv,
586 .stop = ftgmac100_stop,
587 .free_pkt = ftgmac100_free_pkt,
588 .write_hwaddr = ftgmac100_write_hwaddr,
589};
590
591static const struct udevice_id ftgmac100_ids[] = {
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100592 { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
593 { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100594 { }
595};
596
597U_BOOT_DRIVER(ftgmac100) = {
598 .name = "ftgmac100",
599 .id = UCLASS_ETH,
600 .of_match = ftgmac100_ids,
601 .ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
602 .probe = ftgmac100_probe,
603 .remove = ftgmac100_remove,
604 .ops = &ftgmac100_ops,
605 .priv_auto_alloc_size = sizeof(struct ftgmac100_data),
606 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
607 .flags = DM_FLAG_ALLOC_PRIV_DMA,
608};