blob: 78779d7d60b916b9b01059420b06c8c0297ad6bd [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Macpaul Linb3dbf4a52010-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 Goaterf95de0b2018-10-29 07:06:31 +010010 *
11 * Copyright (C) 2018, IBM Corporation.
Macpaul Linb3dbf4a52010-12-21 16:59:46 +080012 */
13
Simon Glassf7ae49f2020-05-10 11:40:05 -060014#include <common.h>
Cédric Le Goater1c0c61e2018-10-29 07:06:36 +010015#include <clk.h>
Simon Glass1eb69ae2019-11-14 12:57:39 -070016#include <cpu_func.h>
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +010017#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060018#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070019#include <malloc.h>
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +010020#include <miiphy.h>
Macpaul Linb3dbf4a52010-12-21 16:59:46 +080021#include <net.h>
Cédric Le Goaterd0e0b842018-10-29 07:06:35 +010022#include <wait_bit.h>
Simon Glass90526e92020-05-10 11:39:56 -060023#include <asm/cache.h>
Simon Glass336d4612020-02-03 07:36:16 -070024#include <dm/device_compat.h>
Simon Glasscd93d622020-05-10 11:40:13 -060025#include <linux/bitops.h>
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +010026#include <linux/io.h>
Cédric Le Goater538e75d2018-10-29 07:06:33 +010027#include <linux/iopoll.h>
Macpaul Linb3dbf4a52010-12-21 16:59:46 +080028
29#include "ftgmac100.h"
30
Cédric Le Goatere7668492018-10-29 07:06:34 +010031/* Min frame ethernet frame size without FCS */
32#define ETH_ZLEN 60
Macpaul Linb3dbf4a52010-12-21 16:59:46 +080033
Cédric Le Goatere7668492018-10-29 07:06:34 +010034/* Receive Buffer Size Register - HW default is 0x640 */
35#define FTGMAC100_RBSR_DEFAULT 0x640
Macpaul Linb3dbf4a52010-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 Goaterd0e0b842018-10-29 07:06:35 +010040/* Timeout for transmit */
41#define FTGMAC100_TX_TIMEOUT_MS 1000
42
Cédric Le Goater538e75d2018-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 Goatere6ddacc2018-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 Goaterf95de0b2018-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 Goater538e75d2018-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 Goater1c0c61e2018-10-29 07:06:36 +010074 * @clks: The bulk of clocks assigned to the device in the DT
Cédric Le Goatere6ddacc2018-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 Goaterf95de0b2018-10-29 07:06:31 +010077 */
Macpaul Linb3dbf4a52010-12-21 16:59:46 +080078struct ftgmac100_data {
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +010079 struct ftgmac100 *iobase;
80
Cédric Le Goater08b3e902019-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 Linb3dbf4a52010-12-21 16:59:46 +080083 int tx_index;
84 int rx_index;
Cédric Le Goater538e75d2018-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 Goater1c0c61e2018-10-29 07:06:36 +010091
92 struct clk_bulk clks;
Cédric Le Goatere6ddacc2018-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 Linb3dbf4a52010-12-21 16:59:46 +080097};
98
99/*
100 * struct mii_bus functions
101 */
Cédric Le Goater538e75d2018-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 Linb3dbf4a52010-12-21 16:59:46 +0800104{
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100105 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100106 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800107 int phycr;
108 int data;
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100109 int ret;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800110
Cédric Le Goater538e75d2018-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;
115 writel(phycr, &ftgmac100->phycr);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800116
Cédric Le Goater538e75d2018-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;
124 }
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800125
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100126 data = readl(&ftgmac100->phydata);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800127
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100128 return FTGMAC100_PHYDATA_MIIRDATA(data);
129}
130
131static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
132 int reg_addr, u16 value)
133{
134 struct ftgmac100_data *priv = bus->priv;
135 struct ftgmac100 *ftgmac100 = priv->iobase;
136 int phycr;
137 int data;
138 int ret;
139
140 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
141 FTGMAC100_PHYCR_PHYAD(phy_addr) |
142 FTGMAC100_PHYCR_REGAD(reg_addr) |
143 FTGMAC100_PHYCR_MIIWR;
Macpaul Linb3dbf4a52010-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 Goater538e75d2018-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 Linb3dbf4a52010-12-21 16:59:46 +0800155 }
156
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100157 return ret;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800158}
159
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100160static int ftgmac100_mdio_init(struct udevice *dev)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800161{
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100162 struct ftgmac100_data *priv = dev_get_priv(dev);
163 struct mii_dev *bus;
164 int ret;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800165
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100166 bus = mdio_alloc();
167 if (!bus)
168 return -ENOMEM;
169
170 bus->read = ftgmac100_mdio_read;
171 bus->write = ftgmac100_mdio_write;
172 bus->priv = priv;
173
Simon Glass8b85dfc2020-12-16 21:20:07 -0700174 ret = mdio_register_seq(bus, dev_seq(dev));
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100175 if (ret) {
176 free(bus);
177 return ret;
178 }
179
180 priv->bus = bus;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800181
182 return 0;
183}
184
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100185static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800186{
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100187 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100188 struct phy_device *phydev = priv->phydev;
189 u32 maccr;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800190
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100191 if (!phydev->link) {
192 dev_err(phydev->dev, "No link\n");
193 return -EREMOTEIO;
194 }
Macpaul Linb3dbf4a52010-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 Goater538e75d2018-10-29 07:06:33 +0100202 if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800203 maccr |= FTGMAC100_MACCR_GIGA_MODE;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800204
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100205 if (phydev->speed == 100)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800206 maccr |= FTGMAC100_MACCR_FAST_MODE;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800207
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100208 if (phydev->duplex)
209 maccr |= FTGMAC100_MACCR_FULLDUP;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800210
211 /* update MII config into maccr */
212 writel(maccr, &ftgmac100->maccr);
213
Cédric Le Goater538e75d2018-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 Hung9c27ce72021-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 Goater538e75d2018-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 Linb3dbf4a52010-12-21 16:59:46 +0800242}
243
244/*
245 * Reset MAC
246 */
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100247static void ftgmac100_reset(struct ftgmac100_data *priv)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800248{
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100249 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800250
251 debug("%s()\n", __func__);
252
Cédric Le Goater591ffd92018-10-29 07:06:32 +0100253 setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
Macpaul Linb3dbf4a52010-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 Goaterf95de0b2018-10-29 07:06:31 +0100262static int ftgmac100_set_mac(struct ftgmac100_data *priv,
263 const unsigned char *mac)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800264{
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100265 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Linb3dbf4a52010-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 Linb3dbf4a52010-12-21 16:59:46 +0800273
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100274 return 0;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800275}
276
277/*
Hongwei Zhang0be3d1f2020-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 Linb3dbf4a52010-12-21 16:59:46 +0800300 * disable transmitter, receiver
301 */
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100302static void ftgmac100_stop(struct udevice *dev)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800303{
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100304 struct ftgmac100_data *priv = dev_get_priv(dev);
305 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800306
307 debug("%s()\n", __func__);
308
309 writel(0, &ftgmac100->maccr);
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100310
311 phy_shutdown(priv->phydev);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800312}
313
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100314static int ftgmac100_start(struct udevice *dev)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800315{
Simon Glassc69cda22020-12-03 16:55:20 -0700316 struct eth_pdata *plat = dev_get_plat(dev);
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100317 struct ftgmac100_data *priv = dev_get_priv(dev);
318 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100319 struct phy_device *phydev = priv->phydev;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800320 unsigned int maccr;
Cédric Le Goatere7668492018-10-29 07:06:34 +0100321 ulong start, end;
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100322 int ret;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800323 int i;
324
325 debug("%s()\n", __func__);
326
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100327 ftgmac100_reset(priv);
328
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800329 /* set the ethernet address */
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100330 ftgmac100_set_mac(priv, plat->enetaddr);
Macpaul Linb3dbf4a52010-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 Linb3dbf4a52010-12-21 16:59:46 +0800339 for (i = 0; i < PKTBUFSTX; i++) {
Cédric Le Goatere7668492018-10-29 07:06:34 +0100340 priv->txdes[i].txdes3 = 0;
341 priv->txdes[i].txdes0 = 0;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800342 }
Cédric Le Goatere6ddacc2018-10-29 07:06:38 +0100343 priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
Cédric Le Goatere7668492018-10-29 07:06:34 +0100344
Cédric Le Goater08b3e902019-11-28 13:37:04 +0100345 start = ((ulong)&priv->txdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goatere7668492018-10-29 07:06:34 +0100346 end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
347 flush_dcache_range(start, end);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800348
349 for (i = 0; i < PKTBUFSRX; i++) {
Cédric Le Goatere7668492018-10-29 07:06:34 +0100350 priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
351 priv->rxdes[i].rxdes0 = 0;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800352 }
Cédric Le Goatere6ddacc2018-10-29 07:06:38 +0100353 priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
Cédric Le Goatere7668492018-10-29 07:06:34 +0100354
Cédric Le Goater08b3e902019-11-28 13:37:04 +0100355 start = ((ulong)&priv->rxdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goatere7668492018-10-29 07:06:34 +0100356 end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
357 flush_dcache_range(start, end);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800358
359 /* transmit ring */
Cédric Le Goatere7668492018-10-29 07:06:34 +0100360 writel((u32)priv->txdes, &ftgmac100->txr_badr);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800361
362 /* receive ring */
Cédric Le Goatere7668492018-10-29 07:06:34 +0100363 writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
Macpaul Linb3dbf4a52010-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 Goatere7668492018-10-29 07:06:34 +0100369 writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
Macpaul Linb3dbf4a52010-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 Goater538e75d2018-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;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800387 }
388
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100389 ret = ftgmac100_phy_adjust_link(priv);
390 if (ret) {
391 dev_err(phydev->dev, "Could not adjust link\n");
392 return ret;
393 }
394
395 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 Linb3dbf4a52010-12-21 16:59:46 +0800398 return 0;
399}
400
Cédric Le Goaterf95de0b2018-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 Goater08b3e902019-11-28 13:37:04 +0100405 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goatere7668492018-10-29 07:06:34 +0100406 ulong des_end = des_start +
407 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100408
Cédric Le Goatere7668492018-10-29 07:06:34 +0100409 /* Release buffer to DMA and flush descriptor */
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100410 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
Cédric Le Goatere7668492018-10-29 07:06:34 +0100411 flush_dcache_range(des_start, des_end);
Cédric Le Goaterf95de0b2018-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 Linb3dbf4a52010-12-21 16:59:46 +0800419/*
420 * Get a data block via Ethernet
421 */
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100422static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800423{
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100424 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goatere7668492018-10-29 07:06:34 +0100425 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800426 unsigned short rxlen;
Cédric Le Goater08b3e902019-11-28 13:37:04 +0100427 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goatere7668492018-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 Linb3dbf4a52010-12-21 16:59:46 +0800432
Cédric Le Goatere7668492018-10-29 07:06:34 +0100433 invalidate_dcache_range(des_start, des_end);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800434
435 if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
Cédric Le Goatere7668492018-10-29 07:06:34 +0100436 return -EAGAIN;
Macpaul Linb3dbf4a52010-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 Goatere7668492018-10-29 07:06:34 +0100443 return -EAGAIN;
Macpaul Linb3dbf4a52010-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 Goatere7668492018-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;
Kuo-Jung Sua8f9cd12013-05-07 14:33:51 +0800455
Cédric Le Goatere7668492018-10-29 07:06:34 +0100456 return rxlen;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800457}
458
Cédric Le Goaterd0e0b842018-10-29 07:06:35 +0100459static u32 ftgmac100_read_txdesc(const void *desc)
460{
461 const struct ftgmac100_txdes *txdes = desc;
Cédric Le Goater08b3e902019-11-28 13:37:04 +0100462 ulong des_start = ((ulong)txdes) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goaterd0e0b842018-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 Linb3dbf4a52010-12-21 16:59:46 +0800472/*
473 * Send a data block via Ethernet
474 */
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100475static int ftgmac100_send(struct udevice *dev, void *packet, int length)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800476{
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100477 struct ftgmac100_data *priv = dev_get_priv(dev);
478 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800479 struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
Cédric Le Goater08b3e902019-11-28 13:37:04 +0100480 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goatere7668492018-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 Goaterd0e0b842018-10-29 07:06:35 +0100485 int rc;
Cédric Le Goatere7668492018-10-29 07:06:34 +0100486
487 invalidate_dcache_range(des_start, des_end);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800488
489 if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
Cédric Le Goatere7668492018-10-29 07:06:34 +0100490 dev_err(dev, "no TX descriptor available\n");
491 return -EPERM;
Macpaul Linb3dbf4a52010-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 Goatere7668492018-10-29 07:06:34 +0100498 curr_des->txdes3 = (unsigned int)packet;
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800499
Cédric Le Goatere7668492018-10-29 07:06:34 +0100500 /* 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);
504
505 /* Only one segment on TXBUF */
Cédric Le Goatere6ddacc2018-10-29 07:06:38 +0100506 curr_des->txdes0 &= priv->txdes0_edotr_mask;
Macpaul Linb3dbf4a52010-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 Goatere7668492018-10-29 07:06:34 +0100512 /* Flush modified buffer descriptor */
513 flush_dcache_range(des_start, des_end);
514
515 /* Start transmit */
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800516 writel(1, &ftgmac100->txpd);
517
Cédric Le Goaterd0e0b842018-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 Linb3dbf4a52010-12-21 16:59:46 +0800524 debug("%s(): packet sent\n", __func__);
525
Cédric Le Goatere7668492018-10-29 07:06:34 +0100526 /* Move to next descriptor */
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800527 priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
528
529 return 0;
530}
531
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100532static int ftgmac100_write_hwaddr(struct udevice *dev)
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800533{
Simon Glassc69cda22020-12-03 16:55:20 -0700534 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100535 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800536
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100537 return ftgmac100_set_mac(priv, pdata->enetaddr);
538}
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800539
Hongwei Zhang0be3d1f2020-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 Glassd1998a92020-12-03 16:55:21 -0700548static int ftgmac100_of_to_plat(struct udevice *dev)
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100549{
Simon Glassc69cda22020-12-03 16:55:20 -0700550 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater1c0c61e2018-10-29 07:06:36 +0100551 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800552
Masahiro Yamada25484932020-07-17 14:36:48 +0900553 pdata->iobase = dev_read_addr(dev);
Marek Behún123ca112022-04-07 00:33:01 +0200554
555 pdata->phy_interface = dev_read_phy_mode(dev);
Marek Behúnffb0f6f2022-04-07 00:33:03 +0200556 if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100557 return -EINVAL;
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100558
559 pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
560
Cédric Le Goatere6ddacc2018-10-29 07:06:38 +0100561 if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
562 priv->rxdes0_edorr_mask = BIT(30);
563 priv->txdes0_edotr_mask = BIT(30);
564 } else {
565 priv->rxdes0_edorr_mask = BIT(15);
566 priv->txdes0_edotr_mask = BIT(15);
567 }
568
Cédric Le Goater1c0c61e2018-10-29 07:06:36 +0100569 return clk_get_bulk(dev, &priv->clks);
Macpaul Linb3dbf4a52010-12-21 16:59:46 +0800570}
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100571
572static int ftgmac100_probe(struct udevice *dev)
573{
Simon Glassc69cda22020-12-03 16:55:20 -0700574 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100575 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100576 int ret;
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100577
578 priv->iobase = (struct ftgmac100 *)pdata->iobase;
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100579 priv->phy_mode = pdata->phy_interface;
580 priv->max_speed = pdata->max_speed;
581 priv->phy_addr = 0;
582
Thirupathaiah Annapureddy66e036b2020-08-17 17:08:26 -0700583#ifdef CONFIG_PHY_ADDR
584 priv->phy_addr = CONFIG_PHY_ADDR;
585#endif
586
Cédric Le Goater1c0c61e2018-10-29 07:06:36 +0100587 ret = clk_enable_bulk(&priv->clks);
588 if (ret)
589 goto out;
590
Dylan Hung9c27ce72021-12-09 10:12:24 +0800591 /*
592 * If DM MDIO is enabled, the MDIO bus will be initialized later in
593 * dm_eth_phy_connect
594 */
595 if (!IS_ENABLED(CONFIG_DM_MDIO)) {
596 ret = ftgmac100_mdio_init(dev);
597 if (ret) {
598 dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
599 goto out;
600 }
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100601 }
602
603 ret = ftgmac100_phy_init(dev);
604 if (ret) {
605 dev_err(dev, "Failed to initialize PHY: %d\n", ret);
606 goto out;
607 }
608
Hongwei Zhang0be3d1f2020-12-10 18:11:09 -0500609 ftgmac_read_hwaddr(dev);
610
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100611out:
Cédric Le Goater1c0c61e2018-10-29 07:06:36 +0100612 if (ret)
613 clk_release_bulk(&priv->clks);
614
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100615 return ret;
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100616}
617
618static int ftgmac100_remove(struct udevice *dev)
619{
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100620 struct ftgmac100_data *priv = dev_get_priv(dev);
621
622 free(priv->phydev);
623 mdio_unregister(priv->bus);
624 mdio_free(priv->bus);
Cédric Le Goater1c0c61e2018-10-29 07:06:36 +0100625 clk_release_bulk(&priv->clks);
Cédric Le Goater538e75d2018-10-29 07:06:33 +0100626
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100627 return 0;
628}
629
630static const struct eth_ops ftgmac100_ops = {
631 .start = ftgmac100_start,
632 .send = ftgmac100_send,
633 .recv = ftgmac100_recv,
634 .stop = ftgmac100_stop,
635 .free_pkt = ftgmac100_free_pkt,
636 .write_hwaddr = ftgmac100_write_hwaddr,
637};
638
639static const struct udevice_id ftgmac100_ids[] = {
Cédric Le Goatere6ddacc2018-10-29 07:06:38 +0100640 { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
641 { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
Dylan Hungac4fda72021-12-09 10:12:25 +0800642 { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100643 { }
644};
645
646U_BOOT_DRIVER(ftgmac100) = {
647 .name = "ftgmac100",
648 .id = UCLASS_ETH,
649 .of_match = ftgmac100_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700650 .of_to_plat = ftgmac100_of_to_plat,
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100651 .probe = ftgmac100_probe,
652 .remove = ftgmac100_remove,
653 .ops = &ftgmac100_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700654 .priv_auto = sizeof(struct ftgmac100_data),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700655 .plat_auto = sizeof(struct eth_pdata),
Cédric Le Goaterf95de0b2018-10-29 07:06:31 +0100656 .flags = DM_FLAG_ALLOC_PRIV_DMA,
657};