Commit 0125bcf01cfb0715b35ab9d5325479b3953bb966
Committed by
Simon Glass
1 parent
e72ced2340
Exists in
smarc_8mq_lf_v2020.04
and in
22 other branches
net: gmac_rockchip: Add Rockchip GMAC driver
Add a new driver for the GMAC ethernet interface present in Rockchip RK3288 SOCs. This driver subclasses the generic design-ware driver to add the glue needed specifically for Rockchip. Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Signed-off-by: Simon Glass <sjg@chromium.org> Signed-off-by: Romain Perier <romain.perier@collabora.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Showing 3 changed files with 162 additions and 0 deletions Side-by-side Diff
drivers/net/Kconfig
... | ... | @@ -215,5 +215,12 @@ |
215 | 215 | This driver implements 10/100 Mbps Ethernet and MAC layer for |
216 | 216 | Microchip PIC32 microcontrollers. |
217 | 217 | |
218 | +config GMAC_ROCKCHIP | |
219 | + bool "Rockchip Synopsys Designware Ethernet MAC" | |
220 | + depends on DM_ETH && ETH_DESIGNWARE | |
221 | + help | |
222 | + This driver provides Rockchip SoCs network support based on the | |
223 | + Synopsys Designware driver. | |
224 | + | |
218 | 225 | endif # NETDEVICES |
drivers/net/Makefile
... | ... | @@ -34,6 +34,7 @@ |
34 | 34 | obj-$(CONFIG_FTMAC110) += ftmac110.o |
35 | 35 | obj-$(CONFIG_FTMAC100) += ftmac100.o |
36 | 36 | obj-$(CONFIG_GRETH) += greth.o |
37 | +obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o | |
37 | 38 | obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o |
38 | 39 | obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o |
39 | 40 | obj-$(CONFIG_LAN91C96) += lan91c96.o |
drivers/net/gmac_rockchip.c
1 | +/* | |
2 | + * (C) Copyright 2015 Sjoerd Simons <sjoerd.simons@collabora.co.uk> | |
3 | + * | |
4 | + * SPDX-License-Identifier: GPL-2.0+ | |
5 | + * | |
6 | + * Rockchip GMAC ethernet IP driver for U-Boot | |
7 | + */ | |
8 | + | |
9 | +#include <common.h> | |
10 | +#include <dm.h> | |
11 | +#include <clk.h> | |
12 | +#include <phy.h> | |
13 | +#include <syscon.h> | |
14 | +#include <asm/io.h> | |
15 | +#include <asm/arch/periph.h> | |
16 | +#include <asm/arch/clock.h> | |
17 | +#include <asm/arch/grf_rk3288.h> | |
18 | +#include <dm/pinctrl.h> | |
19 | +#include <dt-bindings/clock/rk3288-cru.h> | |
20 | +#include "designware.h" | |
21 | + | |
22 | +DECLARE_GLOBAL_DATA_PTR; | |
23 | + | |
24 | +/* | |
25 | + * Platform data for the gmac | |
26 | + * | |
27 | + * dw_eth_pdata: Required platform data for designware driver (must be first) | |
28 | + */ | |
29 | +struct gmac_rockchip_platdata { | |
30 | + struct dw_eth_pdata dw_eth_pdata; | |
31 | + int tx_delay; | |
32 | + int rx_delay; | |
33 | +}; | |
34 | + | |
35 | +static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev) | |
36 | +{ | |
37 | + struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); | |
38 | + | |
39 | + pdata->tx_delay = fdtdec_get_int(gd->fdt_blob, dev->of_offset, | |
40 | + "tx-delay", 0x30); | |
41 | + pdata->rx_delay = fdtdec_get_int(gd->fdt_blob, dev->of_offset, | |
42 | + "rx-delay", 0x10); | |
43 | + | |
44 | + return designware_eth_ofdata_to_platdata(dev); | |
45 | +} | |
46 | + | |
47 | +static int gmac_rockchip_fix_mac_speed(struct dw_eth_dev *priv) | |
48 | +{ | |
49 | + struct rk3288_grf *grf; | |
50 | + int clk; | |
51 | + | |
52 | + switch (priv->phydev->speed) { | |
53 | + case 10: | |
54 | + clk = GMAC_CLK_SEL_2_5M; | |
55 | + break; | |
56 | + case 100: | |
57 | + clk = GMAC_CLK_SEL_25M; | |
58 | + break; | |
59 | + case 1000: | |
60 | + clk = GMAC_CLK_SEL_125M; | |
61 | + break; | |
62 | + default: | |
63 | + debug("Unknown phy speed: %d\n", priv->phydev->speed); | |
64 | + return -EINVAL; | |
65 | + } | |
66 | + | |
67 | + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
68 | + rk_clrsetreg(&grf->soc_con1, | |
69 | + GMAC_CLK_SEL_MASK << GMAC_CLK_SEL_SHIFT, | |
70 | + clk << GMAC_CLK_SEL_SHIFT); | |
71 | + | |
72 | + return 0; | |
73 | +} | |
74 | + | |
75 | +static int gmac_rockchip_probe(struct udevice *dev) | |
76 | +{ | |
77 | + struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); | |
78 | + struct rk3288_grf *grf; | |
79 | + struct clk clk; | |
80 | + int ret; | |
81 | + | |
82 | + ret = clk_get_by_index(dev, 0, &clk); | |
83 | + if (ret) | |
84 | + return ret; | |
85 | + | |
86 | + /* Since mac_clk is fed by an external clock we can use 0 here */ | |
87 | + ret = clk_set_rate(&clk, 0); | |
88 | + if (ret) | |
89 | + return ret; | |
90 | + | |
91 | + /* Set to RGMII mode */ | |
92 | + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
93 | + rk_clrsetreg(&grf->soc_con1, | |
94 | + RMII_MODE_MASK << RMII_MODE_SHIFT | | |
95 | + GMAC_PHY_INTF_SEL_MASK << GMAC_PHY_INTF_SEL_SHIFT, | |
96 | + GMAC_PHY_INTF_SEL_RGMII << GMAC_PHY_INTF_SEL_SHIFT); | |
97 | + | |
98 | + rk_clrsetreg(&grf->soc_con3, | |
99 | + RXCLK_DLY_ENA_GMAC_MASK << RXCLK_DLY_ENA_GMAC_SHIFT | | |
100 | + TXCLK_DLY_ENA_GMAC_MASK << TXCLK_DLY_ENA_GMAC_SHIFT | | |
101 | + CLK_RX_DL_CFG_GMAC_MASK << CLK_RX_DL_CFG_GMAC_SHIFT | | |
102 | + CLK_TX_DL_CFG_GMAC_MASK << CLK_TX_DL_CFG_GMAC_SHIFT, | |
103 | + RXCLK_DLY_ENA_GMAC_ENABLE << RXCLK_DLY_ENA_GMAC_SHIFT | | |
104 | + TXCLK_DLY_ENA_GMAC_ENABLE << TXCLK_DLY_ENA_GMAC_SHIFT | | |
105 | + pdata->rx_delay << CLK_RX_DL_CFG_GMAC_SHIFT | | |
106 | + pdata->tx_delay << CLK_TX_DL_CFG_GMAC_SHIFT); | |
107 | + | |
108 | + return designware_eth_probe(dev); | |
109 | +} | |
110 | + | |
111 | +static int gmac_rockchip_eth_start(struct udevice *dev) | |
112 | +{ | |
113 | + struct eth_pdata *pdata = dev_get_platdata(dev); | |
114 | + struct dw_eth_dev *priv = dev_get_priv(dev); | |
115 | + int ret; | |
116 | + | |
117 | + ret = designware_eth_init(priv, pdata->enetaddr); | |
118 | + if (ret) | |
119 | + return ret; | |
120 | + ret = gmac_rockchip_fix_mac_speed(priv); | |
121 | + if (ret) | |
122 | + return ret; | |
123 | + ret = designware_eth_enable(priv); | |
124 | + if (ret) | |
125 | + return ret; | |
126 | + | |
127 | + return 0; | |
128 | +} | |
129 | + | |
130 | +const struct eth_ops gmac_rockchip_eth_ops = { | |
131 | + .start = gmac_rockchip_eth_start, | |
132 | + .send = designware_eth_send, | |
133 | + .recv = designware_eth_recv, | |
134 | + .free_pkt = designware_eth_free_pkt, | |
135 | + .stop = designware_eth_stop, | |
136 | + .write_hwaddr = designware_eth_write_hwaddr, | |
137 | +}; | |
138 | + | |
139 | +static const struct udevice_id rockchip_gmac_ids[] = { | |
140 | + { .compatible = "rockchip,rk3288-gmac" }, | |
141 | + { } | |
142 | +}; | |
143 | + | |
144 | +U_BOOT_DRIVER(eth_gmac_rockchip) = { | |
145 | + .name = "gmac_rockchip", | |
146 | + .id = UCLASS_ETH, | |
147 | + .of_match = rockchip_gmac_ids, | |
148 | + .ofdata_to_platdata = gmac_rockchip_ofdata_to_platdata, | |
149 | + .probe = gmac_rockchip_probe, | |
150 | + .ops = &gmac_rockchip_eth_ops, | |
151 | + .priv_auto_alloc_size = sizeof(struct dw_eth_dev), | |
152 | + .platdata_auto_alloc_size = sizeof(struct gmac_rockchip_platdata), | |
153 | + .flags = DM_FLAG_ALLOC_PRIV_DMA, | |
154 | +}; |