17ad269eaSRoger Chen /** 27ad269eaSRoger Chen * dwmac-rk.c - Rockchip RK3288 DWMAC specific glue layer 37ad269eaSRoger Chen * 47ad269eaSRoger Chen * Copyright (C) 2014 Chen-Zhi (Roger Chen) 57ad269eaSRoger Chen * 67ad269eaSRoger Chen * Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com> 77ad269eaSRoger Chen * 87ad269eaSRoger Chen * This program is free software; you can redistribute it and/or modify 97ad269eaSRoger Chen * it under the terms of the GNU General Public License as published by 107ad269eaSRoger Chen * the Free Software Foundation; either version 2 of the License, or 117ad269eaSRoger Chen * (at your option) any later version. 127ad269eaSRoger Chen * 137ad269eaSRoger Chen * This program is distributed in the hope that it will be useful, 147ad269eaSRoger Chen * but WITHOUT ANY WARRANTY; without even the implied warranty of 157ad269eaSRoger Chen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 167ad269eaSRoger Chen * GNU General Public License for more details. 177ad269eaSRoger Chen */ 187ad269eaSRoger Chen 197ad269eaSRoger Chen #include <linux/stmmac.h> 207ad269eaSRoger Chen #include <linux/bitops.h> 217ad269eaSRoger Chen #include <linux/clk.h> 227ad269eaSRoger Chen #include <linux/phy.h> 237ad269eaSRoger Chen #include <linux/of_net.h> 247ad269eaSRoger Chen #include <linux/gpio.h> 25e0fb4013SJoachim Eastwood #include <linux/module.h> 267ad269eaSRoger Chen #include <linux/of_gpio.h> 277ad269eaSRoger Chen #include <linux/of_device.h> 28e0fb4013SJoachim Eastwood #include <linux/platform_device.h> 297ad269eaSRoger Chen #include <linux/regulator/consumer.h> 307ad269eaSRoger Chen #include <linux/delay.h> 317ad269eaSRoger Chen #include <linux/mfd/syscon.h> 327ad269eaSRoger Chen #include <linux/regmap.h> 332c896fb0SDavid Wu #include <linux/pm_runtime.h> 347ad269eaSRoger Chen 35e0fb4013SJoachim Eastwood #include "stmmac_platform.h" 36e0fb4013SJoachim Eastwood 370fb98db1SHeiko Stübner struct rk_priv_data; 380fb98db1SHeiko Stübner struct rk_gmac_ops { 390fb98db1SHeiko Stübner void (*set_to_rgmii)(struct rk_priv_data *bsp_priv, 400fb98db1SHeiko Stübner int tx_delay, int rx_delay); 410fb98db1SHeiko Stübner void (*set_to_rmii)(struct rk_priv_data *bsp_priv); 420fb98db1SHeiko Stübner void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); 430fb98db1SHeiko Stübner void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); 44*fecd4d7eSDavid Wu void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); 450fb98db1SHeiko Stübner }; 460fb98db1SHeiko Stübner 477ad269eaSRoger Chen struct rk_priv_data { 487ad269eaSRoger Chen struct platform_device *pdev; 497ad269eaSRoger Chen int phy_iface; 502e12f536SRomain Perier struct regulator *regulator; 51229666c1SVincent Palatin bool suspended; 5292c2588fSJoachim Eastwood const struct rk_gmac_ops *ops; 537ad269eaSRoger Chen 547ad269eaSRoger Chen bool clk_enabled; 557ad269eaSRoger Chen bool clock_input; 56*fecd4d7eSDavid Wu bool integrated_phy; 577ad269eaSRoger Chen 587ad269eaSRoger Chen struct clk *clk_mac; 597ad269eaSRoger Chen struct clk *gmac_clkin; 607ad269eaSRoger Chen struct clk *mac_clk_rx; 617ad269eaSRoger Chen struct clk *mac_clk_tx; 627ad269eaSRoger Chen struct clk *clk_mac_ref; 637ad269eaSRoger Chen struct clk *clk_mac_refout; 647ad269eaSRoger Chen struct clk *aclk_mac; 657ad269eaSRoger Chen struct clk *pclk_mac; 66*fecd4d7eSDavid Wu struct clk *clk_phy; 67*fecd4d7eSDavid Wu 68*fecd4d7eSDavid Wu struct reset_control *phy_reset; 697ad269eaSRoger Chen 707ad269eaSRoger Chen int tx_delay; 717ad269eaSRoger Chen int rx_delay; 727ad269eaSRoger Chen 737ad269eaSRoger Chen struct regmap *grf; 747ad269eaSRoger Chen }; 757ad269eaSRoger Chen 767ad269eaSRoger Chen #define HIWORD_UPDATE(val, mask, shift) \ 777ad269eaSRoger Chen ((val) << (shift) | (mask) << ((shift) + 16)) 787ad269eaSRoger Chen 797ad269eaSRoger Chen #define GRF_BIT(nr) (BIT(nr) | BIT(nr+16)) 807ad269eaSRoger Chen #define GRF_CLR_BIT(nr) (BIT(nr+16)) 817ad269eaSRoger Chen 82eaf70ad1SWadim Egorov #define DELAY_ENABLE(soc, tx, rx) \ 83eaf70ad1SWadim Egorov (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ 84eaf70ad1SWadim Egorov ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) 85eaf70ad1SWadim Egorov 86e7ffd812SXing Zheng #define RK3228_GRF_MAC_CON0 0x0900 87e7ffd812SXing Zheng #define RK3228_GRF_MAC_CON1 0x0904 88e7ffd812SXing Zheng 89e7ffd812SXing Zheng /* RK3228_GRF_MAC_CON0 */ 90e7ffd812SXing Zheng #define RK3228_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) 91e7ffd812SXing Zheng #define RK3228_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) 92e7ffd812SXing Zheng 93e7ffd812SXing Zheng /* RK3228_GRF_MAC_CON1 */ 94e7ffd812SXing Zheng #define RK3228_GMAC_PHY_INTF_SEL_RGMII \ 95e7ffd812SXing Zheng (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) 96e7ffd812SXing Zheng #define RK3228_GMAC_PHY_INTF_SEL_RMII \ 97e7ffd812SXing Zheng (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6)) 98e7ffd812SXing Zheng #define RK3228_GMAC_FLOW_CTRL GRF_BIT(3) 99e7ffd812SXing Zheng #define RK3228_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3) 100e7ffd812SXing Zheng #define RK3228_GMAC_SPEED_10M GRF_CLR_BIT(2) 101e7ffd812SXing Zheng #define RK3228_GMAC_SPEED_100M GRF_BIT(2) 102e7ffd812SXing Zheng #define RK3228_GMAC_RMII_CLK_25M GRF_BIT(7) 103e7ffd812SXing Zheng #define RK3228_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7) 104e7ffd812SXing Zheng #define RK3228_GMAC_CLK_125M (GRF_CLR_BIT(8) | GRF_CLR_BIT(9)) 105e7ffd812SXing Zheng #define RK3228_GMAC_CLK_25M (GRF_BIT(8) | GRF_BIT(9)) 106e7ffd812SXing Zheng #define RK3228_GMAC_CLK_2_5M (GRF_CLR_BIT(8) | GRF_BIT(9)) 107e7ffd812SXing Zheng #define RK3228_GMAC_RMII_MODE GRF_BIT(10) 108e7ffd812SXing Zheng #define RK3228_GMAC_RMII_MODE_CLR GRF_CLR_BIT(10) 109e7ffd812SXing Zheng #define RK3228_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0) 110e7ffd812SXing Zheng #define RK3228_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0) 111e7ffd812SXing Zheng #define RK3228_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1) 112e7ffd812SXing Zheng #define RK3228_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1) 113e7ffd812SXing Zheng 114e7ffd812SXing Zheng static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv, 115e7ffd812SXing Zheng int tx_delay, int rx_delay) 116e7ffd812SXing Zheng { 117e7ffd812SXing Zheng struct device *dev = &bsp_priv->pdev->dev; 118e7ffd812SXing Zheng 119e7ffd812SXing Zheng if (IS_ERR(bsp_priv->grf)) { 120e7ffd812SXing Zheng dev_err(dev, "Missing rockchip,grf property\n"); 121e7ffd812SXing Zheng return; 122e7ffd812SXing Zheng } 123e7ffd812SXing Zheng 124e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 125e7ffd812SXing Zheng RK3228_GMAC_PHY_INTF_SEL_RGMII | 126e7ffd812SXing Zheng RK3228_GMAC_RMII_MODE_CLR | 127eaf70ad1SWadim Egorov DELAY_ENABLE(RK3228, tx_delay, rx_delay)); 128e7ffd812SXing Zheng 129e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON0, 130e7ffd812SXing Zheng RK3228_GMAC_CLK_RX_DL_CFG(rx_delay) | 131e7ffd812SXing Zheng RK3228_GMAC_CLK_TX_DL_CFG(tx_delay)); 132e7ffd812SXing Zheng } 133e7ffd812SXing Zheng 134e7ffd812SXing Zheng static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv) 135e7ffd812SXing Zheng { 136e7ffd812SXing Zheng struct device *dev = &bsp_priv->pdev->dev; 137e7ffd812SXing Zheng 138e7ffd812SXing Zheng if (IS_ERR(bsp_priv->grf)) { 139e7ffd812SXing Zheng dev_err(dev, "Missing rockchip,grf property\n"); 140e7ffd812SXing Zheng return; 141e7ffd812SXing Zheng } 142e7ffd812SXing Zheng 143e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 144e7ffd812SXing Zheng RK3228_GMAC_PHY_INTF_SEL_RMII | 145e7ffd812SXing Zheng RK3228_GMAC_RMII_MODE); 146e7ffd812SXing Zheng 147e7ffd812SXing Zheng /* set MAC to RMII mode */ 148e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, GRF_BIT(11)); 149e7ffd812SXing Zheng } 150e7ffd812SXing Zheng 151e7ffd812SXing Zheng static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) 152e7ffd812SXing Zheng { 153e7ffd812SXing Zheng struct device *dev = &bsp_priv->pdev->dev; 154e7ffd812SXing Zheng 155e7ffd812SXing Zheng if (IS_ERR(bsp_priv->grf)) { 156e7ffd812SXing Zheng dev_err(dev, "Missing rockchip,grf property\n"); 157e7ffd812SXing Zheng return; 158e7ffd812SXing Zheng } 159e7ffd812SXing Zheng 160e7ffd812SXing Zheng if (speed == 10) 161e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 162e7ffd812SXing Zheng RK3228_GMAC_CLK_2_5M); 163e7ffd812SXing Zheng else if (speed == 100) 164e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 165e7ffd812SXing Zheng RK3228_GMAC_CLK_25M); 166e7ffd812SXing Zheng else if (speed == 1000) 167e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 168e7ffd812SXing Zheng RK3228_GMAC_CLK_125M); 169e7ffd812SXing Zheng else 170e7ffd812SXing Zheng dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); 171e7ffd812SXing Zheng } 172e7ffd812SXing Zheng 173e7ffd812SXing Zheng static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) 174e7ffd812SXing Zheng { 175e7ffd812SXing Zheng struct device *dev = &bsp_priv->pdev->dev; 176e7ffd812SXing Zheng 177e7ffd812SXing Zheng if (IS_ERR(bsp_priv->grf)) { 178e7ffd812SXing Zheng dev_err(dev, "Missing rockchip,grf property\n"); 179e7ffd812SXing Zheng return; 180e7ffd812SXing Zheng } 181e7ffd812SXing Zheng 182e7ffd812SXing Zheng if (speed == 10) 183e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 184e7ffd812SXing Zheng RK3228_GMAC_RMII_CLK_2_5M | 185e7ffd812SXing Zheng RK3228_GMAC_SPEED_10M); 186e7ffd812SXing Zheng else if (speed == 100) 187e7ffd812SXing Zheng regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, 188e7ffd812SXing Zheng RK3228_GMAC_RMII_CLK_25M | 189e7ffd812SXing Zheng RK3228_GMAC_SPEED_100M); 190e7ffd812SXing Zheng else 191e7ffd812SXing Zheng dev_err(dev, "unknown speed value for RMII! speed=%d", speed); 192e7ffd812SXing Zheng } 193e7ffd812SXing Zheng 194e7ffd812SXing Zheng static const struct rk_gmac_ops rk3228_ops = { 195e7ffd812SXing Zheng .set_to_rgmii = rk3228_set_to_rgmii, 196e7ffd812SXing Zheng .set_to_rmii = rk3228_set_to_rmii, 197e7ffd812SXing Zheng .set_rgmii_speed = rk3228_set_rgmii_speed, 198e7ffd812SXing Zheng .set_rmii_speed = rk3228_set_rmii_speed, 199e7ffd812SXing Zheng }; 200e7ffd812SXing Zheng 2017ad269eaSRoger Chen #define RK3288_GRF_SOC_CON1 0x0248 2027ad269eaSRoger Chen #define RK3288_GRF_SOC_CON3 0x0250 2037ad269eaSRoger Chen 2047ad269eaSRoger Chen /*RK3288_GRF_SOC_CON1*/ 2050fb98db1SHeiko Stübner #define RK3288_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | \ 2060fb98db1SHeiko Stübner GRF_CLR_BIT(8)) 2070fb98db1SHeiko Stübner #define RK3288_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \ 2080fb98db1SHeiko Stübner GRF_BIT(8)) 2090fb98db1SHeiko Stübner #define RK3288_GMAC_FLOW_CTRL GRF_BIT(9) 2100fb98db1SHeiko Stübner #define RK3288_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9) 2110fb98db1SHeiko Stübner #define RK3288_GMAC_SPEED_10M GRF_CLR_BIT(10) 2120fb98db1SHeiko Stübner #define RK3288_GMAC_SPEED_100M GRF_BIT(10) 2130fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_CLK_25M GRF_BIT(11) 2140fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11) 2150fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13)) 2160fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13)) 2170fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13)) 2180fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_MODE GRF_BIT(14) 2190fb98db1SHeiko Stübner #define RK3288_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14) 2207ad269eaSRoger Chen 2217ad269eaSRoger Chen /*RK3288_GRF_SOC_CON3*/ 2220fb98db1SHeiko Stübner #define RK3288_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) 2230fb98db1SHeiko Stübner #define RK3288_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) 2240fb98db1SHeiko Stübner #define RK3288_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) 2250fb98db1SHeiko Stübner #define RK3288_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) 2260fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) 2270fb98db1SHeiko Stübner #define RK3288_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) 2287ad269eaSRoger Chen 2290fb98db1SHeiko Stübner static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv, 2307ad269eaSRoger Chen int tx_delay, int rx_delay) 2317ad269eaSRoger Chen { 2327ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 2337ad269eaSRoger Chen 2347ad269eaSRoger Chen if (IS_ERR(bsp_priv->grf)) { 235d42202dcSRomain Perier dev_err(dev, "Missing rockchip,grf property\n"); 2367ad269eaSRoger Chen return; 2377ad269eaSRoger Chen } 2387ad269eaSRoger Chen 2397ad269eaSRoger Chen regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2400fb98db1SHeiko Stübner RK3288_GMAC_PHY_INTF_SEL_RGMII | 2410fb98db1SHeiko Stübner RK3288_GMAC_RMII_MODE_CLR); 2427ad269eaSRoger Chen regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3, 243eaf70ad1SWadim Egorov DELAY_ENABLE(RK3288, tx_delay, rx_delay) | 2440fb98db1SHeiko Stübner RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) | 2450fb98db1SHeiko Stübner RK3288_GMAC_CLK_TX_DL_CFG(tx_delay)); 2467ad269eaSRoger Chen } 2477ad269eaSRoger Chen 2480fb98db1SHeiko Stübner static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv) 2497ad269eaSRoger Chen { 2507ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 2517ad269eaSRoger Chen 2527ad269eaSRoger Chen if (IS_ERR(bsp_priv->grf)) { 253d42202dcSRomain Perier dev_err(dev, "Missing rockchip,grf property\n"); 2547ad269eaSRoger Chen return; 2557ad269eaSRoger Chen } 2567ad269eaSRoger Chen 2577ad269eaSRoger Chen regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2580fb98db1SHeiko Stübner RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE); 2597ad269eaSRoger Chen } 2607ad269eaSRoger Chen 2610fb98db1SHeiko Stübner static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) 2627ad269eaSRoger Chen { 2637ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 2647ad269eaSRoger Chen 2657ad269eaSRoger Chen if (IS_ERR(bsp_priv->grf)) { 266d42202dcSRomain Perier dev_err(dev, "Missing rockchip,grf property\n"); 2677ad269eaSRoger Chen return; 2687ad269eaSRoger Chen } 2697ad269eaSRoger Chen 2707ad269eaSRoger Chen if (speed == 10) 2710fb98db1SHeiko Stübner regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2720fb98db1SHeiko Stübner RK3288_GMAC_CLK_2_5M); 2737ad269eaSRoger Chen else if (speed == 100) 2740fb98db1SHeiko Stübner regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2750fb98db1SHeiko Stübner RK3288_GMAC_CLK_25M); 2767ad269eaSRoger Chen else if (speed == 1000) 2770fb98db1SHeiko Stübner regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2780fb98db1SHeiko Stübner RK3288_GMAC_CLK_125M); 2797ad269eaSRoger Chen else 2807ad269eaSRoger Chen dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); 2817ad269eaSRoger Chen } 2827ad269eaSRoger Chen 2830fb98db1SHeiko Stübner static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) 2847ad269eaSRoger Chen { 2857ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 2867ad269eaSRoger Chen 2877ad269eaSRoger Chen if (IS_ERR(bsp_priv->grf)) { 288d42202dcSRomain Perier dev_err(dev, "Missing rockchip,grf property\n"); 2897ad269eaSRoger Chen return; 2907ad269eaSRoger Chen } 2917ad269eaSRoger Chen 2927ad269eaSRoger Chen if (speed == 10) { 2937ad269eaSRoger Chen regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2940fb98db1SHeiko Stübner RK3288_GMAC_RMII_CLK_2_5M | 2950fb98db1SHeiko Stübner RK3288_GMAC_SPEED_10M); 2967ad269eaSRoger Chen } else if (speed == 100) { 2977ad269eaSRoger Chen regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, 2980fb98db1SHeiko Stübner RK3288_GMAC_RMII_CLK_25M | 2990fb98db1SHeiko Stübner RK3288_GMAC_SPEED_100M); 3007ad269eaSRoger Chen } else { 3017ad269eaSRoger Chen dev_err(dev, "unknown speed value for RMII! speed=%d", speed); 3027ad269eaSRoger Chen } 3037ad269eaSRoger Chen } 3047ad269eaSRoger Chen 30592c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3288_ops = { 3060fb98db1SHeiko Stübner .set_to_rgmii = rk3288_set_to_rgmii, 3070fb98db1SHeiko Stübner .set_to_rmii = rk3288_set_to_rmii, 3080fb98db1SHeiko Stübner .set_rgmii_speed = rk3288_set_rgmii_speed, 3090fb98db1SHeiko Stübner .set_rmii_speed = rk3288_set_rmii_speed, 3100fb98db1SHeiko Stübner }; 3110fb98db1SHeiko Stübner 312d4ff816eSdavid.wu #define RK3328_GRF_MAC_CON0 0x0900 313d4ff816eSdavid.wu #define RK3328_GRF_MAC_CON1 0x0904 314d4ff816eSdavid.wu 315d4ff816eSdavid.wu /* RK3328_GRF_MAC_CON0 */ 316d4ff816eSdavid.wu #define RK3328_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) 317d4ff816eSdavid.wu #define RK3328_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) 318d4ff816eSdavid.wu 319d4ff816eSdavid.wu /* RK3328_GRF_MAC_CON1 */ 320d4ff816eSdavid.wu #define RK3328_GMAC_PHY_INTF_SEL_RGMII \ 321d4ff816eSdavid.wu (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) 322d4ff816eSdavid.wu #define RK3328_GMAC_PHY_INTF_SEL_RMII \ 323d4ff816eSdavid.wu (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6)) 324d4ff816eSdavid.wu #define RK3328_GMAC_FLOW_CTRL GRF_BIT(3) 325d4ff816eSdavid.wu #define RK3328_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3) 326d4ff816eSdavid.wu #define RK3328_GMAC_SPEED_10M GRF_CLR_BIT(2) 327d4ff816eSdavid.wu #define RK3328_GMAC_SPEED_100M GRF_BIT(2) 328d4ff816eSdavid.wu #define RK3328_GMAC_RMII_CLK_25M GRF_BIT(7) 329d4ff816eSdavid.wu #define RK3328_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7) 330d4ff816eSdavid.wu #define RK3328_GMAC_CLK_125M (GRF_CLR_BIT(11) | GRF_CLR_BIT(12)) 331d4ff816eSdavid.wu #define RK3328_GMAC_CLK_25M (GRF_BIT(11) | GRF_BIT(12)) 332d4ff816eSdavid.wu #define RK3328_GMAC_CLK_2_5M (GRF_CLR_BIT(11) | GRF_BIT(12)) 333d4ff816eSdavid.wu #define RK3328_GMAC_RMII_MODE GRF_BIT(9) 334d4ff816eSdavid.wu #define RK3328_GMAC_RMII_MODE_CLR GRF_CLR_BIT(9) 335d4ff816eSdavid.wu #define RK3328_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0) 336d4ff816eSdavid.wu #define RK3328_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0) 337d4ff816eSdavid.wu #define RK3328_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1) 338d4ff816eSdavid.wu #define RK3328_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(0) 339d4ff816eSdavid.wu 340d4ff816eSdavid.wu static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv, 341d4ff816eSdavid.wu int tx_delay, int rx_delay) 342d4ff816eSdavid.wu { 343d4ff816eSdavid.wu struct device *dev = &bsp_priv->pdev->dev; 344d4ff816eSdavid.wu 345d4ff816eSdavid.wu if (IS_ERR(bsp_priv->grf)) { 346d4ff816eSdavid.wu dev_err(dev, "Missing rockchip,grf property\n"); 347d4ff816eSdavid.wu return; 348d4ff816eSdavid.wu } 349d4ff816eSdavid.wu 350d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 351d4ff816eSdavid.wu RK3328_GMAC_PHY_INTF_SEL_RGMII | 352d4ff816eSdavid.wu RK3328_GMAC_RMII_MODE_CLR | 353d4ff816eSdavid.wu RK3328_GMAC_RXCLK_DLY_ENABLE | 354d4ff816eSdavid.wu RK3328_GMAC_TXCLK_DLY_ENABLE); 355d4ff816eSdavid.wu 356d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON0, 357d4ff816eSdavid.wu RK3328_GMAC_CLK_RX_DL_CFG(rx_delay) | 358d4ff816eSdavid.wu RK3328_GMAC_CLK_TX_DL_CFG(tx_delay)); 359d4ff816eSdavid.wu } 360d4ff816eSdavid.wu 361d4ff816eSdavid.wu static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv) 362d4ff816eSdavid.wu { 363d4ff816eSdavid.wu struct device *dev = &bsp_priv->pdev->dev; 364d4ff816eSdavid.wu 365d4ff816eSdavid.wu if (IS_ERR(bsp_priv->grf)) { 366d4ff816eSdavid.wu dev_err(dev, "Missing rockchip,grf property\n"); 367d4ff816eSdavid.wu return; 368d4ff816eSdavid.wu } 369d4ff816eSdavid.wu 370d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 371d4ff816eSdavid.wu RK3328_GMAC_PHY_INTF_SEL_RMII | 372d4ff816eSdavid.wu RK3328_GMAC_RMII_MODE); 373d4ff816eSdavid.wu } 374d4ff816eSdavid.wu 375d4ff816eSdavid.wu static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) 376d4ff816eSdavid.wu { 377d4ff816eSdavid.wu struct device *dev = &bsp_priv->pdev->dev; 378d4ff816eSdavid.wu 379d4ff816eSdavid.wu if (IS_ERR(bsp_priv->grf)) { 380d4ff816eSdavid.wu dev_err(dev, "Missing rockchip,grf property\n"); 381d4ff816eSdavid.wu return; 382d4ff816eSdavid.wu } 383d4ff816eSdavid.wu 384d4ff816eSdavid.wu if (speed == 10) 385d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 386d4ff816eSdavid.wu RK3328_GMAC_CLK_2_5M); 387d4ff816eSdavid.wu else if (speed == 100) 388d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 389d4ff816eSdavid.wu RK3328_GMAC_CLK_25M); 390d4ff816eSdavid.wu else if (speed == 1000) 391d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 392d4ff816eSdavid.wu RK3328_GMAC_CLK_125M); 393d4ff816eSdavid.wu else 394d4ff816eSdavid.wu dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); 395d4ff816eSdavid.wu } 396d4ff816eSdavid.wu 397d4ff816eSdavid.wu static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) 398d4ff816eSdavid.wu { 399d4ff816eSdavid.wu struct device *dev = &bsp_priv->pdev->dev; 400d4ff816eSdavid.wu 401d4ff816eSdavid.wu if (IS_ERR(bsp_priv->grf)) { 402d4ff816eSdavid.wu dev_err(dev, "Missing rockchip,grf property\n"); 403d4ff816eSdavid.wu return; 404d4ff816eSdavid.wu } 405d4ff816eSdavid.wu 406d4ff816eSdavid.wu if (speed == 10) 407d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 408d4ff816eSdavid.wu RK3328_GMAC_RMII_CLK_2_5M | 409d4ff816eSdavid.wu RK3328_GMAC_SPEED_10M); 410d4ff816eSdavid.wu else if (speed == 100) 411d4ff816eSdavid.wu regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, 412d4ff816eSdavid.wu RK3328_GMAC_RMII_CLK_25M | 413d4ff816eSdavid.wu RK3328_GMAC_SPEED_100M); 414d4ff816eSdavid.wu else 415d4ff816eSdavid.wu dev_err(dev, "unknown speed value for RMII! speed=%d", speed); 416d4ff816eSdavid.wu } 417d4ff816eSdavid.wu 418d4ff816eSdavid.wu static const struct rk_gmac_ops rk3328_ops = { 419d4ff816eSdavid.wu .set_to_rgmii = rk3328_set_to_rgmii, 420d4ff816eSdavid.wu .set_to_rmii = rk3328_set_to_rmii, 421d4ff816eSdavid.wu .set_rgmii_speed = rk3328_set_rgmii_speed, 422d4ff816eSdavid.wu .set_rmii_speed = rk3328_set_rmii_speed, 423d4ff816eSdavid.wu }; 424d4ff816eSdavid.wu 425ba289af8SRoger Chen #define RK3366_GRF_SOC_CON6 0x0418 426ba289af8SRoger Chen #define RK3366_GRF_SOC_CON7 0x041c 427ba289af8SRoger Chen 428ba289af8SRoger Chen /* RK3366_GRF_SOC_CON6 */ 429ba289af8SRoger Chen #define RK3366_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ 430ba289af8SRoger Chen GRF_CLR_BIT(11)) 431ba289af8SRoger Chen #define RK3366_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ 432ba289af8SRoger Chen GRF_BIT(11)) 433ba289af8SRoger Chen #define RK3366_GMAC_FLOW_CTRL GRF_BIT(8) 434ba289af8SRoger Chen #define RK3366_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) 435ba289af8SRoger Chen #define RK3366_GMAC_SPEED_10M GRF_CLR_BIT(7) 436ba289af8SRoger Chen #define RK3366_GMAC_SPEED_100M GRF_BIT(7) 437ba289af8SRoger Chen #define RK3366_GMAC_RMII_CLK_25M GRF_BIT(3) 438ba289af8SRoger Chen #define RK3366_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) 439ba289af8SRoger Chen #define RK3366_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) 440ba289af8SRoger Chen #define RK3366_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) 441ba289af8SRoger Chen #define RK3366_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) 442ba289af8SRoger Chen #define RK3366_GMAC_RMII_MODE GRF_BIT(6) 443ba289af8SRoger Chen #define RK3366_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) 444ba289af8SRoger Chen 445ba289af8SRoger Chen /* RK3366_GRF_SOC_CON7 */ 446ba289af8SRoger Chen #define RK3366_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) 447ba289af8SRoger Chen #define RK3366_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) 448ba289af8SRoger Chen #define RK3366_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) 449ba289af8SRoger Chen #define RK3366_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) 450ba289af8SRoger Chen #define RK3366_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) 451ba289af8SRoger Chen #define RK3366_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) 452ba289af8SRoger Chen 453ba289af8SRoger Chen static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv, 454ba289af8SRoger Chen int tx_delay, int rx_delay) 455ba289af8SRoger Chen { 456ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 457ba289af8SRoger Chen 458ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 459ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 460ba289af8SRoger Chen return; 461ba289af8SRoger Chen } 462ba289af8SRoger Chen 463ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 464ba289af8SRoger Chen RK3366_GMAC_PHY_INTF_SEL_RGMII | 465ba289af8SRoger Chen RK3366_GMAC_RMII_MODE_CLR); 466ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON7, 467eaf70ad1SWadim Egorov DELAY_ENABLE(RK3366, tx_delay, rx_delay) | 468ba289af8SRoger Chen RK3366_GMAC_CLK_RX_DL_CFG(rx_delay) | 469ba289af8SRoger Chen RK3366_GMAC_CLK_TX_DL_CFG(tx_delay)); 470ba289af8SRoger Chen } 471ba289af8SRoger Chen 472ba289af8SRoger Chen static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv) 473ba289af8SRoger Chen { 474ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 475ba289af8SRoger Chen 476ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 477ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 478ba289af8SRoger Chen return; 479ba289af8SRoger Chen } 480ba289af8SRoger Chen 481ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 482ba289af8SRoger Chen RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE); 483ba289af8SRoger Chen } 484ba289af8SRoger Chen 485ba289af8SRoger Chen static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) 486ba289af8SRoger Chen { 487ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 488ba289af8SRoger Chen 489ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 490ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 491ba289af8SRoger Chen return; 492ba289af8SRoger Chen } 493ba289af8SRoger Chen 494ba289af8SRoger Chen if (speed == 10) 495ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 496ba289af8SRoger Chen RK3366_GMAC_CLK_2_5M); 497ba289af8SRoger Chen else if (speed == 100) 498ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 499ba289af8SRoger Chen RK3366_GMAC_CLK_25M); 500ba289af8SRoger Chen else if (speed == 1000) 501ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 502ba289af8SRoger Chen RK3366_GMAC_CLK_125M); 503ba289af8SRoger Chen else 504ba289af8SRoger Chen dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); 505ba289af8SRoger Chen } 506ba289af8SRoger Chen 507ba289af8SRoger Chen static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) 508ba289af8SRoger Chen { 509ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 510ba289af8SRoger Chen 511ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 512ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 513ba289af8SRoger Chen return; 514ba289af8SRoger Chen } 515ba289af8SRoger Chen 516ba289af8SRoger Chen if (speed == 10) { 517ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 518ba289af8SRoger Chen RK3366_GMAC_RMII_CLK_2_5M | 519ba289af8SRoger Chen RK3366_GMAC_SPEED_10M); 520ba289af8SRoger Chen } else if (speed == 100) { 521ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, 522ba289af8SRoger Chen RK3366_GMAC_RMII_CLK_25M | 523ba289af8SRoger Chen RK3366_GMAC_SPEED_100M); 524ba289af8SRoger Chen } else { 525ba289af8SRoger Chen dev_err(dev, "unknown speed value for RMII! speed=%d", speed); 526ba289af8SRoger Chen } 527ba289af8SRoger Chen } 528ba289af8SRoger Chen 529ba289af8SRoger Chen static const struct rk_gmac_ops rk3366_ops = { 530ba289af8SRoger Chen .set_to_rgmii = rk3366_set_to_rgmii, 531ba289af8SRoger Chen .set_to_rmii = rk3366_set_to_rmii, 532ba289af8SRoger Chen .set_rgmii_speed = rk3366_set_rgmii_speed, 533ba289af8SRoger Chen .set_rmii_speed = rk3366_set_rmii_speed, 534ba289af8SRoger Chen }; 535ba289af8SRoger Chen 536df558854SHeiko Stübner #define RK3368_GRF_SOC_CON15 0x043c 537df558854SHeiko Stübner #define RK3368_GRF_SOC_CON16 0x0440 538df558854SHeiko Stübner 539df558854SHeiko Stübner /* RK3368_GRF_SOC_CON15 */ 540df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ 541df558854SHeiko Stübner GRF_CLR_BIT(11)) 542df558854SHeiko Stübner #define RK3368_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ 543df558854SHeiko Stübner GRF_BIT(11)) 544df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL GRF_BIT(8) 545df558854SHeiko Stübner #define RK3368_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) 546df558854SHeiko Stübner #define RK3368_GMAC_SPEED_10M GRF_CLR_BIT(7) 547df558854SHeiko Stübner #define RK3368_GMAC_SPEED_100M GRF_BIT(7) 548df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_25M GRF_BIT(3) 549df558854SHeiko Stübner #define RK3368_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) 550df558854SHeiko Stübner #define RK3368_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) 551df558854SHeiko Stübner #define RK3368_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) 552df558854SHeiko Stübner #define RK3368_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) 553df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE GRF_BIT(6) 554df558854SHeiko Stübner #define RK3368_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) 555df558854SHeiko Stübner 556df558854SHeiko Stübner /* RK3368_GRF_SOC_CON16 */ 557df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) 558df558854SHeiko Stübner #define RK3368_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) 559df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) 560df558854SHeiko Stübner #define RK3368_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) 561df558854SHeiko Stübner #define RK3368_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) 562df558854SHeiko Stübner #define RK3368_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) 563df558854SHeiko Stübner 564df558854SHeiko Stübner static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv, 565df558854SHeiko Stübner int tx_delay, int rx_delay) 566df558854SHeiko Stübner { 567df558854SHeiko Stübner struct device *dev = &bsp_priv->pdev->dev; 568df558854SHeiko Stübner 569df558854SHeiko Stübner if (IS_ERR(bsp_priv->grf)) { 570df558854SHeiko Stübner dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 571df558854SHeiko Stübner return; 572df558854SHeiko Stübner } 573df558854SHeiko Stübner 574df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 575df558854SHeiko Stübner RK3368_GMAC_PHY_INTF_SEL_RGMII | 576df558854SHeiko Stübner RK3368_GMAC_RMII_MODE_CLR); 577df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16, 578eaf70ad1SWadim Egorov DELAY_ENABLE(RK3368, tx_delay, rx_delay) | 579df558854SHeiko Stübner RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) | 580df558854SHeiko Stübner RK3368_GMAC_CLK_TX_DL_CFG(tx_delay)); 581df558854SHeiko Stübner } 582df558854SHeiko Stübner 583df558854SHeiko Stübner static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv) 584df558854SHeiko Stübner { 585df558854SHeiko Stübner struct device *dev = &bsp_priv->pdev->dev; 586df558854SHeiko Stübner 587df558854SHeiko Stübner if (IS_ERR(bsp_priv->grf)) { 588df558854SHeiko Stübner dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 589df558854SHeiko Stübner return; 590df558854SHeiko Stübner } 591df558854SHeiko Stübner 592df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 593df558854SHeiko Stübner RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE); 594df558854SHeiko Stübner } 595df558854SHeiko Stübner 596df558854SHeiko Stübner static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) 597df558854SHeiko Stübner { 598df558854SHeiko Stübner struct device *dev = &bsp_priv->pdev->dev; 599df558854SHeiko Stübner 600df558854SHeiko Stübner if (IS_ERR(bsp_priv->grf)) { 601df558854SHeiko Stübner dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 602df558854SHeiko Stübner return; 603df558854SHeiko Stübner } 604df558854SHeiko Stübner 605df558854SHeiko Stübner if (speed == 10) 606df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 607df558854SHeiko Stübner RK3368_GMAC_CLK_2_5M); 608df558854SHeiko Stübner else if (speed == 100) 609df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 610df558854SHeiko Stübner RK3368_GMAC_CLK_25M); 611df558854SHeiko Stübner else if (speed == 1000) 612df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 613df558854SHeiko Stübner RK3368_GMAC_CLK_125M); 614df558854SHeiko Stübner else 615df558854SHeiko Stübner dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); 616df558854SHeiko Stübner } 617df558854SHeiko Stübner 618df558854SHeiko Stübner static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) 619df558854SHeiko Stübner { 620df558854SHeiko Stübner struct device *dev = &bsp_priv->pdev->dev; 621df558854SHeiko Stübner 622df558854SHeiko Stübner if (IS_ERR(bsp_priv->grf)) { 623df558854SHeiko Stübner dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 624df558854SHeiko Stübner return; 625df558854SHeiko Stübner } 626df558854SHeiko Stübner 627df558854SHeiko Stübner if (speed == 10) { 628df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 629df558854SHeiko Stübner RK3368_GMAC_RMII_CLK_2_5M | 630df558854SHeiko Stübner RK3368_GMAC_SPEED_10M); 631df558854SHeiko Stübner } else if (speed == 100) { 632df558854SHeiko Stübner regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, 633df558854SHeiko Stübner RK3368_GMAC_RMII_CLK_25M | 634df558854SHeiko Stübner RK3368_GMAC_SPEED_100M); 635df558854SHeiko Stübner } else { 636df558854SHeiko Stübner dev_err(dev, "unknown speed value for RMII! speed=%d", speed); 637df558854SHeiko Stübner } 638df558854SHeiko Stübner } 639df558854SHeiko Stübner 64092c2588fSJoachim Eastwood static const struct rk_gmac_ops rk3368_ops = { 641df558854SHeiko Stübner .set_to_rgmii = rk3368_set_to_rgmii, 642df558854SHeiko Stübner .set_to_rmii = rk3368_set_to_rmii, 643df558854SHeiko Stübner .set_rgmii_speed = rk3368_set_rgmii_speed, 644df558854SHeiko Stübner .set_rmii_speed = rk3368_set_rmii_speed, 645df558854SHeiko Stübner }; 646df558854SHeiko Stübner 647ba289af8SRoger Chen #define RK3399_GRF_SOC_CON5 0xc214 648ba289af8SRoger Chen #define RK3399_GRF_SOC_CON6 0xc218 649ba289af8SRoger Chen 650ba289af8SRoger Chen /* RK3399_GRF_SOC_CON5 */ 651ba289af8SRoger Chen #define RK3399_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ 652ba289af8SRoger Chen GRF_CLR_BIT(11)) 653ba289af8SRoger Chen #define RK3399_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ 654ba289af8SRoger Chen GRF_BIT(11)) 655ba289af8SRoger Chen #define RK3399_GMAC_FLOW_CTRL GRF_BIT(8) 656ba289af8SRoger Chen #define RK3399_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) 657ba289af8SRoger Chen #define RK3399_GMAC_SPEED_10M GRF_CLR_BIT(7) 658ba289af8SRoger Chen #define RK3399_GMAC_SPEED_100M GRF_BIT(7) 659ba289af8SRoger Chen #define RK3399_GMAC_RMII_CLK_25M GRF_BIT(3) 660ba289af8SRoger Chen #define RK3399_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) 661ba289af8SRoger Chen #define RK3399_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) 662ba289af8SRoger Chen #define RK3399_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) 663ba289af8SRoger Chen #define RK3399_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) 664ba289af8SRoger Chen #define RK3399_GMAC_RMII_MODE GRF_BIT(6) 665ba289af8SRoger Chen #define RK3399_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) 666ba289af8SRoger Chen 667ba289af8SRoger Chen /* RK3399_GRF_SOC_CON6 */ 668ba289af8SRoger Chen #define RK3399_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) 669ba289af8SRoger Chen #define RK3399_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) 670ba289af8SRoger Chen #define RK3399_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) 671ba289af8SRoger Chen #define RK3399_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) 672ba289af8SRoger Chen #define RK3399_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) 673ba289af8SRoger Chen #define RK3399_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) 674ba289af8SRoger Chen 675ba289af8SRoger Chen static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv, 676ba289af8SRoger Chen int tx_delay, int rx_delay) 677ba289af8SRoger Chen { 678ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 679ba289af8SRoger Chen 680ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 681ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 682ba289af8SRoger Chen return; 683ba289af8SRoger Chen } 684ba289af8SRoger Chen 685ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 686ba289af8SRoger Chen RK3399_GMAC_PHY_INTF_SEL_RGMII | 687ba289af8SRoger Chen RK3399_GMAC_RMII_MODE_CLR); 688ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON6, 689eaf70ad1SWadim Egorov DELAY_ENABLE(RK3399, tx_delay, rx_delay) | 690ba289af8SRoger Chen RK3399_GMAC_CLK_RX_DL_CFG(rx_delay) | 691ba289af8SRoger Chen RK3399_GMAC_CLK_TX_DL_CFG(tx_delay)); 692ba289af8SRoger Chen } 693ba289af8SRoger Chen 694ba289af8SRoger Chen static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv) 695ba289af8SRoger Chen { 696ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 697ba289af8SRoger Chen 698ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 699ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 700ba289af8SRoger Chen return; 701ba289af8SRoger Chen } 702ba289af8SRoger Chen 703ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 704ba289af8SRoger Chen RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE); 705ba289af8SRoger Chen } 706ba289af8SRoger Chen 707ba289af8SRoger Chen static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) 708ba289af8SRoger Chen { 709ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 710ba289af8SRoger Chen 711ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 712ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 713ba289af8SRoger Chen return; 714ba289af8SRoger Chen } 715ba289af8SRoger Chen 716ba289af8SRoger Chen if (speed == 10) 717ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 718ba289af8SRoger Chen RK3399_GMAC_CLK_2_5M); 719ba289af8SRoger Chen else if (speed == 100) 720ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 721ba289af8SRoger Chen RK3399_GMAC_CLK_25M); 722ba289af8SRoger Chen else if (speed == 1000) 723ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 724ba289af8SRoger Chen RK3399_GMAC_CLK_125M); 725ba289af8SRoger Chen else 726ba289af8SRoger Chen dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); 727ba289af8SRoger Chen } 728ba289af8SRoger Chen 729ba289af8SRoger Chen static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) 730ba289af8SRoger Chen { 731ba289af8SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 732ba289af8SRoger Chen 733ba289af8SRoger Chen if (IS_ERR(bsp_priv->grf)) { 734ba289af8SRoger Chen dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); 735ba289af8SRoger Chen return; 736ba289af8SRoger Chen } 737ba289af8SRoger Chen 738ba289af8SRoger Chen if (speed == 10) { 739ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 740ba289af8SRoger Chen RK3399_GMAC_RMII_CLK_2_5M | 741ba289af8SRoger Chen RK3399_GMAC_SPEED_10M); 742ba289af8SRoger Chen } else if (speed == 100) { 743ba289af8SRoger Chen regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, 744ba289af8SRoger Chen RK3399_GMAC_RMII_CLK_25M | 745ba289af8SRoger Chen RK3399_GMAC_SPEED_100M); 746ba289af8SRoger Chen } else { 747ba289af8SRoger Chen dev_err(dev, "unknown speed value for RMII! speed=%d", speed); 748ba289af8SRoger Chen } 749ba289af8SRoger Chen } 750ba289af8SRoger Chen 751ba289af8SRoger Chen static const struct rk_gmac_ops rk3399_ops = { 752ba289af8SRoger Chen .set_to_rgmii = rk3399_set_to_rgmii, 753ba289af8SRoger Chen .set_to_rmii = rk3399_set_to_rmii, 754ba289af8SRoger Chen .set_rgmii_speed = rk3399_set_rgmii_speed, 755ba289af8SRoger Chen .set_rmii_speed = rk3399_set_rmii_speed, 756ba289af8SRoger Chen }; 757ba289af8SRoger Chen 758*fecd4d7eSDavid Wu #define RK_GRF_MACPHY_CON0 0xb00 759*fecd4d7eSDavid Wu #define RK_GRF_MACPHY_CON1 0xb04 760*fecd4d7eSDavid Wu #define RK_GRF_MACPHY_CON2 0xb08 761*fecd4d7eSDavid Wu #define RK_GRF_MACPHY_CON3 0xb0c 762*fecd4d7eSDavid Wu 763*fecd4d7eSDavid Wu #define RK_MACPHY_ENABLE GRF_BIT(0) 764*fecd4d7eSDavid Wu #define RK_MACPHY_DISABLE GRF_CLR_BIT(0) 765*fecd4d7eSDavid Wu #define RK_MACPHY_CFG_CLK_50M GRF_BIT(14) 766*fecd4d7eSDavid Wu #define RK_GMAC2PHY_RMII_MODE (GRF_BIT(6) | GRF_CLR_BIT(7)) 767*fecd4d7eSDavid Wu #define RK_GRF_CON2_MACPHY_ID HIWORD_UPDATE(0x1234, 0xffff, 0) 768*fecd4d7eSDavid Wu #define RK_GRF_CON3_MACPHY_ID HIWORD_UPDATE(0x35, 0x3f, 0) 769*fecd4d7eSDavid Wu 770*fecd4d7eSDavid Wu static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv) 7717ad269eaSRoger Chen { 772*fecd4d7eSDavid Wu if (priv->ops->integrated_phy_powerup) 773*fecd4d7eSDavid Wu priv->ops->integrated_phy_powerup(priv); 774*fecd4d7eSDavid Wu 775*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M); 776*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE); 777*fecd4d7eSDavid Wu 778*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID); 779*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID); 780*fecd4d7eSDavid Wu 781*fecd4d7eSDavid Wu if (priv->phy_reset) { 782*fecd4d7eSDavid Wu /* PHY needs to be disabled before trying to reset it */ 783*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE); 784*fecd4d7eSDavid Wu if (priv->phy_reset) 785*fecd4d7eSDavid Wu reset_control_assert(priv->phy_reset); 786*fecd4d7eSDavid Wu usleep_range(10, 20); 787*fecd4d7eSDavid Wu if (priv->phy_reset) 788*fecd4d7eSDavid Wu reset_control_deassert(priv->phy_reset); 789*fecd4d7eSDavid Wu usleep_range(10, 20); 790*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE); 791*fecd4d7eSDavid Wu msleep(30); 792*fecd4d7eSDavid Wu } 793*fecd4d7eSDavid Wu } 794*fecd4d7eSDavid Wu 795*fecd4d7eSDavid Wu static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv) 796*fecd4d7eSDavid Wu { 797*fecd4d7eSDavid Wu regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE); 798*fecd4d7eSDavid Wu if (priv->phy_reset) 799*fecd4d7eSDavid Wu reset_control_assert(priv->phy_reset); 800*fecd4d7eSDavid Wu } 801*fecd4d7eSDavid Wu 802*fecd4d7eSDavid Wu static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) 803*fecd4d7eSDavid Wu { 804*fecd4d7eSDavid Wu struct rk_priv_data *bsp_priv = plat->bsp_priv; 8057ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 806*fecd4d7eSDavid Wu int ret; 8077ad269eaSRoger Chen 8087ad269eaSRoger Chen bsp_priv->clk_enabled = false; 8097ad269eaSRoger Chen 8107ad269eaSRoger Chen bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx"); 8117ad269eaSRoger Chen if (IS_ERR(bsp_priv->mac_clk_rx)) 812d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 813d42202dcSRomain Perier "mac_clk_rx"); 8147ad269eaSRoger Chen 8157ad269eaSRoger Chen bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx"); 8167ad269eaSRoger Chen if (IS_ERR(bsp_priv->mac_clk_tx)) 817d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 818d42202dcSRomain Perier "mac_clk_tx"); 8197ad269eaSRoger Chen 8207ad269eaSRoger Chen bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac"); 8217ad269eaSRoger Chen if (IS_ERR(bsp_priv->aclk_mac)) 822d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 823d42202dcSRomain Perier "aclk_mac"); 8247ad269eaSRoger Chen 8257ad269eaSRoger Chen bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac"); 8267ad269eaSRoger Chen if (IS_ERR(bsp_priv->pclk_mac)) 827d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 828d42202dcSRomain Perier "pclk_mac"); 8297ad269eaSRoger Chen 8307ad269eaSRoger Chen bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth"); 8317ad269eaSRoger Chen if (IS_ERR(bsp_priv->clk_mac)) 832d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 833d42202dcSRomain Perier "stmmaceth"); 8347ad269eaSRoger Chen 8357ad269eaSRoger Chen if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { 8367ad269eaSRoger Chen bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref"); 8377ad269eaSRoger Chen if (IS_ERR(bsp_priv->clk_mac_ref)) 838d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 839d42202dcSRomain Perier "clk_mac_ref"); 8407ad269eaSRoger Chen 8417ad269eaSRoger Chen if (!bsp_priv->clock_input) { 8427ad269eaSRoger Chen bsp_priv->clk_mac_refout = 8437ad269eaSRoger Chen devm_clk_get(dev, "clk_mac_refout"); 8447ad269eaSRoger Chen if (IS_ERR(bsp_priv->clk_mac_refout)) 845d42202dcSRomain Perier dev_err(dev, "cannot get clock %s\n", 846d42202dcSRomain Perier "clk_mac_refout"); 8477ad269eaSRoger Chen } 8487ad269eaSRoger Chen } 8497ad269eaSRoger Chen 8507ad269eaSRoger Chen if (bsp_priv->clock_input) { 851d42202dcSRomain Perier dev_info(dev, "clock input from PHY\n"); 8527ad269eaSRoger Chen } else { 8537ad269eaSRoger Chen if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) 854c48fa33cSHeiko Stübner clk_set_rate(bsp_priv->clk_mac, 50000000); 8557ad269eaSRoger Chen } 8567ad269eaSRoger Chen 857*fecd4d7eSDavid Wu if (plat->phy_node && bsp_priv->integrated_phy) { 858*fecd4d7eSDavid Wu bsp_priv->clk_phy = of_clk_get(plat->phy_node, 0); 859*fecd4d7eSDavid Wu if (IS_ERR(bsp_priv->clk_phy)) { 860*fecd4d7eSDavid Wu ret = PTR_ERR(bsp_priv->clk_phy); 861*fecd4d7eSDavid Wu dev_err(dev, "Cannot get PHY clock: %d\n", ret); 862*fecd4d7eSDavid Wu return -EINVAL; 863*fecd4d7eSDavid Wu } 864*fecd4d7eSDavid Wu clk_set_rate(bsp_priv->clk_phy, 50000000); 865*fecd4d7eSDavid Wu } 866*fecd4d7eSDavid Wu 8677ad269eaSRoger Chen return 0; 8687ad269eaSRoger Chen } 8697ad269eaSRoger Chen 8707ad269eaSRoger Chen static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) 8717ad269eaSRoger Chen { 872428ad1bcSLABBE Corentin int phy_iface = bsp_priv->phy_iface; 8737ad269eaSRoger Chen 8747ad269eaSRoger Chen if (enable) { 8757ad269eaSRoger Chen if (!bsp_priv->clk_enabled) { 8767ad269eaSRoger Chen if (phy_iface == PHY_INTERFACE_MODE_RMII) { 8777ad269eaSRoger Chen if (!IS_ERR(bsp_priv->mac_clk_rx)) 8787ad269eaSRoger Chen clk_prepare_enable( 8797ad269eaSRoger Chen bsp_priv->mac_clk_rx); 8807ad269eaSRoger Chen 8817ad269eaSRoger Chen if (!IS_ERR(bsp_priv->clk_mac_ref)) 8827ad269eaSRoger Chen clk_prepare_enable( 8837ad269eaSRoger Chen bsp_priv->clk_mac_ref); 8847ad269eaSRoger Chen 8857ad269eaSRoger Chen if (!IS_ERR(bsp_priv->clk_mac_refout)) 8867ad269eaSRoger Chen clk_prepare_enable( 8877ad269eaSRoger Chen bsp_priv->clk_mac_refout); 8887ad269eaSRoger Chen } 8897ad269eaSRoger Chen 890*fecd4d7eSDavid Wu if (!IS_ERR(bsp_priv->clk_phy)) 891*fecd4d7eSDavid Wu clk_prepare_enable(bsp_priv->clk_phy); 892*fecd4d7eSDavid Wu 8937ad269eaSRoger Chen if (!IS_ERR(bsp_priv->aclk_mac)) 8947ad269eaSRoger Chen clk_prepare_enable(bsp_priv->aclk_mac); 8957ad269eaSRoger Chen 8967ad269eaSRoger Chen if (!IS_ERR(bsp_priv->pclk_mac)) 8977ad269eaSRoger Chen clk_prepare_enable(bsp_priv->pclk_mac); 8987ad269eaSRoger Chen 8997ad269eaSRoger Chen if (!IS_ERR(bsp_priv->mac_clk_tx)) 9007ad269eaSRoger Chen clk_prepare_enable(bsp_priv->mac_clk_tx); 9017ad269eaSRoger Chen 9027ad269eaSRoger Chen /** 9037ad269eaSRoger Chen * if (!IS_ERR(bsp_priv->clk_mac)) 9047ad269eaSRoger Chen * clk_prepare_enable(bsp_priv->clk_mac); 9057ad269eaSRoger Chen */ 9067ad269eaSRoger Chen mdelay(5); 9077ad269eaSRoger Chen bsp_priv->clk_enabled = true; 9087ad269eaSRoger Chen } 9097ad269eaSRoger Chen } else { 9107ad269eaSRoger Chen if (bsp_priv->clk_enabled) { 9117ad269eaSRoger Chen if (phy_iface == PHY_INTERFACE_MODE_RMII) { 9127ad269eaSRoger Chen if (!IS_ERR(bsp_priv->mac_clk_rx)) 9137ad269eaSRoger Chen clk_disable_unprepare( 9147ad269eaSRoger Chen bsp_priv->mac_clk_rx); 9157ad269eaSRoger Chen 9167ad269eaSRoger Chen if (!IS_ERR(bsp_priv->clk_mac_ref)) 9177ad269eaSRoger Chen clk_disable_unprepare( 9187ad269eaSRoger Chen bsp_priv->clk_mac_ref); 9197ad269eaSRoger Chen 9207ad269eaSRoger Chen if (!IS_ERR(bsp_priv->clk_mac_refout)) 9217ad269eaSRoger Chen clk_disable_unprepare( 9227ad269eaSRoger Chen bsp_priv->clk_mac_refout); 9237ad269eaSRoger Chen } 9247ad269eaSRoger Chen 925*fecd4d7eSDavid Wu if (!IS_ERR(bsp_priv->clk_phy)) 926*fecd4d7eSDavid Wu clk_disable_unprepare(bsp_priv->clk_phy); 927*fecd4d7eSDavid Wu 9287ad269eaSRoger Chen if (!IS_ERR(bsp_priv->aclk_mac)) 9297ad269eaSRoger Chen clk_disable_unprepare(bsp_priv->aclk_mac); 9307ad269eaSRoger Chen 9317ad269eaSRoger Chen if (!IS_ERR(bsp_priv->pclk_mac)) 9327ad269eaSRoger Chen clk_disable_unprepare(bsp_priv->pclk_mac); 9337ad269eaSRoger Chen 9347ad269eaSRoger Chen if (!IS_ERR(bsp_priv->mac_clk_tx)) 9357ad269eaSRoger Chen clk_disable_unprepare(bsp_priv->mac_clk_tx); 9367ad269eaSRoger Chen /** 9377ad269eaSRoger Chen * if (!IS_ERR(bsp_priv->clk_mac)) 9387ad269eaSRoger Chen * clk_disable_unprepare(bsp_priv->clk_mac); 9397ad269eaSRoger Chen */ 9407ad269eaSRoger Chen bsp_priv->clk_enabled = false; 9417ad269eaSRoger Chen } 9427ad269eaSRoger Chen } 9437ad269eaSRoger Chen 9447ad269eaSRoger Chen return 0; 9457ad269eaSRoger Chen } 9467ad269eaSRoger Chen 9477ad269eaSRoger Chen static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable) 9487ad269eaSRoger Chen { 9492e12f536SRomain Perier struct regulator *ldo = bsp_priv->regulator; 9507ad269eaSRoger Chen int ret; 9517ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 9527ad269eaSRoger Chen 9532e12f536SRomain Perier if (!ldo) { 954d42202dcSRomain Perier dev_err(dev, "no regulator found\n"); 9557ad269eaSRoger Chen return -1; 9567ad269eaSRoger Chen } 9577ad269eaSRoger Chen 9587ad269eaSRoger Chen if (enable) { 9597ad269eaSRoger Chen ret = regulator_enable(ldo); 9602e12f536SRomain Perier if (ret) 961d42202dcSRomain Perier dev_err(dev, "fail to enable phy-supply\n"); 9627ad269eaSRoger Chen } else { 9637ad269eaSRoger Chen ret = regulator_disable(ldo); 9642e12f536SRomain Perier if (ret) 965d42202dcSRomain Perier dev_err(dev, "fail to disable phy-supply\n"); 9667ad269eaSRoger Chen } 9677ad269eaSRoger Chen 9687ad269eaSRoger Chen return 0; 9697ad269eaSRoger Chen } 9707ad269eaSRoger Chen 9710fb98db1SHeiko Stübner static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, 972*fecd4d7eSDavid Wu struct plat_stmmacenet_data *plat, 97392c2588fSJoachim Eastwood const struct rk_gmac_ops *ops) 9747ad269eaSRoger Chen { 9757ad269eaSRoger Chen struct rk_priv_data *bsp_priv; 9767ad269eaSRoger Chen struct device *dev = &pdev->dev; 9777ad269eaSRoger Chen int ret; 9787ad269eaSRoger Chen const char *strings = NULL; 9797ad269eaSRoger Chen int value; 9807ad269eaSRoger Chen 9817ad269eaSRoger Chen bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL); 9827ad269eaSRoger Chen if (!bsp_priv) 9837ad269eaSRoger Chen return ERR_PTR(-ENOMEM); 9847ad269eaSRoger Chen 9857ad269eaSRoger Chen bsp_priv->phy_iface = of_get_phy_mode(dev->of_node); 9860fb98db1SHeiko Stübner bsp_priv->ops = ops; 9877ad269eaSRoger Chen 9882e12f536SRomain Perier bsp_priv->regulator = devm_regulator_get_optional(dev, "phy"); 9892e12f536SRomain Perier if (IS_ERR(bsp_priv->regulator)) { 9902e12f536SRomain Perier if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) { 9912e12f536SRomain Perier dev_err(dev, "phy regulator is not available yet, deferred probing\n"); 9922e12f536SRomain Perier return ERR_PTR(-EPROBE_DEFER); 9932e12f536SRomain Perier } 9942e12f536SRomain Perier dev_err(dev, "no regulator found\n"); 9952e12f536SRomain Perier bsp_priv->regulator = NULL; 9967ad269eaSRoger Chen } 9977ad269eaSRoger Chen 9987ad269eaSRoger Chen ret = of_property_read_string(dev->of_node, "clock_in_out", &strings); 9997ad269eaSRoger Chen if (ret) { 1000d42202dcSRomain Perier dev_err(dev, "Can not read property: clock_in_out.\n"); 10017ad269eaSRoger Chen bsp_priv->clock_input = true; 10027ad269eaSRoger Chen } else { 1003d42202dcSRomain Perier dev_info(dev, "clock input or output? (%s).\n", 1004d42202dcSRomain Perier strings); 10057ad269eaSRoger Chen if (!strcmp(strings, "input")) 10067ad269eaSRoger Chen bsp_priv->clock_input = true; 10077ad269eaSRoger Chen else 10087ad269eaSRoger Chen bsp_priv->clock_input = false; 10097ad269eaSRoger Chen } 10107ad269eaSRoger Chen 10117ad269eaSRoger Chen ret = of_property_read_u32(dev->of_node, "tx_delay", &value); 10127ad269eaSRoger Chen if (ret) { 10137ad269eaSRoger Chen bsp_priv->tx_delay = 0x30; 1014d42202dcSRomain Perier dev_err(dev, "Can not read property: tx_delay."); 1015d42202dcSRomain Perier dev_err(dev, "set tx_delay to 0x%x\n", 1016d42202dcSRomain Perier bsp_priv->tx_delay); 10177ad269eaSRoger Chen } else { 1018d42202dcSRomain Perier dev_info(dev, "TX delay(0x%x).\n", value); 10197ad269eaSRoger Chen bsp_priv->tx_delay = value; 10207ad269eaSRoger Chen } 10217ad269eaSRoger Chen 10227ad269eaSRoger Chen ret = of_property_read_u32(dev->of_node, "rx_delay", &value); 10237ad269eaSRoger Chen if (ret) { 10247ad269eaSRoger Chen bsp_priv->rx_delay = 0x10; 1025d42202dcSRomain Perier dev_err(dev, "Can not read property: rx_delay."); 1026d42202dcSRomain Perier dev_err(dev, "set rx_delay to 0x%x\n", 1027d42202dcSRomain Perier bsp_priv->rx_delay); 10287ad269eaSRoger Chen } else { 1029d42202dcSRomain Perier dev_info(dev, "RX delay(0x%x).\n", value); 10307ad269eaSRoger Chen bsp_priv->rx_delay = value; 10317ad269eaSRoger Chen } 10327ad269eaSRoger Chen 10337ad269eaSRoger Chen bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, 10347ad269eaSRoger Chen "rockchip,grf"); 10357ad269eaSRoger Chen 1036*fecd4d7eSDavid Wu if (plat->phy_node) { 1037*fecd4d7eSDavid Wu bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node, 1038*fecd4d7eSDavid Wu "phy-is-integrated"); 1039*fecd4d7eSDavid Wu if (bsp_priv->integrated_phy) { 1040*fecd4d7eSDavid Wu bsp_priv->phy_reset = of_reset_control_get(plat->phy_node, NULL); 1041*fecd4d7eSDavid Wu if (IS_ERR(bsp_priv->phy_reset)) { 1042*fecd4d7eSDavid Wu dev_err(&pdev->dev, "No PHY reset control found.\n"); 1043*fecd4d7eSDavid Wu bsp_priv->phy_reset = NULL; 1044*fecd4d7eSDavid Wu } 1045*fecd4d7eSDavid Wu } 1046*fecd4d7eSDavid Wu } 1047*fecd4d7eSDavid Wu dev_info(dev, "integrated PHY? (%s).\n", 1048*fecd4d7eSDavid Wu bsp_priv->integrated_phy ? "yes" : "no"); 1049*fecd4d7eSDavid Wu 1050*fecd4d7eSDavid Wu bsp_priv->pdev = pdev; 105145383f52SRoger Chen 105245383f52SRoger Chen return bsp_priv; 105345383f52SRoger Chen } 105445383f52SRoger Chen 105545383f52SRoger Chen static int rk_gmac_powerup(struct rk_priv_data *bsp_priv) 105645383f52SRoger Chen { 105745383f52SRoger Chen int ret; 105845383f52SRoger Chen struct device *dev = &bsp_priv->pdev->dev; 105945383f52SRoger Chen 1060f217bfdeSHeiko Stübner ret = gmac_clk_enable(bsp_priv, true); 1061f217bfdeSHeiko Stübner if (ret) 1062f217bfdeSHeiko Stübner return ret; 1063f217bfdeSHeiko Stübner 10647ad269eaSRoger Chen /*rmii or rgmii*/ 1065eaf70ad1SWadim Egorov switch (bsp_priv->phy_iface) { 1066eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII: 1067d42202dcSRomain Perier dev_info(dev, "init for RGMII\n"); 10680fb98db1SHeiko Stübner bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, 10690fb98db1SHeiko Stübner bsp_priv->rx_delay); 1070eaf70ad1SWadim Egorov break; 1071eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII_ID: 1072eaf70ad1SWadim Egorov dev_info(dev, "init for RGMII_ID\n"); 1073eaf70ad1SWadim Egorov bsp_priv->ops->set_to_rgmii(bsp_priv, 0, 0); 1074eaf70ad1SWadim Egorov break; 1075eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII_RXID: 1076eaf70ad1SWadim Egorov dev_info(dev, "init for RGMII_RXID\n"); 1077eaf70ad1SWadim Egorov bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, 0); 1078eaf70ad1SWadim Egorov break; 1079eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII_TXID: 1080eaf70ad1SWadim Egorov dev_info(dev, "init for RGMII_TXID\n"); 1081eaf70ad1SWadim Egorov bsp_priv->ops->set_to_rgmii(bsp_priv, 0, bsp_priv->rx_delay); 1082eaf70ad1SWadim Egorov break; 1083eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RMII: 1084d42202dcSRomain Perier dev_info(dev, "init for RMII\n"); 10850fb98db1SHeiko Stübner bsp_priv->ops->set_to_rmii(bsp_priv); 1086eaf70ad1SWadim Egorov break; 1087eaf70ad1SWadim Egorov default: 1088d42202dcSRomain Perier dev_err(dev, "NO interface defined!\n"); 10897ad269eaSRoger Chen } 10907ad269eaSRoger Chen 10917ad269eaSRoger Chen ret = phy_power_on(bsp_priv, true); 10927ad269eaSRoger Chen if (ret) 10937ad269eaSRoger Chen return ret; 10947ad269eaSRoger Chen 10952c896fb0SDavid Wu pm_runtime_enable(dev); 10962c896fb0SDavid Wu pm_runtime_get_sync(dev); 10972c896fb0SDavid Wu 1098*fecd4d7eSDavid Wu if (bsp_priv->integrated_phy) 1099*fecd4d7eSDavid Wu rk_gmac_integrated_phy_powerup(bsp_priv); 1100*fecd4d7eSDavid Wu 11017ad269eaSRoger Chen return 0; 11027ad269eaSRoger Chen } 11037ad269eaSRoger Chen 1104229666c1SVincent Palatin static void rk_gmac_powerdown(struct rk_priv_data *gmac) 11057ad269eaSRoger Chen { 11062c896fb0SDavid Wu struct device *dev = &gmac->pdev->dev; 11072c896fb0SDavid Wu 1108*fecd4d7eSDavid Wu if (gmac->integrated_phy) 1109*fecd4d7eSDavid Wu rk_gmac_integrated_phy_powerdown(gmac); 1110*fecd4d7eSDavid Wu 11112c896fb0SDavid Wu pm_runtime_put_sync(dev); 11122c896fb0SDavid Wu pm_runtime_disable(dev); 11132c896fb0SDavid Wu 11147ad269eaSRoger Chen phy_power_on(gmac, false); 11157ad269eaSRoger Chen gmac_clk_enable(gmac, false); 11167ad269eaSRoger Chen } 11177ad269eaSRoger Chen 11187ad269eaSRoger Chen static void rk_fix_speed(void *priv, unsigned int speed) 11197ad269eaSRoger Chen { 11207ad269eaSRoger Chen struct rk_priv_data *bsp_priv = priv; 11217ad269eaSRoger Chen struct device *dev = &bsp_priv->pdev->dev; 11227ad269eaSRoger Chen 1123eaf70ad1SWadim Egorov switch (bsp_priv->phy_iface) { 1124eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII: 1125eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII_ID: 1126eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII_RXID: 1127eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RGMII_TXID: 11280fb98db1SHeiko Stübner bsp_priv->ops->set_rgmii_speed(bsp_priv, speed); 1129eaf70ad1SWadim Egorov break; 1130eaf70ad1SWadim Egorov case PHY_INTERFACE_MODE_RMII: 11310fb98db1SHeiko Stübner bsp_priv->ops->set_rmii_speed(bsp_priv, speed); 1132eaf70ad1SWadim Egorov break; 1133eaf70ad1SWadim Egorov default: 11347ad269eaSRoger Chen dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); 11357ad269eaSRoger Chen } 1136eaf70ad1SWadim Egorov } 11377ad269eaSRoger Chen 113827ffefd2SJoachim Eastwood static int rk_gmac_probe(struct platform_device *pdev) 113927ffefd2SJoachim Eastwood { 114027ffefd2SJoachim Eastwood struct plat_stmmacenet_data *plat_dat; 114127ffefd2SJoachim Eastwood struct stmmac_resources stmmac_res; 1142f529f182SJoachim Eastwood const struct rk_gmac_ops *data; 114327ffefd2SJoachim Eastwood int ret; 114427ffefd2SJoachim Eastwood 1145149adeddSJoachim Eastwood data = of_device_get_match_data(&pdev->dev); 1146149adeddSJoachim Eastwood if (!data) { 1147149adeddSJoachim Eastwood dev_err(&pdev->dev, "no of match data provided\n"); 1148149adeddSJoachim Eastwood return -EINVAL; 1149149adeddSJoachim Eastwood } 1150149adeddSJoachim Eastwood 115127ffefd2SJoachim Eastwood ret = stmmac_get_platform_resources(pdev, &stmmac_res); 115227ffefd2SJoachim Eastwood if (ret) 115327ffefd2SJoachim Eastwood return ret; 115427ffefd2SJoachim Eastwood 115527ffefd2SJoachim Eastwood plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 115627ffefd2SJoachim Eastwood if (IS_ERR(plat_dat)) 115727ffefd2SJoachim Eastwood return PTR_ERR(plat_dat); 115827ffefd2SJoachim Eastwood 115927ffefd2SJoachim Eastwood plat_dat->has_gmac = true; 116027ffefd2SJoachim Eastwood plat_dat->fix_mac_speed = rk_fix_speed; 116127ffefd2SJoachim Eastwood 1162*fecd4d7eSDavid Wu plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data); 1163d2ed0a77SJohan Hovold if (IS_ERR(plat_dat->bsp_priv)) { 1164d2ed0a77SJohan Hovold ret = PTR_ERR(plat_dat->bsp_priv); 1165d2ed0a77SJohan Hovold goto err_remove_config_dt; 1166d2ed0a77SJohan Hovold } 116727ffefd2SJoachim Eastwood 1168*fecd4d7eSDavid Wu ret = rk_gmac_clk_init(plat_dat); 1169*fecd4d7eSDavid Wu if (ret) 1170*fecd4d7eSDavid Wu return ret; 1171*fecd4d7eSDavid Wu 117207a5e769SJoachim Eastwood ret = rk_gmac_powerup(plat_dat->bsp_priv); 117327ffefd2SJoachim Eastwood if (ret) 1174d2ed0a77SJohan Hovold goto err_remove_config_dt; 117527ffefd2SJoachim Eastwood 11762d222656SJohan Hovold ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 11772d222656SJohan Hovold if (ret) 11782745529aSDavid S. Miller goto err_gmac_powerdown; 11792d222656SJohan Hovold 11802d222656SJohan Hovold return 0; 11812d222656SJohan Hovold 11822745529aSDavid S. Miller err_gmac_powerdown: 11832745529aSDavid S. Miller rk_gmac_powerdown(plat_dat->bsp_priv); 1184d2ed0a77SJohan Hovold err_remove_config_dt: 1185d2ed0a77SJohan Hovold stmmac_remove_config_dt(pdev, plat_dat); 11862d222656SJohan Hovold 11872d222656SJohan Hovold return ret; 118827ffefd2SJoachim Eastwood } 118927ffefd2SJoachim Eastwood 11900de8c4c9SJoachim Eastwood static int rk_gmac_remove(struct platform_device *pdev) 11910de8c4c9SJoachim Eastwood { 11920de8c4c9SJoachim Eastwood struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev); 11930de8c4c9SJoachim Eastwood int ret = stmmac_dvr_remove(&pdev->dev); 11940de8c4c9SJoachim Eastwood 11950de8c4c9SJoachim Eastwood rk_gmac_powerdown(bsp_priv); 11960de8c4c9SJoachim Eastwood 11970de8c4c9SJoachim Eastwood return ret; 11980de8c4c9SJoachim Eastwood } 11990de8c4c9SJoachim Eastwood 12005619468aSJoachim Eastwood #ifdef CONFIG_PM_SLEEP 12015619468aSJoachim Eastwood static int rk_gmac_suspend(struct device *dev) 12025619468aSJoachim Eastwood { 12035619468aSJoachim Eastwood struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev); 12045619468aSJoachim Eastwood int ret = stmmac_suspend(dev); 12055619468aSJoachim Eastwood 12065619468aSJoachim Eastwood /* Keep the PHY up if we use Wake-on-Lan. */ 12075619468aSJoachim Eastwood if (!device_may_wakeup(dev)) { 12085619468aSJoachim Eastwood rk_gmac_powerdown(bsp_priv); 12095619468aSJoachim Eastwood bsp_priv->suspended = true; 12105619468aSJoachim Eastwood } 12115619468aSJoachim Eastwood 12125619468aSJoachim Eastwood return ret; 12135619468aSJoachim Eastwood } 12145619468aSJoachim Eastwood 12155619468aSJoachim Eastwood static int rk_gmac_resume(struct device *dev) 12165619468aSJoachim Eastwood { 12175619468aSJoachim Eastwood struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev); 12185619468aSJoachim Eastwood 12195619468aSJoachim Eastwood /* The PHY was up for Wake-on-Lan. */ 12205619468aSJoachim Eastwood if (bsp_priv->suspended) { 12215619468aSJoachim Eastwood rk_gmac_powerup(bsp_priv); 12225619468aSJoachim Eastwood bsp_priv->suspended = false; 12235619468aSJoachim Eastwood } 12245619468aSJoachim Eastwood 12255619468aSJoachim Eastwood return stmmac_resume(dev); 12265619468aSJoachim Eastwood } 12275619468aSJoachim Eastwood #endif /* CONFIG_PM_SLEEP */ 12285619468aSJoachim Eastwood 12295619468aSJoachim Eastwood static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume); 12305619468aSJoachim Eastwood 1231e0fb4013SJoachim Eastwood static const struct of_device_id rk_gmac_dwmac_match[] = { 1232e7ffd812SXing Zheng { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, 1233f529f182SJoachim Eastwood { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, 1234d4ff816eSdavid.wu { .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops }, 1235ba289af8SRoger Chen { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops }, 1236f529f182SJoachim Eastwood { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, 1237ba289af8SRoger Chen { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops }, 1238e0fb4013SJoachim Eastwood { } 1239e0fb4013SJoachim Eastwood }; 1240e0fb4013SJoachim Eastwood MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match); 1241e0fb4013SJoachim Eastwood 1242e0fb4013SJoachim Eastwood static struct platform_driver rk_gmac_dwmac_driver = { 124327ffefd2SJoachim Eastwood .probe = rk_gmac_probe, 12440de8c4c9SJoachim Eastwood .remove = rk_gmac_remove, 1245e0fb4013SJoachim Eastwood .driver = { 1246e0fb4013SJoachim Eastwood .name = "rk_gmac-dwmac", 12475619468aSJoachim Eastwood .pm = &rk_gmac_pm_ops, 1248e0fb4013SJoachim Eastwood .of_match_table = rk_gmac_dwmac_match, 1249e0fb4013SJoachim Eastwood }, 1250e0fb4013SJoachim Eastwood }; 1251e0fb4013SJoachim Eastwood module_platform_driver(rk_gmac_dwmac_driver); 1252e0fb4013SJoachim Eastwood 1253e0fb4013SJoachim Eastwood MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>"); 1254e0fb4013SJoachim Eastwood MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer"); 1255e0fb4013SJoachim Eastwood MODULE_LICENSE("GPL"); 1256