blob: b6e9526c3b9f84afcdfcfc5ab21ef268b70f244d [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
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <common.h>
Cédric Le Goater6afa3f12018-10-29 07:06:36 +010015#include <clk.h>
Simon Glass63334482019-11-14 12:57:39 -070016#include <cpu_func.h>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010017#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060018#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070019#include <malloc.h>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010020#include <miiphy.h>
Macpaul Lin199c6252010-12-21 16:59:46 +080021#include <net.h>
Cédric Le Goater9bcb6652018-10-29 07:06:35 +010022#include <wait_bit.h>
Simon Glass274e0b02020-05-10 11:39:56 -060023#include <asm/cache.h>
Simon Glass9bc15642020-02-03 07:36:16 -070024#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060025#include <linux/bitops.h>
Cédric Le Goater38b33e92018-10-29 07:06:31 +010026#include <linux/io.h>
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010027#include <linux/iopoll.h>
Macpaul Lin199c6252010-12-21 16:59:46 +080028
29#include "ftgmac100.h"
30
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010031/* Min frame ethernet frame size without FCS */
32#define ETH_ZLEN 60
Macpaul Lin199c6252010-12-21 16:59:46 +080033
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010034/* Receive Buffer Size Register - HW default is 0x640 */
35#define FTGMAC100_RBSR_DEFAULT 0x640
Macpaul Lin199c6252010-12-21 16:59:46 +080036
37/* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
38#define PKTBUFSTX 4 /* must be power of 2 */
39
Cédric Le Goater9bcb6652018-10-29 07:06:35 +010040/* Timeout for transmit */
41#define FTGMAC100_TX_TIMEOUT_MS 1000
42
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010043/* Timeout for a mdio read/write operation */
44#define FTGMAC100_MDIO_TIMEOUT_USEC 10000
45
46/*
47 * MDC clock cycle threshold
48 *
49 * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
50 */
51#define MDC_CYCTHR 0x34
52
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010053/*
54 * ftgmac100 model variants
55 */
56enum ftgmac100_model {
57 FTGMAC100_MODEL_FARADAY,
58 FTGMAC100_MODEL_ASPEED,
59};
60
Cédric Le Goater38b33e92018-10-29 07:06:31 +010061/**
62 * struct ftgmac100_data - private data for the FTGMAC100 driver
63 *
64 * @iobase: The base address of the hardware registers
65 * @txdes: The array of transmit descriptors
66 * @rxdes: The array of receive descriptors
67 * @tx_index: Transmit descriptor index in @txdes
68 * @rx_index: Receive descriptor index in @rxdes
69 * @phy_addr: The PHY interface address to use
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010070 * @phydev: The PHY device backing the MAC
71 * @bus: The mdio bus
72 * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
73 * @max_speed: Maximum speed of Ethernet connection supported by MAC
Cédric Le Goater6afa3f12018-10-29 07:06:36 +010074 * @clks: The bulk of clocks assigned to the device in the DT
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010075 * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
76 * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
Cédric Le Goater38b33e92018-10-29 07:06:31 +010077 */
Macpaul Lin199c6252010-12-21 16:59:46 +080078struct ftgmac100_data {
Cédric Le Goater38b33e92018-10-29 07:06:31 +010079 struct ftgmac100 *iobase;
80
Cédric Le Goater0404e9f2019-11-28 13:37:04 +010081 struct ftgmac100_txdes txdes[PKTBUFSTX] __aligned(ARCH_DMA_MINALIGN);
82 struct ftgmac100_rxdes rxdes[PKTBUFSRX] __aligned(ARCH_DMA_MINALIGN);
Macpaul Lin199c6252010-12-21 16:59:46 +080083 int tx_index;
84 int rx_index;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010085
86 u32 phy_addr;
87 struct phy_device *phydev;
88 struct mii_dev *bus;
89 u32 phy_mode;
90 u32 max_speed;
Cédric Le Goater6afa3f12018-10-29 07:06:36 +010091
92 struct clk_bulk clks;
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010093
94 /* End of RX/TX ring buffer bits. Depend on model */
95 u32 rxdes0_edorr_mask;
96 u32 txdes0_edotr_mask;
Macpaul Lin199c6252010-12-21 16:59:46 +080097};
98
99/*
100 * struct mii_bus functions
101 */
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100102static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
103 int reg_addr)
Macpaul Lin199c6252010-12-21 16:59:46 +0800104{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100105 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100106 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800107 int phycr;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100108 int data;
109 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800110
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100111 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
112 FTGMAC100_PHYCR_PHYAD(phy_addr) |
113 FTGMAC100_PHYCR_REGAD(reg_addr) |
114 FTGMAC100_PHYCR_MIIRD;
Macpaul Lin199c6252010-12-21 16:59:46 +0800115 writel(phycr, &ftgmac100->phycr);
116
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100117 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
118 !(phycr & FTGMAC100_PHYCR_MIIRD),
119 FTGMAC100_MDIO_TIMEOUT_USEC);
120 if (ret) {
121 pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
122 priv->phydev->dev->name, phy_addr, reg_addr);
123 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800124 }
125
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100126 data = readl(&ftgmac100->phydata);
127
128 return FTGMAC100_PHYDATA_MIIRDATA(data);
Macpaul Lin199c6252010-12-21 16:59:46 +0800129}
130
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100131static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
132 int reg_addr, u16 value)
Macpaul Lin199c6252010-12-21 16:59:46 +0800133{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100134 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100135 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800136 int phycr;
137 int data;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100138 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800139
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100140 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
141 FTGMAC100_PHYCR_PHYAD(phy_addr) |
142 FTGMAC100_PHYCR_REGAD(reg_addr) |
143 FTGMAC100_PHYCR_MIIWR;
Macpaul Lin199c6252010-12-21 16:59:46 +0800144 data = FTGMAC100_PHYDATA_MIIWDATA(value);
145
146 writel(data, &ftgmac100->phydata);
147 writel(phycr, &ftgmac100->phycr);
148
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100149 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
150 !(phycr & FTGMAC100_PHYCR_MIIWR),
151 FTGMAC100_MDIO_TIMEOUT_USEC);
152 if (ret) {
153 pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
154 priv->phydev->dev->name, phy_addr, reg_addr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800155 }
156
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100157 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800158}
159
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100160static int ftgmac100_mdio_init(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800161{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100162 struct ftgmac100_data *priv = dev_get_priv(dev);
163 struct mii_dev *bus;
164 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800165
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100166 bus = mdio_alloc();
167 if (!bus)
168 return -ENOMEM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800169
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100170 bus->read = ftgmac100_mdio_read;
171 bus->write = ftgmac100_mdio_write;
172 bus->priv = priv;
Macpaul Lin199c6252010-12-21 16:59:46 +0800173
Simon Glass75e534b2020-12-16 21:20:07 -0700174 ret = mdio_register_seq(bus, dev_seq(dev));
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100175 if (ret) {
176 free(bus);
177 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800178 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800179
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100180 priv->bus = bus;
Macpaul Lin199c6252010-12-21 16:59:46 +0800181
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100182 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800183}
184
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100185static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800186{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100187 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100188 struct phy_device *phydev = priv->phydev;
189 u32 maccr;
Macpaul Lin199c6252010-12-21 16:59:46 +0800190
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100191 if (!phydev->link) {
192 dev_err(phydev->dev, "No link\n");
193 return -EREMOTEIO;
194 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800195
196 /* read MAC control register and clear related bits */
197 maccr = readl(&ftgmac100->maccr) &
198 ~(FTGMAC100_MACCR_GIGA_MODE |
199 FTGMAC100_MACCR_FAST_MODE |
200 FTGMAC100_MACCR_FULLDUP);
201
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100202 if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
Macpaul Lin199c6252010-12-21 16:59:46 +0800203 maccr |= FTGMAC100_MACCR_GIGA_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800204
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100205 if (phydev->speed == 100)
Macpaul Lin199c6252010-12-21 16:59:46 +0800206 maccr |= FTGMAC100_MACCR_FAST_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800207
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100208 if (phydev->duplex)
209 maccr |= FTGMAC100_MACCR_FULLDUP;
Macpaul Lin199c6252010-12-21 16:59:46 +0800210
211 /* update MII config into maccr */
212 writel(maccr, &ftgmac100->maccr);
213
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100214 return 0;
215}
216
217static int ftgmac100_phy_init(struct udevice *dev)
218{
219 struct ftgmac100_data *priv = dev_get_priv(dev);
220 struct phy_device *phydev;
221 int ret;
222
Dylan Hung2bec3722021-12-09 10:12:24 +0800223 if (IS_ENABLED(CONFIG_DM_MDIO))
224 phydev = dm_eth_phy_connect(dev);
225 else
226 phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
227
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100228 if (!phydev)
229 return -ENODEV;
230
231 phydev->supported &= PHY_GBIT_FEATURES;
232 if (priv->max_speed) {
233 ret = phy_set_supported(phydev, priv->max_speed);
234 if (ret)
235 return ret;
236 }
237 phydev->advertising = phydev->supported;
238 priv->phydev = phydev;
239 phy_config(phydev);
240
241 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800242}
243
244/*
245 * Reset MAC
246 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100247static void ftgmac100_reset(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800248{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100249 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800250
251 debug("%s()\n", __func__);
252
Cédric Le Goatercef951c2018-10-29 07:06:32 +0100253 setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
Macpaul Lin199c6252010-12-21 16:59:46 +0800254
255 while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
256 ;
257}
258
259/*
260 * Set MAC address
261 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100262static int ftgmac100_set_mac(struct ftgmac100_data *priv,
263 const unsigned char *mac)
Macpaul Lin199c6252010-12-21 16:59:46 +0800264{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100265 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800266 unsigned int maddr = mac[0] << 8 | mac[1];
267 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
268
269 debug("%s(%x %x)\n", __func__, maddr, laddr);
270
271 writel(maddr, &ftgmac100->mac_madr);
272 writel(laddr, &ftgmac100->mac_ladr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800273
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100274 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800275}
276
277/*
Hongwei Zhang55ae5902020-12-10 18:11:09 -0500278 * Get MAC address
279 */
280static int ftgmac100_get_mac(struct ftgmac100_data *priv,
281 unsigned char *mac)
282{
283 struct ftgmac100 *ftgmac100 = priv->iobase;
284 unsigned int maddr = readl(&ftgmac100->mac_madr);
285 unsigned int laddr = readl(&ftgmac100->mac_ladr);
286
287 debug("%s(%x %x)\n", __func__, maddr, laddr);
288
289 mac[0] = (maddr >> 8) & 0xff;
290 mac[1] = maddr & 0xff;
291 mac[2] = (laddr >> 24) & 0xff;
292 mac[3] = (laddr >> 16) & 0xff;
293 mac[4] = (laddr >> 8) & 0xff;
294 mac[5] = laddr & 0xff;
295
296 return 0;
297}
298
299/*
Macpaul Lin199c6252010-12-21 16:59:46 +0800300 * disable transmitter, receiver
301 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100302static void ftgmac100_stop(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800303{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100304 struct ftgmac100_data *priv = dev_get_priv(dev);
305 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800306
307 debug("%s()\n", __func__);
308
309 writel(0, &ftgmac100->maccr);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100310
311 phy_shutdown(priv->phydev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800312}
313
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100314static int ftgmac100_start(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800315{
Simon Glassfa20e932020-12-03 16:55:20 -0700316 struct eth_pdata *plat = dev_get_plat(dev);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100317 struct ftgmac100_data *priv = dev_get_priv(dev);
318 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100319 struct phy_device *phydev = priv->phydev;
Macpaul Lin199c6252010-12-21 16:59:46 +0800320 unsigned int maccr;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100321 ulong start, end;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100322 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800323 int i;
324
325 debug("%s()\n", __func__);
326
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100327 ftgmac100_reset(priv);
328
Macpaul Lin199c6252010-12-21 16:59:46 +0800329 /* set the ethernet address */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100330 ftgmac100_set_mac(priv, plat->enetaddr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800331
332 /* disable all interrupts */
333 writel(0, &ftgmac100->ier);
334
335 /* initialize descriptors */
336 priv->tx_index = 0;
337 priv->rx_index = 0;
338
Macpaul Lin199c6252010-12-21 16:59:46 +0800339 for (i = 0; i < PKTBUFSTX; i++) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100340 priv->txdes[i].txdes3 = 0;
341 priv->txdes[i].txdes0 = 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800342 }
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100343 priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100344
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100345 start = ((ulong)&priv->txdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100346 end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
347 flush_dcache_range(start, end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800348
349 for (i = 0; i < PKTBUFSRX; i++) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100350 priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
351 priv->rxdes[i].rxdes0 = 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800352 }
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100353 priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100354
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100355 start = ((ulong)&priv->rxdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100356 end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
357 flush_dcache_range(start, end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800358
359 /* transmit ring */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100360 writel((u32)priv->txdes, &ftgmac100->txr_badr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800361
362 /* receive ring */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100363 writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800364
365 /* poll receive descriptor automatically */
366 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
367
368 /* config receive buffer size register */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100369 writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800370
371 /* enable transmitter, receiver */
372 maccr = FTGMAC100_MACCR_TXMAC_EN |
373 FTGMAC100_MACCR_RXMAC_EN |
374 FTGMAC100_MACCR_TXDMA_EN |
375 FTGMAC100_MACCR_RXDMA_EN |
376 FTGMAC100_MACCR_CRC_APD |
377 FTGMAC100_MACCR_FULLDUP |
378 FTGMAC100_MACCR_RX_RUNT |
379 FTGMAC100_MACCR_RX_BROADPKT;
380
381 writel(maccr, &ftgmac100->maccr);
382
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100383 ret = phy_startup(phydev);
384 if (ret) {
385 dev_err(phydev->dev, "Could not start PHY\n");
386 return ret;
387 }
388
389 ret = ftgmac100_phy_adjust_link(priv);
390 if (ret) {
391 dev_err(phydev->dev, "Could not adjust link\n");
392 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800393 }
394
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100395 printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
396 phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
397
Macpaul Lin199c6252010-12-21 16:59:46 +0800398 return 0;
399}
400
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100401static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
402{
403 struct ftgmac100_data *priv = dev_get_priv(dev);
404 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100405 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100406 ulong des_end = des_start +
407 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100408
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100409 /* Release buffer to DMA and flush descriptor */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100410 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100411 flush_dcache_range(des_start, des_end);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100412
413 /* Move to next descriptor */
414 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
415
416 return 0;
417}
418
Macpaul Lin199c6252010-12-21 16:59:46 +0800419/*
420 * Get a data block via Ethernet
421 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100422static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
Macpaul Lin199c6252010-12-21 16:59:46 +0800423{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100424 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100425 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Macpaul Lin199c6252010-12-21 16:59:46 +0800426 unsigned short rxlen;
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100427 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100428 ulong des_end = des_start +
429 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
430 ulong data_start = curr_des->rxdes3;
431 ulong data_end;
Macpaul Lin199c6252010-12-21 16:59:46 +0800432
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100433 invalidate_dcache_range(des_start, des_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800434
435 if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100436 return -EAGAIN;
Macpaul Lin199c6252010-12-21 16:59:46 +0800437
438 if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
439 FTGMAC100_RXDES0_CRC_ERR |
440 FTGMAC100_RXDES0_FTL |
441 FTGMAC100_RXDES0_RUNT |
442 FTGMAC100_RXDES0_RX_ODD_NB)) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100443 return -EAGAIN;
Macpaul Lin199c6252010-12-21 16:59:46 +0800444 }
445
446 rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
447
448 debug("%s(): RX buffer %d, %x received\n",
449 __func__, priv->rx_index, rxlen);
450
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100451 /* Invalidate received data */
452 data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
453 invalidate_dcache_range(data_start, data_end);
454 *packetp = (uchar *)data_start;
Macpaul Lin199c6252010-12-21 16:59:46 +0800455
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100456 return rxlen;
Macpaul Lin199c6252010-12-21 16:59:46 +0800457}
458
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100459static u32 ftgmac100_read_txdesc(const void *desc)
460{
461 const struct ftgmac100_txdes *txdes = desc;
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100462 ulong des_start = ((ulong)txdes) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100463 ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
464
465 invalidate_dcache_range(des_start, des_end);
466
467 return txdes->txdes0;
468}
469
470BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
471
Macpaul Lin199c6252010-12-21 16:59:46 +0800472/*
473 * Send a data block via Ethernet
474 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100475static int ftgmac100_send(struct udevice *dev, void *packet, int length)
Macpaul Lin199c6252010-12-21 16:59:46 +0800476{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100477 struct ftgmac100_data *priv = dev_get_priv(dev);
478 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800479 struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100480 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100481 ulong des_end = des_start +
482 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
483 ulong data_start;
484 ulong data_end;
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100485 int rc;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100486
487 invalidate_dcache_range(des_start, des_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800488
489 if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100490 dev_err(dev, "no TX descriptor available\n");
491 return -EPERM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800492 }
493
494 debug("%s(%x, %x)\n", __func__, (int)packet, length);
495
496 length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
497
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100498 curr_des->txdes3 = (unsigned int)packet;
499
500 /* Flush data to be sent */
501 data_start = curr_des->txdes3;
502 data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
503 flush_dcache_range(data_start, data_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800504
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100505 /* Only one segment on TXBUF */
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100506 curr_des->txdes0 &= priv->txdes0_edotr_mask;
Macpaul Lin199c6252010-12-21 16:59:46 +0800507 curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
508 FTGMAC100_TXDES0_LTS |
509 FTGMAC100_TXDES0_TXBUF_SIZE(length) |
510 FTGMAC100_TXDES0_TXDMA_OWN ;
511
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100512 /* Flush modified buffer descriptor */
513 flush_dcache_range(des_start, des_end);
514
515 /* Start transmit */
Macpaul Lin199c6252010-12-21 16:59:46 +0800516 writel(1, &ftgmac100->txpd);
517
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100518 rc = wait_for_bit_ftgmac100_txdone(curr_des,
519 FTGMAC100_TXDES0_TXDMA_OWN, false,
520 FTGMAC100_TX_TIMEOUT_MS, true);
521 if (rc)
522 return rc;
523
Macpaul Lin199c6252010-12-21 16:59:46 +0800524 debug("%s(): packet sent\n", __func__);
525
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100526 /* Move to next descriptor */
Macpaul Lin199c6252010-12-21 16:59:46 +0800527 priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
528
529 return 0;
530}
531
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100532static int ftgmac100_write_hwaddr(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800533{
Simon Glassfa20e932020-12-03 16:55:20 -0700534 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100535 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800536
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100537 return ftgmac100_set_mac(priv, pdata->enetaddr);
538}
Macpaul Lin199c6252010-12-21 16:59:46 +0800539
Hongwei Zhang55ae5902020-12-10 18:11:09 -0500540static int ftgmac_read_hwaddr(struct udevice *dev)
541{
542 struct eth_pdata *pdata = dev_get_plat(dev);
543 struct ftgmac100_data *priv = dev_get_priv(dev);
544
545 return ftgmac100_get_mac(priv, pdata->enetaddr);
546}
547
Simon Glassaad29ae2020-12-03 16:55:21 -0700548static int ftgmac100_of_to_plat(struct udevice *dev)
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100549{
Simon Glassfa20e932020-12-03 16:55:20 -0700550 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100551 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100552 const char *phy_mode;
Macpaul Lin199c6252010-12-21 16:59:46 +0800553
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900554 pdata->iobase = dev_read_addr(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100555 pdata->phy_interface = -1;
556 phy_mode = dev_read_string(dev, "phy-mode");
557 if (phy_mode)
558 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
559 if (pdata->phy_interface == -1) {
560 dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
561 return -EINVAL;
562 }
563
564 pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
565
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100566 if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
567 priv->rxdes0_edorr_mask = BIT(30);
568 priv->txdes0_edotr_mask = BIT(30);
569 } else {
570 priv->rxdes0_edorr_mask = BIT(15);
571 priv->txdes0_edotr_mask = BIT(15);
572 }
573
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100574 return clk_get_bulk(dev, &priv->clks);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100575}
Macpaul Lin199c6252010-12-21 16:59:46 +0800576
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100577static int ftgmac100_probe(struct udevice *dev)
578{
Simon Glassfa20e932020-12-03 16:55:20 -0700579 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100580 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100581 int ret;
Macpaul Linc56c5a32011-09-20 19:54:32 +0000582
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100583 priv->iobase = (struct ftgmac100 *)pdata->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100584 priv->phy_mode = pdata->phy_interface;
585 priv->max_speed = pdata->max_speed;
586 priv->phy_addr = 0;
587
Thirupathaiah Annapureddy22bb3772020-08-17 17:08:26 -0700588#ifdef CONFIG_PHY_ADDR
589 priv->phy_addr = CONFIG_PHY_ADDR;
590#endif
591
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100592 ret = clk_enable_bulk(&priv->clks);
593 if (ret)
594 goto out;
595
Dylan Hung2bec3722021-12-09 10:12:24 +0800596 /*
597 * If DM MDIO is enabled, the MDIO bus will be initialized later in
598 * dm_eth_phy_connect
599 */
600 if (!IS_ENABLED(CONFIG_DM_MDIO)) {
601 ret = ftgmac100_mdio_init(dev);
602 if (ret) {
603 dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
604 goto out;
605 }
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100606 }
607
608 ret = ftgmac100_phy_init(dev);
609 if (ret) {
610 dev_err(dev, "Failed to initialize PHY: %d\n", ret);
611 goto out;
612 }
613
Hongwei Zhang55ae5902020-12-10 18:11:09 -0500614 ftgmac_read_hwaddr(dev);
615
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100616out:
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100617 if (ret)
618 clk_release_bulk(&priv->clks);
619
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100620 return ret;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100621}
Macpaul Lin199c6252010-12-21 16:59:46 +0800622
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100623static int ftgmac100_remove(struct udevice *dev)
624{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100625 struct ftgmac100_data *priv = dev_get_priv(dev);
626
627 free(priv->phydev);
628 mdio_unregister(priv->bus);
629 mdio_free(priv->bus);
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100630 clk_release_bulk(&priv->clks);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100631
Macpaul Lin199c6252010-12-21 16:59:46 +0800632 return 0;
633}
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100634
635static const struct eth_ops ftgmac100_ops = {
636 .start = ftgmac100_start,
637 .send = ftgmac100_send,
638 .recv = ftgmac100_recv,
639 .stop = ftgmac100_stop,
640 .free_pkt = ftgmac100_free_pkt,
641 .write_hwaddr = ftgmac100_write_hwaddr,
642};
643
644static const struct udevice_id ftgmac100_ids[] = {
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100645 { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
646 { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100647 { }
648};
649
650U_BOOT_DRIVER(ftgmac100) = {
651 .name = "ftgmac100",
652 .id = UCLASS_ETH,
653 .of_match = ftgmac100_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700654 .of_to_plat = ftgmac100_of_to_plat,
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100655 .probe = ftgmac100_probe,
656 .remove = ftgmac100_remove,
657 .ops = &ftgmac100_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700658 .priv_auto = sizeof(struct ftgmac100_data),
Simon Glass71fa5b42020-12-03 16:55:18 -0700659 .plat_auto = sizeof(struct eth_pdata),
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100660 .flags = DM_FLAG_ALLOC_PRIV_DMA,
661};