blob: 39c0233b626346a2d2f2ebb298be8fa7274ec31e [file] [log] [blame]
Yang Xiwend9717112023-08-23 01:03:42 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Hisilicon Fast Ethernet MAC Driver
4 * Adapted from linux
5 *
6 * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
7 * Copyright (c) 2023 Yang Xiwen <forbidden405@outlook.com>
8 */
9
10#include <dm.h>
11#include <clk.h>
12#include <miiphy.h>
13#include <net.h>
14#include <reset.h>
15#include <wait_bit.h>
16#include <asm/io.h>
17#include <dm/device_compat.h>
Yang Xiwen7579ad12024-01-22 22:33:22 +080018#include <dm/lists.h>
Yang Xiwend9717112023-08-23 01:03:42 +080019#include <linux/delay.h>
20#include <linux/kernel.h>
21
22/* MAC control register list */
23#define MAC_PORTSEL 0x0200
24#define MAC_PORTSEL_STAT_CPU BIT(0)
25#define MAC_PORTSEL_RMII BIT(1)
26#define MAC_PORTSET 0x0208
27#define MAC_PORTSET_DUPLEX_FULL BIT(0)
28#define MAC_PORTSET_LINKED BIT(1)
29#define MAC_PORTSET_SPEED_100M BIT(2)
30#define MAC_SET 0x0210
31#define MAX_FRAME_SIZE 1600
32#define MAX_FRAME_SIZE_MASK GENMASK(10, 0)
33#define BIT_PAUSE_EN BIT(18)
34#define RX_COALESCE_SET 0x0340
35#define RX_COALESCED_FRAME_OFFSET 24
36#define RX_COALESCED_FRAMES 8
37#define RX_COALESCED_TIMER 0x74
38#define QLEN_SET 0x0344
39#define RX_DEPTH_OFFSET 8
40#define MAX_HW_FIFO_DEPTH 64
41#define HW_TX_FIFO_DEPTH 1
42#define MAX_HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
43#define HW_RX_FIFO_DEPTH min(PKTBUFSRX, MAX_HW_RX_FIFO_DEPTH)
44#define IQFRM_DES 0x0354
45#define RX_FRAME_LEN_MASK GENMASK(11, 0)
46#define RX_FRAME_IN_INDEX_MASK GENMASK(17, 12)
47#define IQ_ADDR 0x0358
48#define EQ_ADDR 0x0360
49#define EQFRM_LEN 0x0364
50#define ADDRQ_STAT 0x036C
51#define TX_CNT_INUSE_MASK GENMASK(5, 0)
52#define BIT_TX_READY BIT(24)
53#define BIT_RX_READY BIT(25)
54/* global control register list */
55#define GLB_HOSTMAC_L32 0x0000
56#define GLB_HOSTMAC_H16 0x0004
57#define GLB_SOFT_RESET 0x0008
58#define SOFT_RESET_ALL BIT(0)
59#define GLB_FWCTRL 0x0010
60#define FWCTRL_VLAN_ENABLE BIT(0)
61#define FWCTRL_FW2CPU_ENA BIT(5)
62#define FWCTRL_FWALL2CPU BIT(7)
63#define GLB_MACTCTRL 0x0014
64#define MACTCTRL_UNI2CPU BIT(1)
65#define MACTCTRL_MULTI2CPU BIT(3)
66#define MACTCTRL_BROAD2CPU BIT(5)
67#define MACTCTRL_MACT_ENA BIT(7)
68#define GLB_IRQ_STAT 0x0030
69#define GLB_IRQ_ENA 0x0034
70#define IRQ_ENA_PORT0_MASK GENMASK(7, 0)
71#define IRQ_ENA_PORT0 BIT(18)
72#define IRQ_ENA_ALL BIT(19)
73#define GLB_IRQ_RAW 0x0038
74#define IRQ_INT_RX_RDY BIT(0)
75#define IRQ_INT_TX_PER_PACKET BIT(1)
76#define IRQ_INT_TX_FIFO_EMPTY BIT(6)
77#define IRQ_INT_MULTI_RXRDY BIT(7)
78#define DEF_INT_MASK (IRQ_INT_MULTI_RXRDY | \
79 IRQ_INT_TX_PER_PACKET | \
80 IRQ_INT_TX_FIFO_EMPTY)
81#define GLB_MAC_L32_BASE 0x0100
82#define GLB_MAC_H16_BASE 0x0104
83#define MACFLT_HI16_MASK GENMASK(15, 0)
84#define BIT_MACFLT_ENA BIT(17)
85#define BIT_MACFLT_FW2CPU BIT(21)
86#define GLB_MAC_H16(reg) (GLB_MAC_H16_BASE + ((reg) * 0x8))
87#define GLB_MAC_L32(reg) (GLB_MAC_L32_BASE + ((reg) * 0x8))
88#define MAX_MAC_FILTER_NUM 8
89#define MAX_UNICAST_ADDRESSES 2
90#define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - \
91 MAX_UNICAST_ADDRESSES)
92/* software tx and rx queue number, should be power of 2 */
93#define TXQ_NUM 64
94#define RXQ_NUM 128
95
96#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us"
97#define MAC_RESET_DELAY_PROPERTY "hisilicon,mac-reset-delay-us"
98#define MAC_RESET_ASSERT_PERIOD 200000
99
100enum phy_reset_delays {
101 PRE_DELAY,
102 PULSE,
103 POST_DELAY,
104 DELAYS_NUM,
105};
106
107enum clk_type {
108 CLK_MAC,
109 CLK_BUS,
110 CLK_PHY,
111 CLK_NUM,
112};
113
114struct hisi_femac_priv {
115 void __iomem *port_base;
116 void __iomem *glb_base;
117 struct clk *clks[CLK_NUM];
118 struct reset_ctl *mac_rst;
119 struct reset_ctl *phy_rst;
120 u32 phy_reset_delays[DELAYS_NUM];
121 u32 mac_reset_delay;
122
123 struct phy_device *phy;
124
125 u32 link_status;
126};
127
128static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs)
129{
130 u32 val;
131
132 val = readl(priv->glb_base + GLB_IRQ_ENA);
133 writel(val | irqs, priv->glb_base + GLB_IRQ_ENA);
134}
135
136static void hisi_femac_irq_disable(struct hisi_femac_priv *priv, int irqs)
137{
138 u32 val;
139
140 val = readl(priv->glb_base + GLB_IRQ_ENA);
141 writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA);
142}
143
144static void hisi_femac_port_init(struct hisi_femac_priv *priv)
145{
146 u32 val;
147
148 /* MAC gets link status info and phy mode by software config */
149 val = MAC_PORTSEL_STAT_CPU;
150 if (priv->phy->interface == PHY_INTERFACE_MODE_RMII)
151 val |= MAC_PORTSEL_RMII;
152 writel(val, priv->port_base + MAC_PORTSEL);
153
154 /*clear all interrupt status */
155 writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW);
156 hisi_femac_irq_disable(priv, IRQ_ENA_PORT0_MASK | IRQ_ENA_PORT0);
157
158 val = readl(priv->glb_base + GLB_FWCTRL);
159 val &= ~(FWCTRL_VLAN_ENABLE | FWCTRL_FWALL2CPU);
160 val |= FWCTRL_FW2CPU_ENA;
161 writel(val, priv->glb_base + GLB_FWCTRL);
162
163 val = readl(priv->glb_base + GLB_MACTCTRL);
164 val |= (MACTCTRL_BROAD2CPU | MACTCTRL_MACT_ENA);
165 writel(val, priv->glb_base + GLB_MACTCTRL);
166
167 val = readl(priv->port_base + MAC_SET);
168 val &= ~MAX_FRAME_SIZE_MASK;
169 val |= MAX_FRAME_SIZE;
170 writel(val, priv->port_base + MAC_SET);
171
172 val = RX_COALESCED_TIMER |
173 (RX_COALESCED_FRAMES << RX_COALESCED_FRAME_OFFSET);
174 writel(val, priv->port_base + RX_COALESCE_SET);
175
176 val = (HW_RX_FIFO_DEPTH << RX_DEPTH_OFFSET) | HW_TX_FIFO_DEPTH;
177 writel(val, priv->port_base + QLEN_SET);
178}
179
180static void hisi_femac_rx_refill(struct hisi_femac_priv *priv)
181{
182 int i;
183 ulong addr;
184
185 for (i = 0; i < HW_RX_FIFO_DEPTH; i++) {
186 addr = (ulong)net_rx_packets[i];
187 writel(addr, priv->port_base + IQ_ADDR);
188 }
189}
190
191static void hisi_femac_adjust_link(struct udevice *dev)
192{
193 struct hisi_femac_priv *priv = dev_get_priv(dev);
194 struct phy_device *phy = priv->phy;
195 u32 status = 0;
196
197 if (phy->link)
198 status |= MAC_PORTSET_LINKED;
199 if (phy->duplex == DUPLEX_FULL)
200 status |= MAC_PORTSET_DUPLEX_FULL;
201 if (phy->speed == SPEED_100)
202 status |= MAC_PORTSET_SPEED_100M;
203
204 writel(status, priv->port_base + MAC_PORTSET);
205}
206
207static int hisi_femac_port_reset(struct hisi_femac_priv *priv)
208{
209 u32 val;
210
211 val = readl(priv->glb_base + GLB_SOFT_RESET);
212 val |= SOFT_RESET_ALL;
213 writel(val, priv->glb_base + GLB_SOFT_RESET);
214
215 udelay(800);
216
217 val &= ~SOFT_RESET_ALL;
218 writel(val, priv->glb_base + GLB_SOFT_RESET);
219
220 return 0;
221}
222
223static int hisi_femac_set_hw_mac_addr(struct udevice *dev)
224{
225 struct hisi_femac_priv *priv = dev_get_priv(dev);
226 struct eth_pdata *plat = dev_get_plat(dev);
227 unsigned char *mac = plat->enetaddr;
228 u32 reg;
229
230 reg = mac[1] | (mac[0] << 8);
231 writel(reg, priv->glb_base + GLB_HOSTMAC_H16);
232
233 reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24);
234 writel(reg, priv->glb_base + GLB_HOSTMAC_L32);
235
236 return 0;
237}
238
239static int hisi_femac_start(struct udevice *dev)
240{
241 int ret;
242 struct hisi_femac_priv *priv = dev_get_priv(dev);
243
244 hisi_femac_port_reset(priv);
245 hisi_femac_set_hw_mac_addr(dev);
246 hisi_femac_rx_refill(priv);
247
248 ret = phy_startup(priv->phy);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800249 if (ret) {
250 dev_err(dev, "Failed to startup phy: %d\n", ret);
251 return log_msg_ret("phy", ret);
252 }
Yang Xiwend9717112023-08-23 01:03:42 +0800253
254 if (!priv->phy->link) {
255 debug("%s: link down\n", __func__);
256 return -ENODEV;
257 }
258
259 hisi_femac_adjust_link(dev);
260
261 writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW);
262 hisi_femac_irq_enable(priv, IRQ_ENA_ALL | IRQ_ENA_PORT0 | DEF_INT_MASK);
263
264 return 0;
265}
266
267static int hisi_femac_send(struct udevice *dev, void *packet, int length)
268{
269 struct hisi_femac_priv *priv = dev_get_priv(dev);
270 ulong addr = (ulong)packet;
271 int ret;
272
273 // clear previous irq
274 writel(IRQ_INT_TX_PER_PACKET, priv->glb_base + GLB_IRQ_RAW);
275
276 // flush cache
277 flush_cache(addr, length + ETH_FCS_LEN);
278
279 // write packet address
280 writel(addr, priv->port_base + EQ_ADDR);
281
282 // write packet length (and send it)
283 writel(length + ETH_FCS_LEN, priv->port_base + EQFRM_LEN);
284
285 // wait until FIFO is empty
286 ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, IRQ_INT_TX_PER_PACKET, true, 50, false);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800287 if (ret == -ETIMEDOUT) {
288 dev_err(dev, "FIFO timeout\n");
289 return log_msg_ret("net", ret);
290 }
Yang Xiwend9717112023-08-23 01:03:42 +0800291
292 return 0;
293}
294
295static int hisi_femac_recv(struct udevice *dev, int flags, uchar **packetp)
296{
297 struct hisi_femac_priv *priv = dev_get_priv(dev);
298 int val, index, length;
299
300 val = readl(priv->glb_base + GLB_IRQ_RAW);
301 if (!(val & IRQ_INT_RX_RDY))
302 return -EAGAIN;
303
304 val = readl(priv->port_base + IQFRM_DES);
305 index = (val & RX_FRAME_IN_INDEX_MASK) >> 12;
306 length = val & RX_FRAME_LEN_MASK;
307
308 // invalidate cache
309 invalidate_dcache_range((ulong)net_rx_packets[index], (ulong)net_rx_packets[index] + length);
310 *packetp = net_rx_packets[index];
311
312 // Tell hardware we will process the packet
313 writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW);
314
315 return length;
316}
317
318static int hisi_femac_free_pkt(struct udevice *dev, uchar *packet, int length)
319{
320 struct hisi_femac_priv *priv = dev_get_priv(dev);
321 ulong addr = (ulong)packet;
322
323 // Tell hardware the packet can be reused
324 writel(addr, priv->port_base + IQ_ADDR);
325
326 return 0;
327}
328
329static void hisi_femac_stop(struct udevice *dev)
330{
331 struct hisi_femac_priv *priv = dev_get_priv(dev);
332
333 // assert internal reset
334 writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET);
335}
336
337int hisi_femac_of_to_plat(struct udevice *dev)
338{
339 int ret, i;
340 struct hisi_femac_priv *priv = dev_get_priv(dev);
Yang Xiwen7579ad12024-01-22 22:33:22 +0800341 ofnode mdio_node;
342 bool mdio_registered = false;
Yang Xiwend9717112023-08-23 01:03:42 +0800343 static const char * const clk_strs[] = {
344 [CLK_MAC] = "mac",
345 [CLK_BUS] = "bus",
346 [CLK_PHY] = "phy",
347 };
348
349 priv->port_base = dev_remap_addr_name(dev, "port");
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800350 if (!priv->port_base) {
351 dev_err(dev, "Failed to remap port address space\n");
352 return log_msg_ret("net", -EINVAL);
353 }
Yang Xiwend9717112023-08-23 01:03:42 +0800354
355 priv->glb_base = dev_remap_addr_name(dev, "glb");
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800356 if (IS_ERR(priv->glb_base)) {
357 dev_err(dev, "Failed to remap global address space\n");
358 return log_msg_ret("net", -EINVAL);
359 }
Yang Xiwend9717112023-08-23 01:03:42 +0800360
361 for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
362 priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
363 if (IS_ERR(priv->clks[i])) {
364 dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800365 return log_msg_ret("clk", PTR_ERR(priv->clks[i]));
Yang Xiwend9717112023-08-23 01:03:42 +0800366 }
367 }
368
369 priv->mac_rst = devm_reset_control_get(dev, "mac");
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800370 if (IS_ERR(priv->mac_rst)) {
371 dev_err(dev, "Failed to get MAC reset %ld\n", PTR_ERR(priv->mac_rst));
372 return log_msg_ret("rst", PTR_ERR(priv->mac_rst));
373 }
Yang Xiwend9717112023-08-23 01:03:42 +0800374
375 priv->phy_rst = devm_reset_control_get(dev, "phy");
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800376 if (IS_ERR(priv->phy_rst)) {
377 dev_err(dev, "Failed to get PHY reset %ld\n", PTR_ERR(priv->phy_rst));
378 return log_msg_ret("rst", PTR_ERR(priv->phy_rst));
379 }
Yang Xiwend9717112023-08-23 01:03:42 +0800380
381 ret = dev_read_u32_array(dev,
382 PHY_RESET_DELAYS_PROPERTY,
383 priv->phy_reset_delays,
384 DELAYS_NUM);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800385 if (ret < 0) {
386 dev_err(dev, "Failed to get PHY reset delays %d\n", ret);
387 return log_msg_ret("rst", ret);
388 }
Yang Xiwend9717112023-08-23 01:03:42 +0800389
390 priv->mac_reset_delay = dev_read_u32_default(dev,
391 MAC_RESET_DELAY_PROPERTY,
392 MAC_RESET_ASSERT_PERIOD);
393
Yang Xiwen7579ad12024-01-22 22:33:22 +0800394 /* Create MDIO bus */
395 ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) {
396 const char *subnode_name = ofnode_get_name(mdio_node);
397 struct udevice *mdiodev;
398
399 // Skip subnodes not starting with "mdio"
400 if (strncmp(subnode_name, "mdio", 4))
401 continue;
402
403 ret = device_bind_driver_to_node(dev, "hisi-femac-mdio",
404 subnode_name, mdio_node, &mdiodev);
405 if (ret) {
406 dev_err(dev, "Failed to register MDIO bus device %d\n", ret);
407 return log_msg_ret("net", ret);
408 }
409
410 mdio_registered = true;
411 break;
412 }
413
414 if (!mdio_registered) {
415 dev_err(dev, "No MDIO subnode is found!\n");
416 return log_msg_ret("mdio", -ENODATA);
417 }
418
Yang Xiwend9717112023-08-23 01:03:42 +0800419 return 0;
420}
421
422static int hisi_femac_phy_reset(struct hisi_femac_priv *priv)
423{
424 struct reset_ctl *rst = priv->phy_rst;
425 u32 *delays = priv->phy_reset_delays;
426 int ret;
427
428 // Disable MAC clk before phy reset
429 ret = clk_disable(priv->clks[CLK_MAC]);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800430 if (ret < 0) {
431 pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret);
432 return log_msg_ret("clk", ret);
433 }
Yang Xiwend9717112023-08-23 01:03:42 +0800434 ret = clk_disable(priv->clks[CLK_BUS]);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800435 if (ret < 0) {
436 pr_err("%s: Failed to disable bus clock %d\n", __func__, ret);
437 return log_msg_ret("clk", ret);
438 }
Yang Xiwend9717112023-08-23 01:03:42 +0800439
440 udelay(delays[PRE_DELAY]);
441
442 ret = reset_assert(rst);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800443 if (ret < 0) {
444 pr_err("%s: Failed to assert reset %d\n", __func__, ret);
445 return log_msg_ret("rst", ret);
446 }
Yang Xiwend9717112023-08-23 01:03:42 +0800447
448 udelay(delays[PULSE]);
449
450 ret = reset_deassert(rst);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800451 if (ret < 0) {
452 pr_err("%s: Failed to deassert reset %d\n", __func__, ret);
453 return log_msg_ret("rst", ret);
454 }
Yang Xiwend9717112023-08-23 01:03:42 +0800455
456 udelay(delays[POST_DELAY]);
457
458 ret = clk_enable(priv->clks[CLK_MAC]);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800459 if (ret < 0) {
460 pr_err("%s: Failed to enable MAC clock %d\n", __func__, ret);
461 return log_msg_ret("clk", ret);
462 }
Yang Xiwend9717112023-08-23 01:03:42 +0800463 ret = clk_enable(priv->clks[CLK_BUS]);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800464 if (ret < 0) {
465 pr_err("%s: Failed to enable MAC bus clock %d\n", __func__, ret);
466 return log_msg_ret("clk", ret);
467 }
Yang Xiwend9717112023-08-23 01:03:42 +0800468
469 return 0;
470}
471
472int hisi_femac_probe(struct udevice *dev)
473{
474 struct hisi_femac_priv *priv = dev_get_priv(dev);
475 int ret, i;
476
477 // Enable clocks
478 for (i = 0; i < CLK_NUM; i++) {
479 ret = clk_prepare_enable(priv->clks[i]);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800480 if (ret < 0) {
481 dev_err(dev, "Failed to enable clk %d: %d\n", i, ret);
482 return log_msg_ret("clk", ret);
483 }
Yang Xiwend9717112023-08-23 01:03:42 +0800484 }
485
486 // Reset MAC
487 ret = reset_assert(priv->mac_rst);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800488 if (ret < 0) {
489 dev_err(dev, "Failed to assert MAC reset: %d\n", ret);
490 return log_msg_ret("net", ret);
491 }
Yang Xiwend9717112023-08-23 01:03:42 +0800492
493 udelay(priv->mac_reset_delay);
494
495 ret = reset_deassert(priv->mac_rst);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800496 if (ret < 0) {
497 dev_err(dev, "Failed to deassert MAC reset: %d\n", ret);
498 return log_msg_ret("net", ret);
499 }
Yang Xiwend9717112023-08-23 01:03:42 +0800500
501 // Reset PHY
502 ret = hisi_femac_phy_reset(priv);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800503 if (ret < 0) {
504 dev_err(dev, "Failed to reset PHY: %d\n", ret);
505 return log_msg_ret("net", ret);
506 }
Yang Xiwend9717112023-08-23 01:03:42 +0800507
508 // Connect to PHY
509 priv->phy = dm_eth_phy_connect(dev);
Yang Xiwenf56b07b2024-01-22 22:33:21 +0800510 if (!priv->phy) {
511 dev_err(dev, "Failed to connect to phy\n");
512 return log_msg_ret("phy", -EINVAL);
513 }
Yang Xiwend9717112023-08-23 01:03:42 +0800514
515 hisi_femac_port_init(priv);
516 return 0;
517}
518
519static const struct eth_ops hisi_femac_ops = {
520 .start = hisi_femac_start,
521 .send = hisi_femac_send,
522 .recv = hisi_femac_recv,
523 .free_pkt = hisi_femac_free_pkt,
524 .stop = hisi_femac_stop,
525 .write_hwaddr = hisi_femac_set_hw_mac_addr,
526};
527
528static const struct udevice_id hisi_femac_ids[] = {
529 {.compatible = "hisilicon,hisi-femac-v1",},
530 {.compatible = "hisilicon,hisi-femac-v2",},
531 {.compatible = "hisilicon,hi3516cv300-femac",},
532 {.compatible = "hisilicon,hi3798mv200-femac",},
533 {},
534};
535
536U_BOOT_DRIVER(hisi_femac_driver) = {
537 .name = "eth_hisi_femac",
538 .id = UCLASS_ETH,
539 .of_match = of_match_ptr(hisi_femac_ids),
540 .of_to_plat = hisi_femac_of_to_plat,
541 .ops = &hisi_femac_ops,
542 .probe = hisi_femac_probe,
543 .plat_auto = sizeof(struct eth_pdata),
544 .priv_auto = sizeof(struct hisi_femac_priv),
545};