2 * (C) Copyright 2015 Sjoerd Simons <sjoerd.simons@collabora.co.uk>
4 * SPDX-License-Identifier: GPL-2.0+
6 * Rockchip GMAC ethernet IP driver for U-Boot
15 #include <asm/arch/periph.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/hardware.h>
18 #include <asm/arch/grf_rk3288.h>
19 #include <asm/arch/grf_rk3399.h>
20 #include <dm/pinctrl.h>
21 #include <dt-bindings/clock/rk3288-cru.h>
22 #include "designware.h"
24 DECLARE_GLOBAL_DATA_PTR
;
27 * Platform data for the gmac
29 * dw_eth_pdata: Required platform data for designware driver (must be first)
31 struct gmac_rockchip_platdata
{
32 struct dw_eth_pdata dw_eth_pdata
;
38 int (*fix_mac_speed
)(struct dw_eth_dev
*priv
);
39 void (*set_to_rgmii
)(struct gmac_rockchip_platdata
*pdata
);
43 static int gmac_rockchip_ofdata_to_platdata(struct udevice
*dev
)
45 struct gmac_rockchip_platdata
*pdata
= dev_get_platdata(dev
);
47 /* Check the new naming-style first... */
48 pdata
->tx_delay
= dev_read_u32_default(dev
, "tx_delay", -ENOENT
);
49 pdata
->rx_delay
= dev_read_u32_default(dev
, "rx_delay", -ENOENT
);
51 /* ... and fall back to the old naming style or default, if necessary */
52 if (pdata
->tx_delay
== -ENOENT
)
53 pdata
->tx_delay
= dev_read_u32_default(dev
, "tx-delay", 0x30);
54 if (pdata
->rx_delay
== -ENOENT
)
55 pdata
->rx_delay
= dev_read_u32_default(dev
, "rx-delay", 0x10);
57 return designware_eth_ofdata_to_platdata(dev
);
60 static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev
*priv
)
62 struct rk3288_grf
*grf
;
65 switch (priv
->phydev
->speed
) {
67 clk
= RK3288_GMAC_CLK_SEL_2_5M
;
70 clk
= RK3288_GMAC_CLK_SEL_25M
;
73 clk
= RK3288_GMAC_CLK_SEL_125M
;
76 debug("Unknown phy speed: %d\n", priv
->phydev
->speed
);
80 grf
= syscon_get_first_range(ROCKCHIP_SYSCON_GRF
);
81 rk_clrsetreg(&grf
->soc_con1
, RK3288_GMAC_CLK_SEL_MASK
, clk
);
86 static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev
*priv
)
88 struct rk3399_grf_regs
*grf
;
91 switch (priv
->phydev
->speed
) {
93 clk
= RK3399_GMAC_CLK_SEL_2_5M
;
96 clk
= RK3399_GMAC_CLK_SEL_25M
;
99 clk
= RK3399_GMAC_CLK_SEL_125M
;
102 debug("Unknown phy speed: %d\n", priv
->phydev
->speed
);
106 grf
= syscon_get_first_range(ROCKCHIP_SYSCON_GRF
);
107 rk_clrsetreg(&grf
->soc_con5
, RK3399_GMAC_CLK_SEL_MASK
, clk
);
112 static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata
*pdata
)
114 struct rk3288_grf
*grf
;
116 grf
= syscon_get_first_range(ROCKCHIP_SYSCON_GRF
);
117 rk_clrsetreg(&grf
->soc_con1
,
118 RK3288_RMII_MODE_MASK
| RK3288_GMAC_PHY_INTF_SEL_MASK
,
119 RK3288_GMAC_PHY_INTF_SEL_RGMII
);
121 rk_clrsetreg(&grf
->soc_con3
,
122 RK3288_RXCLK_DLY_ENA_GMAC_MASK
|
123 RK3288_TXCLK_DLY_ENA_GMAC_MASK
|
124 RK3288_CLK_RX_DL_CFG_GMAC_MASK
|
125 RK3288_CLK_TX_DL_CFG_GMAC_MASK
,
126 RK3288_RXCLK_DLY_ENA_GMAC_ENABLE
|
127 RK3288_TXCLK_DLY_ENA_GMAC_ENABLE
|
128 pdata
->rx_delay
<< RK3288_CLK_RX_DL_CFG_GMAC_SHIFT
|
129 pdata
->tx_delay
<< RK3288_CLK_TX_DL_CFG_GMAC_SHIFT
);
132 static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata
*pdata
)
134 struct rk3399_grf_regs
*grf
;
136 grf
= syscon_get_first_range(ROCKCHIP_SYSCON_GRF
);
138 rk_clrsetreg(&grf
->soc_con5
,
139 RK3399_GMAC_PHY_INTF_SEL_MASK
,
140 RK3399_GMAC_PHY_INTF_SEL_RGMII
);
142 rk_clrsetreg(&grf
->soc_con6
,
143 RK3399_RXCLK_DLY_ENA_GMAC_MASK
|
144 RK3399_TXCLK_DLY_ENA_GMAC_MASK
|
145 RK3399_CLK_RX_DL_CFG_GMAC_MASK
|
146 RK3399_CLK_TX_DL_CFG_GMAC_MASK
,
147 RK3399_RXCLK_DLY_ENA_GMAC_ENABLE
|
148 RK3399_TXCLK_DLY_ENA_GMAC_ENABLE
|
149 pdata
->rx_delay
<< RK3399_CLK_RX_DL_CFG_GMAC_SHIFT
|
150 pdata
->tx_delay
<< RK3399_CLK_TX_DL_CFG_GMAC_SHIFT
);
153 static int gmac_rockchip_probe(struct udevice
*dev
)
155 struct gmac_rockchip_platdata
*pdata
= dev_get_platdata(dev
);
156 struct rk_gmac_ops
*ops
=
157 (struct rk_gmac_ops
*)dev_get_driver_data(dev
);
161 ret
= clk_get_by_index(dev
, 0, &clk
);
165 /* Since mac_clk is fed by an external clock we can use 0 here */
166 ret
= clk_set_rate(&clk
, 0);
170 /* Set to RGMII mode */
171 ops
->set_to_rgmii(pdata
);
173 return designware_eth_probe(dev
);
176 static int gmac_rockchip_eth_start(struct udevice
*dev
)
178 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
179 struct dw_eth_dev
*priv
= dev_get_priv(dev
);
180 struct rk_gmac_ops
*ops
=
181 (struct rk_gmac_ops
*)dev_get_driver_data(dev
);
184 ret
= designware_eth_init(priv
, pdata
->enetaddr
);
187 ret
= ops
->fix_mac_speed(priv
);
190 ret
= designware_eth_enable(priv
);
197 const struct eth_ops gmac_rockchip_eth_ops
= {
198 .start
= gmac_rockchip_eth_start
,
199 .send
= designware_eth_send
,
200 .recv
= designware_eth_recv
,
201 .free_pkt
= designware_eth_free_pkt
,
202 .stop
= designware_eth_stop
,
203 .write_hwaddr
= designware_eth_write_hwaddr
,
206 const struct rk_gmac_ops rk3288_gmac_ops
= {
207 .fix_mac_speed
= rk3288_gmac_fix_mac_speed
,
208 .set_to_rgmii
= rk3288_gmac_set_to_rgmii
,
211 const struct rk_gmac_ops rk3399_gmac_ops
= {
212 .fix_mac_speed
= rk3399_gmac_fix_mac_speed
,
213 .set_to_rgmii
= rk3399_gmac_set_to_rgmii
,
216 static const struct udevice_id rockchip_gmac_ids
[] = {
217 { .compatible
= "rockchip,rk3288-gmac",
218 .data
= (ulong
)&rk3288_gmac_ops
},
219 { .compatible
= "rockchip,rk3399-gmac",
220 .data
= (ulong
)&rk3399_gmac_ops
},
224 U_BOOT_DRIVER(eth_gmac_rockchip
) = {
225 .name
= "gmac_rockchip",
227 .of_match
= rockchip_gmac_ids
,
228 .ofdata_to_platdata
= gmac_rockchip_ofdata_to_platdata
,
229 .probe
= gmac_rockchip_probe
,
230 .ops
= &gmac_rockchip_eth_ops
,
231 .priv_auto_alloc_size
= sizeof(struct dw_eth_dev
),
232 .platdata_auto_alloc_size
= sizeof(struct gmac_rockchip_platdata
),
233 .flags
= DM_FLAG_ALLOC_PRIV_DMA
,