blob: b61a29e636085cc3cb31c61c6f2a71c88ac3f72d [file] [log] [blame]
Yang Xiwen9d8f78a2023-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>
18#include <linux/delay.h>
19#include <linux/kernel.h>
20
21/* MAC control register list */
22#define MAC_PORTSEL 0x0200
23#define MAC_PORTSEL_STAT_CPU BIT(0)
24#define MAC_PORTSEL_RMII BIT(1)
25#define MAC_PORTSET 0x0208
26#define MAC_PORTSET_DUPLEX_FULL BIT(0)
27#define MAC_PORTSET_LINKED BIT(1)
28#define MAC_PORTSET_SPEED_100M BIT(2)
29#define MAC_SET 0x0210
30#define MAX_FRAME_SIZE 1600
31#define MAX_FRAME_SIZE_MASK GENMASK(10, 0)
32#define BIT_PAUSE_EN BIT(18)
33#define RX_COALESCE_SET 0x0340
34#define RX_COALESCED_FRAME_OFFSET 24
35#define RX_COALESCED_FRAMES 8
36#define RX_COALESCED_TIMER 0x74
37#define QLEN_SET 0x0344
38#define RX_DEPTH_OFFSET 8
39#define MAX_HW_FIFO_DEPTH 64
40#define HW_TX_FIFO_DEPTH 1
41#define MAX_HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
42#define HW_RX_FIFO_DEPTH min(PKTBUFSRX, MAX_HW_RX_FIFO_DEPTH)
43#define IQFRM_DES 0x0354
44#define RX_FRAME_LEN_MASK GENMASK(11, 0)
45#define RX_FRAME_IN_INDEX_MASK GENMASK(17, 12)
46#define IQ_ADDR 0x0358
47#define EQ_ADDR 0x0360
48#define EQFRM_LEN 0x0364
49#define ADDRQ_STAT 0x036C
50#define TX_CNT_INUSE_MASK GENMASK(5, 0)
51#define BIT_TX_READY BIT(24)
52#define BIT_RX_READY BIT(25)
53/* global control register list */
54#define GLB_HOSTMAC_L32 0x0000
55#define GLB_HOSTMAC_H16 0x0004
56#define GLB_SOFT_RESET 0x0008
57#define SOFT_RESET_ALL BIT(0)
58#define GLB_FWCTRL 0x0010
59#define FWCTRL_VLAN_ENABLE BIT(0)
60#define FWCTRL_FW2CPU_ENA BIT(5)
61#define FWCTRL_FWALL2CPU BIT(7)
62#define GLB_MACTCTRL 0x0014
63#define MACTCTRL_UNI2CPU BIT(1)
64#define MACTCTRL_MULTI2CPU BIT(3)
65#define MACTCTRL_BROAD2CPU BIT(5)
66#define MACTCTRL_MACT_ENA BIT(7)
67#define GLB_IRQ_STAT 0x0030
68#define GLB_IRQ_ENA 0x0034
69#define IRQ_ENA_PORT0_MASK GENMASK(7, 0)
70#define IRQ_ENA_PORT0 BIT(18)
71#define IRQ_ENA_ALL BIT(19)
72#define GLB_IRQ_RAW 0x0038
73#define IRQ_INT_RX_RDY BIT(0)
74#define IRQ_INT_TX_PER_PACKET BIT(1)
75#define IRQ_INT_TX_FIFO_EMPTY BIT(6)
76#define IRQ_INT_MULTI_RXRDY BIT(7)
77#define DEF_INT_MASK (IRQ_INT_MULTI_RXRDY | \
78 IRQ_INT_TX_PER_PACKET | \
79 IRQ_INT_TX_FIFO_EMPTY)
80#define GLB_MAC_L32_BASE 0x0100
81#define GLB_MAC_H16_BASE 0x0104
82#define MACFLT_HI16_MASK GENMASK(15, 0)
83#define BIT_MACFLT_ENA BIT(17)
84#define BIT_MACFLT_FW2CPU BIT(21)
85#define GLB_MAC_H16(reg) (GLB_MAC_H16_BASE + ((reg) * 0x8))
86#define GLB_MAC_L32(reg) (GLB_MAC_L32_BASE + ((reg) * 0x8))
87#define MAX_MAC_FILTER_NUM 8
88#define MAX_UNICAST_ADDRESSES 2
89#define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - \
90 MAX_UNICAST_ADDRESSES)
91/* software tx and rx queue number, should be power of 2 */
92#define TXQ_NUM 64
93#define RXQ_NUM 128
94
95#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us"
96#define MAC_RESET_DELAY_PROPERTY "hisilicon,mac-reset-delay-us"
97#define MAC_RESET_ASSERT_PERIOD 200000
98
99enum phy_reset_delays {
100 PRE_DELAY,
101 PULSE,
102 POST_DELAY,
103 DELAYS_NUM,
104};
105
106enum clk_type {
107 CLK_MAC,
108 CLK_BUS,
109 CLK_PHY,
110 CLK_NUM,
111};
112
113struct hisi_femac_priv {
114 void __iomem *port_base;
115 void __iomem *glb_base;
116 struct clk *clks[CLK_NUM];
117 struct reset_ctl *mac_rst;
118 struct reset_ctl *phy_rst;
119 u32 phy_reset_delays[DELAYS_NUM];
120 u32 mac_reset_delay;
121
122 struct phy_device *phy;
123
124 u32 link_status;
125};
126
127static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs)
128{
129 u32 val;
130
131 val = readl(priv->glb_base + GLB_IRQ_ENA);
132 writel(val | irqs, priv->glb_base + GLB_IRQ_ENA);
133}
134
135static void hisi_femac_irq_disable(struct hisi_femac_priv *priv, int irqs)
136{
137 u32 val;
138
139 val = readl(priv->glb_base + GLB_IRQ_ENA);
140 writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA);
141}
142
143static void hisi_femac_port_init(struct hisi_femac_priv *priv)
144{
145 u32 val;
146
147 /* MAC gets link status info and phy mode by software config */
148 val = MAC_PORTSEL_STAT_CPU;
149 if (priv->phy->interface == PHY_INTERFACE_MODE_RMII)
150 val |= MAC_PORTSEL_RMII;
151 writel(val, priv->port_base + MAC_PORTSEL);
152
153 /*clear all interrupt status */
154 writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW);
155 hisi_femac_irq_disable(priv, IRQ_ENA_PORT0_MASK | IRQ_ENA_PORT0);
156
157 val = readl(priv->glb_base + GLB_FWCTRL);
158 val &= ~(FWCTRL_VLAN_ENABLE | FWCTRL_FWALL2CPU);
159 val |= FWCTRL_FW2CPU_ENA;
160 writel(val, priv->glb_base + GLB_FWCTRL);
161
162 val = readl(priv->glb_base + GLB_MACTCTRL);
163 val |= (MACTCTRL_BROAD2CPU | MACTCTRL_MACT_ENA);
164 writel(val, priv->glb_base + GLB_MACTCTRL);
165
166 val = readl(priv->port_base + MAC_SET);
167 val &= ~MAX_FRAME_SIZE_MASK;
168 val |= MAX_FRAME_SIZE;
169 writel(val, priv->port_base + MAC_SET);
170
171 val = RX_COALESCED_TIMER |
172 (RX_COALESCED_FRAMES << RX_COALESCED_FRAME_OFFSET);
173 writel(val, priv->port_base + RX_COALESCE_SET);
174
175 val = (HW_RX_FIFO_DEPTH << RX_DEPTH_OFFSET) | HW_TX_FIFO_DEPTH;
176 writel(val, priv->port_base + QLEN_SET);
177}
178
179static void hisi_femac_rx_refill(struct hisi_femac_priv *priv)
180{
181 int i;
182 ulong addr;
183
184 for (i = 0; i < HW_RX_FIFO_DEPTH; i++) {
185 addr = (ulong)net_rx_packets[i];
186 writel(addr, priv->port_base + IQ_ADDR);
187 }
188}
189
190static void hisi_femac_adjust_link(struct udevice *dev)
191{
192 struct hisi_femac_priv *priv = dev_get_priv(dev);
193 struct phy_device *phy = priv->phy;
194 u32 status = 0;
195
196 if (phy->link)
197 status |= MAC_PORTSET_LINKED;
198 if (phy->duplex == DUPLEX_FULL)
199 status |= MAC_PORTSET_DUPLEX_FULL;
200 if (phy->speed == SPEED_100)
201 status |= MAC_PORTSET_SPEED_100M;
202
203 writel(status, priv->port_base + MAC_PORTSET);
204}
205
206static int hisi_femac_port_reset(struct hisi_femac_priv *priv)
207{
208 u32 val;
209
210 val = readl(priv->glb_base + GLB_SOFT_RESET);
211 val |= SOFT_RESET_ALL;
212 writel(val, priv->glb_base + GLB_SOFT_RESET);
213
214 udelay(800);
215
216 val &= ~SOFT_RESET_ALL;
217 writel(val, priv->glb_base + GLB_SOFT_RESET);
218
219 return 0;
220}
221
222static int hisi_femac_set_hw_mac_addr(struct udevice *dev)
223{
224 struct hisi_femac_priv *priv = dev_get_priv(dev);
225 struct eth_pdata *plat = dev_get_plat(dev);
226 unsigned char *mac = plat->enetaddr;
227 u32 reg;
228
229 reg = mac[1] | (mac[0] << 8);
230 writel(reg, priv->glb_base + GLB_HOSTMAC_H16);
231
232 reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24);
233 writel(reg, priv->glb_base + GLB_HOSTMAC_L32);
234
235 return 0;
236}
237
238static int hisi_femac_start(struct udevice *dev)
239{
240 int ret;
241 struct hisi_femac_priv *priv = dev_get_priv(dev);
242
243 hisi_femac_port_reset(priv);
244 hisi_femac_set_hw_mac_addr(dev);
245 hisi_femac_rx_refill(priv);
246
247 ret = phy_startup(priv->phy);
248 if (ret)
249 return log_msg_ret("Failed to startup phy", ret);
250
251 if (!priv->phy->link) {
252 debug("%s: link down\n", __func__);
253 return -ENODEV;
254 }
255
256 hisi_femac_adjust_link(dev);
257
258 writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW);
259 hisi_femac_irq_enable(priv, IRQ_ENA_ALL | IRQ_ENA_PORT0 | DEF_INT_MASK);
260
261 return 0;
262}
263
264static int hisi_femac_send(struct udevice *dev, void *packet, int length)
265{
266 struct hisi_femac_priv *priv = dev_get_priv(dev);
267 ulong addr = (ulong)packet;
268 int ret;
269
270 // clear previous irq
271 writel(IRQ_INT_TX_PER_PACKET, priv->glb_base + GLB_IRQ_RAW);
272
273 // flush cache
274 flush_cache(addr, length + ETH_FCS_LEN);
275
276 // write packet address
277 writel(addr, priv->port_base + EQ_ADDR);
278
279 // write packet length (and send it)
280 writel(length + ETH_FCS_LEN, priv->port_base + EQFRM_LEN);
281
282 // wait until FIFO is empty
283 ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, IRQ_INT_TX_PER_PACKET, true, 50, false);
284 if (ret == -ETIMEDOUT)
285 return log_msg_ret("FIFO timeout", ret);
286
287 return 0;
288}
289
290static int hisi_femac_recv(struct udevice *dev, int flags, uchar **packetp)
291{
292 struct hisi_femac_priv *priv = dev_get_priv(dev);
293 int val, index, length;
294
295 val = readl(priv->glb_base + GLB_IRQ_RAW);
296 if (!(val & IRQ_INT_RX_RDY))
297 return -EAGAIN;
298
299 val = readl(priv->port_base + IQFRM_DES);
300 index = (val & RX_FRAME_IN_INDEX_MASK) >> 12;
301 length = val & RX_FRAME_LEN_MASK;
302
303 // invalidate cache
304 invalidate_dcache_range((ulong)net_rx_packets[index], (ulong)net_rx_packets[index] + length);
305 *packetp = net_rx_packets[index];
306
307 // Tell hardware we will process the packet
308 writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW);
309
310 return length;
311}
312
313static int hisi_femac_free_pkt(struct udevice *dev, uchar *packet, int length)
314{
315 struct hisi_femac_priv *priv = dev_get_priv(dev);
316 ulong addr = (ulong)packet;
317
318 // Tell hardware the packet can be reused
319 writel(addr, priv->port_base + IQ_ADDR);
320
321 return 0;
322}
323
324static void hisi_femac_stop(struct udevice *dev)
325{
326 struct hisi_femac_priv *priv = dev_get_priv(dev);
327
328 // assert internal reset
329 writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET);
330}
331
332int hisi_femac_of_to_plat(struct udevice *dev)
333{
334 int ret, i;
335 struct hisi_femac_priv *priv = dev_get_priv(dev);
336 static const char * const clk_strs[] = {
337 [CLK_MAC] = "mac",
338 [CLK_BUS] = "bus",
339 [CLK_PHY] = "phy",
340 };
341
342 priv->port_base = dev_remap_addr_name(dev, "port");
343 if (IS_ERR(priv->port_base))
344 return log_msg_ret("Failed to remap port address space", PTR_ERR(priv->port_base));
345
346 priv->glb_base = dev_remap_addr_name(dev, "glb");
347 if (IS_ERR(priv->glb_base))
348 return log_msg_ret("Failed to remap global address space", PTR_ERR(priv->glb_base));
349
350 for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
351 priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
352 if (IS_ERR(priv->clks[i])) {
353 dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
354 return log_msg_ret("Failed to get clocks", PTR_ERR(priv->clks[i]));
355 }
356 }
357
358 priv->mac_rst = devm_reset_control_get(dev, "mac");
359 if (IS_ERR(priv->mac_rst))
360 return log_msg_ret("Failed to get MAC reset", PTR_ERR(priv->mac_rst));
361
362 priv->phy_rst = devm_reset_control_get(dev, "phy");
363 if (IS_ERR(priv->phy_rst))
364 return log_msg_ret("Failed to get PHY reset", PTR_ERR(priv->phy_rst));
365
366 ret = dev_read_u32_array(dev,
367 PHY_RESET_DELAYS_PROPERTY,
368 priv->phy_reset_delays,
369 DELAYS_NUM);
370 if (ret < 0)
371 return log_msg_ret("Failed to get PHY reset delays", ret);
372
373 priv->mac_reset_delay = dev_read_u32_default(dev,
374 MAC_RESET_DELAY_PROPERTY,
375 MAC_RESET_ASSERT_PERIOD);
376
377 return 0;
378}
379
380static int hisi_femac_phy_reset(struct hisi_femac_priv *priv)
381{
382 struct reset_ctl *rst = priv->phy_rst;
383 u32 *delays = priv->phy_reset_delays;
384 int ret;
385
386 // Disable MAC clk before phy reset
387 ret = clk_disable(priv->clks[CLK_MAC]);
388 if (ret < 0)
389 return log_msg_ret("Failed to disable MAC clock", ret);
390 ret = clk_disable(priv->clks[CLK_BUS]);
391 if (ret < 0)
392 return log_msg_ret("Failed to disable bus clock", ret);
393
394 udelay(delays[PRE_DELAY]);
395
396 ret = reset_assert(rst);
397 if (ret < 0)
398 return log_msg_ret("Failed to assert reset", ret);
399
400 udelay(delays[PULSE]);
401
402 ret = reset_deassert(rst);
403 if (ret < 0)
404 return log_msg_ret("Failed to deassert reset", ret);
405
406 udelay(delays[POST_DELAY]);
407
408 ret = clk_enable(priv->clks[CLK_MAC]);
409 if (ret < 0)
410 return log_msg_ret("Failed to enable MAC clock", ret);
411 ret = clk_enable(priv->clks[CLK_BUS]);
412 if (ret < 0)
413 return log_msg_ret("Failed to enable MAC bus clock", ret);
414
415 return 0;
416}
417
418int hisi_femac_probe(struct udevice *dev)
419{
420 struct hisi_femac_priv *priv = dev_get_priv(dev);
421 int ret, i;
422
423 // Enable clocks
424 for (i = 0; i < CLK_NUM; i++) {
425 ret = clk_prepare_enable(priv->clks[i]);
426 if (ret < 0)
427 return log_msg_ret("Failed to enable clks", ret);
428 }
429
430 // Reset MAC
431 ret = reset_assert(priv->mac_rst);
432 if (ret < 0)
433 return log_msg_ret("Failed to assert MAC reset", ret);
434
435 udelay(priv->mac_reset_delay);
436
437 ret = reset_deassert(priv->mac_rst);
438 if (ret < 0)
439 return log_msg_ret("Failed to deassert MAC reset", ret);
440
441 // Reset PHY
442 ret = hisi_femac_phy_reset(priv);
443 if (ret < 0)
444 return log_msg_ret("Failed to reset phy", ret);
445
446 // Connect to PHY
447 priv->phy = dm_eth_phy_connect(dev);
448 if (!priv->phy)
449 return log_msg_ret("Failed to connect to phy", -EINVAL);
450
451 hisi_femac_port_init(priv);
452 return 0;
453}
454
455static const struct eth_ops hisi_femac_ops = {
456 .start = hisi_femac_start,
457 .send = hisi_femac_send,
458 .recv = hisi_femac_recv,
459 .free_pkt = hisi_femac_free_pkt,
460 .stop = hisi_femac_stop,
461 .write_hwaddr = hisi_femac_set_hw_mac_addr,
462};
463
464static const struct udevice_id hisi_femac_ids[] = {
465 {.compatible = "hisilicon,hisi-femac-v1",},
466 {.compatible = "hisilicon,hisi-femac-v2",},
467 {.compatible = "hisilicon,hi3516cv300-femac",},
468 {.compatible = "hisilicon,hi3798mv200-femac",},
469 {},
470};
471
472U_BOOT_DRIVER(hisi_femac_driver) = {
473 .name = "eth_hisi_femac",
474 .id = UCLASS_ETH,
475 .of_match = of_match_ptr(hisi_femac_ids),
476 .of_to_plat = hisi_femac_of_to_plat,
477 .ops = &hisi_femac_ops,
478 .probe = hisi_femac_probe,
479 .plat_auto = sizeof(struct eth_pdata),
480 .priv_auto = sizeof(struct hisi_femac_priv),
481};