blob: f5ea2e72d1bbd401faefffaee0d118b61e253fdf [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>
Dylan Hung1a2ef082023-07-27 09:58:14 +080015#include <reset.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>
Simon Glassbdd5f812023-09-14 18:21:46 -060028#include <linux/printk.h>
Jacky Chou65909ec2024-07-08 14:07:18 +080029#include <linux/bitfield.h>
Macpaul Lin199c6252010-12-21 16:59:46 +080030
31#include "ftgmac100.h"
32
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010033/* Min frame ethernet frame size without FCS */
34#define ETH_ZLEN 60
Macpaul Lin199c6252010-12-21 16:59:46 +080035
Cédric Le Goater3174dfb2018-10-29 07:06:34 +010036/* Receive Buffer Size Register - HW default is 0x640 */
37#define FTGMAC100_RBSR_DEFAULT 0x640
Macpaul Lin199c6252010-12-21 16:59:46 +080038
39/* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
40#define PKTBUFSTX 4 /* must be power of 2 */
41
Cédric Le Goater9bcb6652018-10-29 07:06:35 +010042/* Timeout for transmit */
43#define FTGMAC100_TX_TIMEOUT_MS 1000
44
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010045/* Timeout for a mdio read/write operation */
46#define FTGMAC100_MDIO_TIMEOUT_USEC 10000
47
48/*
49 * MDC clock cycle threshold
50 *
51 * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
52 */
53#define MDC_CYCTHR 0x34
54
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010055/*
56 * ftgmac100 model variants
57 */
58enum ftgmac100_model {
59 FTGMAC100_MODEL_FARADAY,
60 FTGMAC100_MODEL_ASPEED,
Jacky Chou65909ec2024-07-08 14:07:18 +080061 FTGMAC100_MODEL_ASPEED_AST2700,
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010062};
63
Jacky Chou65909ec2024-07-08 14:07:18 +080064union ftgmac100_dma_addr {
65 dma_addr_t addr;
66 struct {
67 u32 lo;
68 u32 hi;
69 };
70};
71
Cédric Le Goater38b33e92018-10-29 07:06:31 +010072/**
73 * struct ftgmac100_data - private data for the FTGMAC100 driver
74 *
75 * @iobase: The base address of the hardware registers
76 * @txdes: The array of transmit descriptors
77 * @rxdes: The array of receive descriptors
78 * @tx_index: Transmit descriptor index in @txdes
79 * @rx_index: Receive descriptor index in @rxdes
80 * @phy_addr: The PHY interface address to use
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010081 * @phydev: The PHY device backing the MAC
82 * @bus: The mdio bus
83 * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
84 * @max_speed: Maximum speed of Ethernet connection supported by MAC
Cédric Le Goater6afa3f12018-10-29 07:06:36 +010085 * @clks: The bulk of clocks assigned to the device in the DT
Cédric Le Goater35efcbb2018-10-29 07:06:38 +010086 * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
87 * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
Cédric Le Goater38b33e92018-10-29 07:06:31 +010088 */
Macpaul Lin199c6252010-12-21 16:59:46 +080089struct ftgmac100_data {
Cédric Le Goater38b33e92018-10-29 07:06:31 +010090 struct ftgmac100 *iobase;
91
Cédric Le Goater0404e9f2019-11-28 13:37:04 +010092 struct ftgmac100_txdes txdes[PKTBUFSTX] __aligned(ARCH_DMA_MINALIGN);
93 struct ftgmac100_rxdes rxdes[PKTBUFSRX] __aligned(ARCH_DMA_MINALIGN);
Macpaul Lin199c6252010-12-21 16:59:46 +080094 int tx_index;
95 int rx_index;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +010096
97 u32 phy_addr;
98 struct phy_device *phydev;
99 struct mii_dev *bus;
100 u32 phy_mode;
101 u32 max_speed;
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100102
103 struct clk_bulk clks;
Dylan Hung1a2ef082023-07-27 09:58:14 +0800104 struct reset_ctl *reset_ctl;
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100105
106 /* End of RX/TX ring buffer bits. Depend on model */
107 u32 rxdes0_edorr_mask;
108 u32 txdes0_edotr_mask;
Jacky Chou65909ec2024-07-08 14:07:18 +0800109
110 bool is_ast2700;
Macpaul Lin199c6252010-12-21 16:59:46 +0800111};
112
113/*
114 * struct mii_bus functions
115 */
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100116static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
117 int reg_addr)
Macpaul Lin199c6252010-12-21 16:59:46 +0800118{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100119 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100120 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800121 int phycr;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100122 int data;
123 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800124
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100125 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
126 FTGMAC100_PHYCR_PHYAD(phy_addr) |
127 FTGMAC100_PHYCR_REGAD(reg_addr) |
128 FTGMAC100_PHYCR_MIIRD;
Macpaul Lin199c6252010-12-21 16:59:46 +0800129 writel(phycr, &ftgmac100->phycr);
130
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100131 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
132 !(phycr & FTGMAC100_PHYCR_MIIRD),
133 FTGMAC100_MDIO_TIMEOUT_USEC);
134 if (ret) {
135 pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
Zev Weiss4e5ca0f2022-05-17 15:16:39 -0700136 bus->name, phy_addr, reg_addr);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100137 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800138 }
139
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100140 data = readl(&ftgmac100->phydata);
141
142 return FTGMAC100_PHYDATA_MIIRDATA(data);
Macpaul Lin199c6252010-12-21 16:59:46 +0800143}
144
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100145static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
146 int reg_addr, u16 value)
Macpaul Lin199c6252010-12-21 16:59:46 +0800147{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100148 struct ftgmac100_data *priv = bus->priv;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100149 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800150 int phycr;
151 int data;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100152 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800153
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100154 phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
155 FTGMAC100_PHYCR_PHYAD(phy_addr) |
156 FTGMAC100_PHYCR_REGAD(reg_addr) |
157 FTGMAC100_PHYCR_MIIWR;
Macpaul Lin199c6252010-12-21 16:59:46 +0800158 data = FTGMAC100_PHYDATA_MIIWDATA(value);
159
160 writel(data, &ftgmac100->phydata);
161 writel(phycr, &ftgmac100->phycr);
162
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100163 ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
164 !(phycr & FTGMAC100_PHYCR_MIIWR),
165 FTGMAC100_MDIO_TIMEOUT_USEC);
166 if (ret) {
167 pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
Zev Weiss4e5ca0f2022-05-17 15:16:39 -0700168 bus->name, phy_addr, reg_addr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800169 }
170
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100171 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800172}
173
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100174static int ftgmac100_mdio_init(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800175{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100176 struct ftgmac100_data *priv = dev_get_priv(dev);
177 struct mii_dev *bus;
178 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800179
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100180 bus = mdio_alloc();
181 if (!bus)
182 return -ENOMEM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800183
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100184 bus->read = ftgmac100_mdio_read;
185 bus->write = ftgmac100_mdio_write;
186 bus->priv = priv;
Macpaul Lin199c6252010-12-21 16:59:46 +0800187
Simon Glass75e534b2020-12-16 21:20:07 -0700188 ret = mdio_register_seq(bus, dev_seq(dev));
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100189 if (ret) {
190 free(bus);
191 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800192 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800193
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100194 priv->bus = bus;
Macpaul Lin199c6252010-12-21 16:59:46 +0800195
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100196 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800197}
198
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100199static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800200{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100201 struct ftgmac100 *ftgmac100 = priv->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100202 struct phy_device *phydev = priv->phydev;
203 u32 maccr;
Macpaul Lin199c6252010-12-21 16:59:46 +0800204
Samuel Mendoza-Jonascf4c4f92022-08-08 21:46:05 +0930205 if (!phydev->link && priv->phy_mode != PHY_INTERFACE_MODE_NCSI) {
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100206 dev_err(phydev->dev, "No link\n");
207 return -EREMOTEIO;
208 }
Macpaul Lin199c6252010-12-21 16:59:46 +0800209
210 /* read MAC control register and clear related bits */
211 maccr = readl(&ftgmac100->maccr) &
212 ~(FTGMAC100_MACCR_GIGA_MODE |
213 FTGMAC100_MACCR_FAST_MODE |
214 FTGMAC100_MACCR_FULLDUP);
215
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100216 if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
Macpaul Lin199c6252010-12-21 16:59:46 +0800217 maccr |= FTGMAC100_MACCR_GIGA_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800218
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100219 if (phydev->speed == 100)
Macpaul Lin199c6252010-12-21 16:59:46 +0800220 maccr |= FTGMAC100_MACCR_FAST_MODE;
Macpaul Lin199c6252010-12-21 16:59:46 +0800221
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100222 if (phydev->duplex)
223 maccr |= FTGMAC100_MACCR_FULLDUP;
Macpaul Lin199c6252010-12-21 16:59:46 +0800224
225 /* update MII config into maccr */
226 writel(maccr, &ftgmac100->maccr);
227
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100228 return 0;
229}
230
231static int ftgmac100_phy_init(struct udevice *dev)
232{
233 struct ftgmac100_data *priv = dev_get_priv(dev);
234 struct phy_device *phydev;
235 int ret;
236
Jacky Chou7c011532024-06-28 15:14:45 +0800237 if (IS_ENABLED(CONFIG_DM_MDIO) && priv->phy_mode != PHY_INTERFACE_MODE_NCSI)
Dylan Hung2bec3722021-12-09 10:12:24 +0800238 phydev = dm_eth_phy_connect(dev);
239 else
240 phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
241
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100242 if (!phydev)
243 return -ENODEV;
244
Samuel Mendoza-Jonascf4c4f92022-08-08 21:46:05 +0930245 if (priv->phy_mode != PHY_INTERFACE_MODE_NCSI)
246 phydev->supported &= PHY_GBIT_FEATURES;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100247 if (priv->max_speed) {
248 ret = phy_set_supported(phydev, priv->max_speed);
249 if (ret)
250 return ret;
251 }
252 phydev->advertising = phydev->supported;
253 priv->phydev = phydev;
254 phy_config(phydev);
255
256 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800257}
258
259/*
260 * Reset MAC
261 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100262static void ftgmac100_reset(struct ftgmac100_data *priv)
Macpaul Lin199c6252010-12-21 16:59:46 +0800263{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100264 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800265
266 debug("%s()\n", __func__);
267
Cédric Le Goatercef951c2018-10-29 07:06:32 +0100268 setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
Macpaul Lin199c6252010-12-21 16:59:46 +0800269
270 while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
271 ;
272}
273
274/*
275 * Set MAC address
276 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100277static int ftgmac100_set_mac(struct ftgmac100_data *priv,
278 const unsigned char *mac)
Macpaul Lin199c6252010-12-21 16:59:46 +0800279{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100280 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800281 unsigned int maddr = mac[0] << 8 | mac[1];
282 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
283
284 debug("%s(%x %x)\n", __func__, maddr, laddr);
285
286 writel(maddr, &ftgmac100->mac_madr);
287 writel(laddr, &ftgmac100->mac_ladr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800288
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100289 return 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800290}
291
292/*
Hongwei Zhang55ae5902020-12-10 18:11:09 -0500293 * Get MAC address
294 */
295static int ftgmac100_get_mac(struct ftgmac100_data *priv,
296 unsigned char *mac)
297{
298 struct ftgmac100 *ftgmac100 = priv->iobase;
299 unsigned int maddr = readl(&ftgmac100->mac_madr);
300 unsigned int laddr = readl(&ftgmac100->mac_ladr);
301
302 debug("%s(%x %x)\n", __func__, maddr, laddr);
303
304 mac[0] = (maddr >> 8) & 0xff;
305 mac[1] = maddr & 0xff;
306 mac[2] = (laddr >> 24) & 0xff;
307 mac[3] = (laddr >> 16) & 0xff;
308 mac[4] = (laddr >> 8) & 0xff;
309 mac[5] = laddr & 0xff;
310
311 return 0;
312}
313
314/*
Macpaul Lin199c6252010-12-21 16:59:46 +0800315 * disable transmitter, receiver
316 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100317static void ftgmac100_stop(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800318{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100319 struct ftgmac100_data *priv = dev_get_priv(dev);
320 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800321
322 debug("%s()\n", __func__);
323
324 writel(0, &ftgmac100->maccr);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100325
Samuel Mendoza-Jonascf4c4f92022-08-08 21:46:05 +0930326 if (priv->phy_mode != PHY_INTERFACE_MODE_NCSI)
327 phy_shutdown(priv->phydev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800328}
329
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100330static int ftgmac100_start(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800331{
Simon Glassfa20e932020-12-03 16:55:20 -0700332 struct eth_pdata *plat = dev_get_plat(dev);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100333 struct ftgmac100_data *priv = dev_get_priv(dev);
334 struct ftgmac100 *ftgmac100 = priv->iobase;
Jacky Chou65909ec2024-07-08 14:07:18 +0800335 union ftgmac100_dma_addr dma_addr = {.hi = 0, .lo = 0};
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100336 struct phy_device *phydev = priv->phydev;
Jacky Choua3e259b2024-06-28 17:38:50 +0800337 unsigned int maccr, dblac, desc_size;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100338 ulong start, end;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100339 int ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800340 int i;
341
342 debug("%s()\n", __func__);
343
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100344 ftgmac100_reset(priv);
345
Macpaul Lin199c6252010-12-21 16:59:46 +0800346 /* set the ethernet address */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100347 ftgmac100_set_mac(priv, plat->enetaddr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800348
349 /* disable all interrupts */
350 writel(0, &ftgmac100->ier);
351
352 /* initialize descriptors */
353 priv->tx_index = 0;
354 priv->rx_index = 0;
355
Macpaul Lin199c6252010-12-21 16:59:46 +0800356 for (i = 0; i < PKTBUFSTX; i++) {
Jacky Chou65909ec2024-07-08 14:07:18 +0800357 priv->txdes[i].txdes2 = 0;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100358 priv->txdes[i].txdes3 = 0;
359 priv->txdes[i].txdes0 = 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800360 }
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100361 priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100362
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100363 start = ((ulong)&priv->txdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100364 end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
365 flush_dcache_range(start, end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800366
367 for (i = 0; i < PKTBUFSRX; i++) {
Jacky Chou65909ec2024-07-08 14:07:18 +0800368 unsigned int ip_align = 0;
369
370 dma_addr.addr = (dma_addr_t)net_rx_packets[i];
371 priv->rxdes[i].rxdes2 = FIELD_PREP(FTGMAC100_RXDES2_RXBUF_BADR_HI, dma_addr.hi);
372 /* For IP alignment */
373 if ((dma_addr.lo & (PKTALIGN - 1)) == 0)
374 ip_align = 2;
375 priv->rxdes[i].rxdes3 = dma_addr.lo + ip_align;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100376 priv->rxdes[i].rxdes0 = 0;
Macpaul Lin199c6252010-12-21 16:59:46 +0800377 }
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100378 priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100379
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100380 start = ((ulong)&priv->rxdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100381 end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
382 flush_dcache_range(start, end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800383
384 /* transmit ring */
Jacky Chou65909ec2024-07-08 14:07:18 +0800385 dma_addr.addr = (dma_addr_t)priv->txdes;
386 writel(dma_addr.lo, &ftgmac100->txr_badr);
387 writel(dma_addr.hi, &ftgmac100->txr_badr_hi);
Macpaul Lin199c6252010-12-21 16:59:46 +0800388
389 /* receive ring */
Jacky Chou65909ec2024-07-08 14:07:18 +0800390 dma_addr.addr = (dma_addr_t)priv->rxdes;
391 writel(dma_addr.lo, &ftgmac100->rxr_badr);
392 writel(dma_addr.hi, &ftgmac100->rxr_badr_hi);
Macpaul Lin199c6252010-12-21 16:59:46 +0800393
Jacky Choua3e259b2024-06-28 17:38:50 +0800394 /* Configure TX/RX decsriptor size
395 * This size is calculated based on cache line.
396 */
397 desc_size = ARCH_DMA_MINALIGN / FTGMAC100_DESC_UNIT;
398 /* The descriptor size is at least 2 descriptor units. */
399 if (desc_size < 2)
400 desc_size = 2;
401 dblac = readl(&ftgmac100->dblac) & ~GENMASK(19, 12);
402 dblac |= FTGMAC100_DBLAC_RXDES_SIZE(desc_size) | FTGMAC100_DBLAC_TXDES_SIZE(desc_size);
403 writel(dblac, &ftgmac100->dblac);
404
Macpaul Lin199c6252010-12-21 16:59:46 +0800405 /* poll receive descriptor automatically */
406 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
407
408 /* config receive buffer size register */
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100409 writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
Macpaul Lin199c6252010-12-21 16:59:46 +0800410
411 /* enable transmitter, receiver */
412 maccr = FTGMAC100_MACCR_TXMAC_EN |
413 FTGMAC100_MACCR_RXMAC_EN |
414 FTGMAC100_MACCR_TXDMA_EN |
415 FTGMAC100_MACCR_RXDMA_EN |
416 FTGMAC100_MACCR_CRC_APD |
417 FTGMAC100_MACCR_FULLDUP |
418 FTGMAC100_MACCR_RX_RUNT |
419 FTGMAC100_MACCR_RX_BROADPKT;
420
Jacky Chou65909ec2024-07-08 14:07:18 +0800421 if (priv->is_ast2700 && (priv->phydev->interface == PHY_INTERFACE_MODE_RMII ||
422 priv->phydev->interface == PHY_INTERFACE_MODE_NCSI))
423 maccr |= FTGMAC100_MACCR_RMII_ENABLE;
424
Macpaul Lin199c6252010-12-21 16:59:46 +0800425 writel(maccr, &ftgmac100->maccr);
426
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100427 ret = phy_startup(phydev);
428 if (ret) {
429 dev_err(phydev->dev, "Could not start PHY\n");
430 return ret;
431 }
432
433 ret = ftgmac100_phy_adjust_link(priv);
434 if (ret) {
435 dev_err(phydev->dev, "Could not adjust link\n");
436 return ret;
Macpaul Lin199c6252010-12-21 16:59:46 +0800437 }
438
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100439 printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
440 phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
441
Macpaul Lin199c6252010-12-21 16:59:46 +0800442 return 0;
443}
444
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100445static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
446{
447 struct ftgmac100_data *priv = dev_get_priv(dev);
448 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100449 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100450 ulong des_end = des_start +
451 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100452
Jacky Chou69d57072024-06-27 14:26:00 +0800453 /*
454 * Make sure there are no stale data in write-back over this area, which
455 * might get written into the memory while the ftgmac100 also writes
456 * into the same memory area.
457 */
458 flush_dcache_range((ulong)net_rx_packets[priv->rx_index],
459 (ulong)net_rx_packets[priv->rx_index] + PKTSIZE_ALIGN);
460
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100461 /* Release buffer to DMA and flush descriptor */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100462 curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100463 flush_dcache_range(des_start, des_end);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100464
465 /* Move to next descriptor */
466 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
467
468 return 0;
469}
470
Macpaul Lin199c6252010-12-21 16:59:46 +0800471/*
472 * Get a data block via Ethernet
473 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100474static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
Macpaul Lin199c6252010-12-21 16:59:46 +0800475{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100476 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100477 struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
Macpaul Lin199c6252010-12-21 16:59:46 +0800478 unsigned short rxlen;
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100479 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100480 ulong des_end = des_start +
481 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
Jacky Chou65909ec2024-07-08 14:07:18 +0800482 union ftgmac100_dma_addr data_start = { .lo = 0, .hi = 0 };
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100483 ulong data_end;
Macpaul Lin199c6252010-12-21 16:59:46 +0800484
Jacky Chou65909ec2024-07-08 14:07:18 +0800485 data_start.hi = FIELD_GET(FTGMAC100_RXDES2_RXBUF_BADR_HI, curr_des->rxdes2);
486 data_start.lo = curr_des->rxdes3;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100487 invalidate_dcache_range(des_start, des_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800488
489 if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100490 return -EAGAIN;
Macpaul Lin199c6252010-12-21 16:59:46 +0800491
492 if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
493 FTGMAC100_RXDES0_CRC_ERR |
494 FTGMAC100_RXDES0_FTL |
495 FTGMAC100_RXDES0_RUNT |
496 FTGMAC100_RXDES0_RX_ODD_NB)) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100497 return -EAGAIN;
Macpaul Lin199c6252010-12-21 16:59:46 +0800498 }
499
500 rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
501
502 debug("%s(): RX buffer %d, %x received\n",
503 __func__, priv->rx_index, rxlen);
504
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100505 /* Invalidate received data */
Jacky Chou65909ec2024-07-08 14:07:18 +0800506 data_end = data_start.addr + roundup(rxlen, ARCH_DMA_MINALIGN);
507 invalidate_dcache_range(data_start.addr, data_end);
508 *packetp = (uchar *)data_start.addr;
Macpaul Lin199c6252010-12-21 16:59:46 +0800509
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100510 return rxlen;
Macpaul Lin199c6252010-12-21 16:59:46 +0800511}
512
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100513static u32 ftgmac100_read_txdesc(const void *desc)
514{
515 const struct ftgmac100_txdes *txdes = desc;
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100516 ulong des_start = ((ulong)txdes) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100517 ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
518
519 invalidate_dcache_range(des_start, des_end);
520
521 return txdes->txdes0;
522}
523
524BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
525
Macpaul Lin199c6252010-12-21 16:59:46 +0800526/*
527 * Send a data block via Ethernet
528 */
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100529static int ftgmac100_send(struct udevice *dev, void *packet, int length)
Macpaul Lin199c6252010-12-21 16:59:46 +0800530{
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100531 struct ftgmac100_data *priv = dev_get_priv(dev);
532 struct ftgmac100 *ftgmac100 = priv->iobase;
Macpaul Lin199c6252010-12-21 16:59:46 +0800533 struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
Jacky Chou65909ec2024-07-08 14:07:18 +0800534 union ftgmac100_dma_addr dma_addr;
Cédric Le Goater0404e9f2019-11-28 13:37:04 +0100535 ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100536 ulong des_end = des_start +
537 roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
538 ulong data_start;
539 ulong data_end;
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100540 int rc;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100541
542 invalidate_dcache_range(des_start, des_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800543
544 if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100545 dev_err(dev, "no TX descriptor available\n");
546 return -EPERM;
Macpaul Lin199c6252010-12-21 16:59:46 +0800547 }
548
549 debug("%s(%x, %x)\n", __func__, (int)packet, length);
550
551 length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
552
Jacky Chou65909ec2024-07-08 14:07:18 +0800553 dma_addr.addr = (dma_addr_t)packet;
554 curr_des->txdes2 = FIELD_PREP(FTGMAC100_TXDES2_TXBUF_BADR_HI, dma_addr.hi);
555 curr_des->txdes3 = dma_addr.lo;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100556
557 /* Flush data to be sent */
Jacky Chou65909ec2024-07-08 14:07:18 +0800558 data_start = (ulong)dma_addr.addr;
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100559 data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
560 flush_dcache_range(data_start, data_end);
Macpaul Lin199c6252010-12-21 16:59:46 +0800561
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100562 /* Only one segment on TXBUF */
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100563 curr_des->txdes0 &= priv->txdes0_edotr_mask;
Macpaul Lin199c6252010-12-21 16:59:46 +0800564 curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
565 FTGMAC100_TXDES0_LTS |
566 FTGMAC100_TXDES0_TXBUF_SIZE(length) |
567 FTGMAC100_TXDES0_TXDMA_OWN ;
568
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100569 /* Flush modified buffer descriptor */
570 flush_dcache_range(des_start, des_end);
571
572 /* Start transmit */
Macpaul Lin199c6252010-12-21 16:59:46 +0800573 writel(1, &ftgmac100->txpd);
574
Cédric Le Goater9bcb6652018-10-29 07:06:35 +0100575 rc = wait_for_bit_ftgmac100_txdone(curr_des,
576 FTGMAC100_TXDES0_TXDMA_OWN, false,
577 FTGMAC100_TX_TIMEOUT_MS, true);
578 if (rc)
579 return rc;
580
Macpaul Lin199c6252010-12-21 16:59:46 +0800581 debug("%s(): packet sent\n", __func__);
582
Cédric Le Goater3174dfb2018-10-29 07:06:34 +0100583 /* Move to next descriptor */
Macpaul Lin199c6252010-12-21 16:59:46 +0800584 priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
585
586 return 0;
587}
588
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100589static int ftgmac100_write_hwaddr(struct udevice *dev)
Macpaul Lin199c6252010-12-21 16:59:46 +0800590{
Simon Glassfa20e932020-12-03 16:55:20 -0700591 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100592 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800593
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100594 return ftgmac100_set_mac(priv, pdata->enetaddr);
595}
Macpaul Lin199c6252010-12-21 16:59:46 +0800596
Hongwei Zhang55ae5902020-12-10 18:11:09 -0500597static int ftgmac_read_hwaddr(struct udevice *dev)
598{
599 struct eth_pdata *pdata = dev_get_plat(dev);
600 struct ftgmac100_data *priv = dev_get_priv(dev);
601
602 return ftgmac100_get_mac(priv, pdata->enetaddr);
603}
604
Simon Glassaad29ae2020-12-03 16:55:21 -0700605static int ftgmac100_of_to_plat(struct udevice *dev)
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100606{
Simon Glassfa20e932020-12-03 16:55:20 -0700607 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100608 struct ftgmac100_data *priv = dev_get_priv(dev);
Macpaul Lin199c6252010-12-21 16:59:46 +0800609
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900610 pdata->iobase = dev_read_addr(dev);
Marek Behúnbc194772022-04-07 00:33:01 +0200611
612 pdata->phy_interface = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +0200613 if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100614 return -EINVAL;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100615
616 pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
617
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100618 if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
619 priv->rxdes0_edorr_mask = BIT(30);
620 priv->txdes0_edotr_mask = BIT(30);
Jacky Chou65909ec2024-07-08 14:07:18 +0800621 priv->is_ast2700 = false;
622 } else if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED_AST2700) {
623 priv->rxdes0_edorr_mask = BIT(30);
624 priv->txdes0_edotr_mask = BIT(30);
625 priv->is_ast2700 = true;
Cédric Le Goater35efcbb2018-10-29 07:06:38 +0100626 } else {
627 priv->rxdes0_edorr_mask = BIT(15);
628 priv->txdes0_edotr_mask = BIT(15);
629 }
630
Dylan Hung1a2ef082023-07-27 09:58:14 +0800631 priv->reset_ctl = devm_reset_control_get_optional(dev, NULL);
632
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100633 return clk_get_bulk(dev, &priv->clks);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100634}
Macpaul Lin199c6252010-12-21 16:59:46 +0800635
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100636static int ftgmac100_probe(struct udevice *dev)
637{
Simon Glassfa20e932020-12-03 16:55:20 -0700638 struct eth_pdata *pdata = dev_get_plat(dev);
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100639 struct ftgmac100_data *priv = dev_get_priv(dev);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100640 int ret;
Macpaul Linc56c5a32011-09-20 19:54:32 +0000641
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100642 priv->iobase = (struct ftgmac100 *)pdata->iobase;
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100643 priv->phy_mode = pdata->phy_interface;
644 priv->max_speed = pdata->max_speed;
645 priv->phy_addr = 0;
646
Samuel Mendoza-Jonascf4c4f92022-08-08 21:46:05 +0930647 if (dev_read_bool(dev, "use-ncsi"))
648 priv->phy_mode = PHY_INTERFACE_MODE_NCSI;
649
Thirupathaiah Annapureddy22bb3772020-08-17 17:08:26 -0700650#ifdef CONFIG_PHY_ADDR
651 priv->phy_addr = CONFIG_PHY_ADDR;
652#endif
653
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100654 ret = clk_enable_bulk(&priv->clks);
655 if (ret)
656 goto out;
657
Dylan Hung1a2ef082023-07-27 09:58:14 +0800658 if (priv->reset_ctl) {
659 ret = reset_deassert(priv->reset_ctl);
660 if (ret)
661 goto out;
662 }
663
Dylan Hung2bec3722021-12-09 10:12:24 +0800664 /*
665 * If DM MDIO is enabled, the MDIO bus will be initialized later in
666 * dm_eth_phy_connect
667 */
Samuel Mendoza-Jonascf4c4f92022-08-08 21:46:05 +0930668 if (priv->phy_mode != PHY_INTERFACE_MODE_NCSI &&
669 !IS_ENABLED(CONFIG_DM_MDIO)) {
Dylan Hung2bec3722021-12-09 10:12:24 +0800670 ret = ftgmac100_mdio_init(dev);
671 if (ret) {
672 dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
673 goto out;
674 }
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100675 }
676
677 ret = ftgmac100_phy_init(dev);
678 if (ret) {
679 dev_err(dev, "Failed to initialize PHY: %d\n", ret);
680 goto out;
681 }
682
Hongwei Zhang55ae5902020-12-10 18:11:09 -0500683 ftgmac_read_hwaddr(dev);
684
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100685out:
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100686 if (ret)
687 clk_release_bulk(&priv->clks);
688
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100689 return ret;
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100690}
Macpaul Lin199c6252010-12-21 16:59:46 +0800691
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100692static int ftgmac100_remove(struct udevice *dev)
693{
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100694 struct ftgmac100_data *priv = dev_get_priv(dev);
695
696 free(priv->phydev);
697 mdio_unregister(priv->bus);
698 mdio_free(priv->bus);
Dylan Hung1a2ef082023-07-27 09:58:14 +0800699 if (priv->reset_ctl)
700 reset_assert(priv->reset_ctl);
Cédric Le Goater6afa3f12018-10-29 07:06:36 +0100701 clk_release_bulk(&priv->clks);
Cédric Le Goater7f8482a2018-10-29 07:06:33 +0100702
Macpaul Lin199c6252010-12-21 16:59:46 +0800703 return 0;
704}
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100705
706static const struct eth_ops ftgmac100_ops = {
707 .start = ftgmac100_start,
708 .send = ftgmac100_send,
709 .recv = ftgmac100_recv,
710 .stop = ftgmac100_stop,
711 .free_pkt = ftgmac100_free_pkt,
712 .write_hwaddr = ftgmac100_write_hwaddr,
713};
714
715static const struct udevice_id ftgmac100_ids[] = {
Jacky Chou65909ec2024-07-08 14:07:18 +0800716 { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
717 { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
718 { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
719 { .compatible = "aspeed,ast2700-mac", .data = FTGMAC100_MODEL_ASPEED_AST2700 },
720 {}
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100721};
722
723U_BOOT_DRIVER(ftgmac100) = {
724 .name = "ftgmac100",
725 .id = UCLASS_ETH,
726 .of_match = ftgmac100_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700727 .of_to_plat = ftgmac100_of_to_plat,
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100728 .probe = ftgmac100_probe,
729 .remove = ftgmac100_remove,
730 .ops = &ftgmac100_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700731 .priv_auto = sizeof(struct ftgmac100_data),
Simon Glass71fa5b42020-12-03 16:55:18 -0700732 .plat_auto = sizeof(struct eth_pdata),
Cédric Le Goater38b33e92018-10-29 07:06:31 +0100733 .flags = DM_FLAG_ALLOC_PRIV_DMA,
734};