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 }; 155