diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c')
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 93 |
1 files changed, 76 insertions, 17 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 13133b30b575..7b923362ee55 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | |||
| @@ -61,6 +61,7 @@ struct rk_priv_data { | |||
| 61 | struct clk *mac_clk_tx; | 61 | struct clk *mac_clk_tx; |
| 62 | struct clk *clk_mac_ref; | 62 | struct clk *clk_mac_ref; |
| 63 | struct clk *clk_mac_refout; | 63 | struct clk *clk_mac_refout; |
| 64 | struct clk *clk_mac_speed; | ||
| 64 | struct clk *aclk_mac; | 65 | struct clk *aclk_mac; |
| 65 | struct clk *pclk_mac; | 66 | struct clk *pclk_mac; |
| 66 | struct clk *clk_phy; | 67 | struct clk *clk_phy; |
| @@ -83,6 +84,64 @@ struct rk_priv_data { | |||
| 83 | (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ | 84 | (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ |
| 84 | ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) | 85 | ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) |
| 85 | 86 | ||
| 87 | #define PX30_GRF_GMAC_CON1 0x0904 | ||
| 88 | |||
| 89 | /* PX30_GRF_GMAC_CON1 */ | ||
| 90 | #define PX30_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | \ | ||
| 91 | GRF_BIT(6)) | ||
| 92 | #define PX30_GMAC_SPEED_10M GRF_CLR_BIT(2) | ||
| 93 | #define PX30_GMAC_SPEED_100M GRF_BIT(2) | ||
| 94 | |||
| 95 | static void px30_set_to_rmii(struct rk_priv_data *bsp_priv) | ||
| 96 | { | ||
| 97 | struct device *dev = &bsp_priv->pdev->dev; | ||
| 98 | |||
| 99 | if (IS_ERR(bsp_priv->grf)) { | ||
| 100 | dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | |||
| 104 | regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, | ||
| 105 | PX30_GMAC_PHY_INTF_SEL_RMII); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) | ||
| 109 | { | ||
| 110 | struct device *dev = &bsp_priv->pdev->dev; | ||
| 111 | int ret; | ||
| 112 | |||
| 113 | if (IS_ERR(bsp_priv->clk_mac_speed)) { | ||
| 114 | dev_err(dev, "%s: Missing clk_mac_speed clock\n", __func__); | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | |||
| 118 | if (speed == 10) { | ||
| 119 | regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, | ||
| 120 | PX30_GMAC_SPEED_10M); | ||
| 121 | |||
| 122 | ret = clk_set_rate(bsp_priv->clk_mac_speed, 2500000); | ||
| 123 | if (ret) | ||
| 124 | dev_err(dev, "%s: set clk_mac_speed rate 2500000 failed: %d\n", | ||
| 125 | __func__, ret); | ||
| 126 | } else if (speed == 100) { | ||
| 127 | regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, | ||
| 128 | PX30_GMAC_SPEED_100M); | ||
| 129 | |||
| 130 | ret = clk_set_rate(bsp_priv->clk_mac_speed, 25000000); | ||
| 131 | if (ret) | ||
| 132 | dev_err(dev, "%s: set clk_mac_speed rate 25000000 failed: %d\n", | ||
| 133 | __func__, ret); | ||
| 134 | |||
| 135 | } else { | ||
| 136 | dev_err(dev, "unknown speed value for RMII! speed=%d", speed); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | static const struct rk_gmac_ops px30_ops = { | ||
| 141 | .set_to_rmii = px30_set_to_rmii, | ||
| 142 | .set_rmii_speed = px30_set_rmii_speed, | ||
| 143 | }; | ||
| 144 | |||
| 86 | #define RK3128_GRF_MAC_CON0 0x0168 | 145 | #define RK3128_GRF_MAC_CON0 0x0168 |
| 87 | #define RK3128_GRF_MAC_CON1 0x016c | 146 | #define RK3128_GRF_MAC_CON1 0x016c |
| 88 | 147 | ||
| @@ -1042,6 +1101,10 @@ static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) | |||
| 1042 | } | 1101 | } |
| 1043 | } | 1102 | } |
| 1044 | 1103 | ||
| 1104 | bsp_priv->clk_mac_speed = devm_clk_get(dev, "clk_mac_speed"); | ||
| 1105 | if (IS_ERR(bsp_priv->clk_mac_speed)) | ||
| 1106 | dev_err(dev, "cannot get clock %s\n", "clk_mac_speed"); | ||
| 1107 | |||
| 1045 | if (bsp_priv->clock_input) { | 1108 | if (bsp_priv->clock_input) { |
| 1046 | dev_info(dev, "clock input from PHY\n"); | 1109 | dev_info(dev, "clock input from PHY\n"); |
| 1047 | } else { | 1110 | } else { |
| @@ -1094,6 +1157,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) | |||
| 1094 | if (!IS_ERR(bsp_priv->mac_clk_tx)) | 1157 | if (!IS_ERR(bsp_priv->mac_clk_tx)) |
| 1095 | clk_prepare_enable(bsp_priv->mac_clk_tx); | 1158 | clk_prepare_enable(bsp_priv->mac_clk_tx); |
| 1096 | 1159 | ||
| 1160 | if (!IS_ERR(bsp_priv->clk_mac_speed)) | ||
| 1161 | clk_prepare_enable(bsp_priv->clk_mac_speed); | ||
| 1162 | |||
| 1097 | /** | 1163 | /** |
| 1098 | * if (!IS_ERR(bsp_priv->clk_mac)) | 1164 | * if (!IS_ERR(bsp_priv->clk_mac)) |
| 1099 | * clk_prepare_enable(bsp_priv->clk_mac); | 1165 | * clk_prepare_enable(bsp_priv->clk_mac); |
| @@ -1104,30 +1170,22 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) | |||
| 1104 | } else { | 1170 | } else { |
| 1105 | if (bsp_priv->clk_enabled) { | 1171 | if (bsp_priv->clk_enabled) { |
| 1106 | if (phy_iface == PHY_INTERFACE_MODE_RMII) { | 1172 | if (phy_iface == PHY_INTERFACE_MODE_RMII) { |
| 1107 | if (!IS_ERR(bsp_priv->mac_clk_rx)) | 1173 | clk_disable_unprepare(bsp_priv->mac_clk_rx); |
| 1108 | clk_disable_unprepare( | ||
| 1109 | bsp_priv->mac_clk_rx); | ||
| 1110 | 1174 | ||
| 1111 | if (!IS_ERR(bsp_priv->clk_mac_ref)) | 1175 | clk_disable_unprepare(bsp_priv->clk_mac_ref); |
| 1112 | clk_disable_unprepare( | ||
| 1113 | bsp_priv->clk_mac_ref); | ||
| 1114 | 1176 | ||
| 1115 | if (!IS_ERR(bsp_priv->clk_mac_refout)) | 1177 | clk_disable_unprepare(bsp_priv->clk_mac_refout); |
| 1116 | clk_disable_unprepare( | ||
| 1117 | bsp_priv->clk_mac_refout); | ||
| 1118 | } | 1178 | } |
| 1119 | 1179 | ||
| 1120 | if (!IS_ERR(bsp_priv->clk_phy)) | 1180 | clk_disable_unprepare(bsp_priv->clk_phy); |
| 1121 | clk_disable_unprepare(bsp_priv->clk_phy); | ||
| 1122 | 1181 | ||
| 1123 | if (!IS_ERR(bsp_priv->aclk_mac)) | 1182 | clk_disable_unprepare(bsp_priv->aclk_mac); |
| 1124 | clk_disable_unprepare(bsp_priv->aclk_mac); | ||
| 1125 | 1183 | ||
| 1126 | if (!IS_ERR(bsp_priv->pclk_mac)) | 1184 | clk_disable_unprepare(bsp_priv->pclk_mac); |
| 1127 | clk_disable_unprepare(bsp_priv->pclk_mac); | ||
| 1128 | 1185 | ||
| 1129 | if (!IS_ERR(bsp_priv->mac_clk_tx)) | 1186 | clk_disable_unprepare(bsp_priv->mac_clk_tx); |
| 1130 | clk_disable_unprepare(bsp_priv->mac_clk_tx); | 1187 | |
| 1188 | clk_disable_unprepare(bsp_priv->clk_mac_speed); | ||
| 1131 | /** | 1189 | /** |
| 1132 | * if (!IS_ERR(bsp_priv->clk_mac)) | 1190 | * if (!IS_ERR(bsp_priv->clk_mac)) |
| 1133 | * clk_disable_unprepare(bsp_priv->clk_mac); | 1191 | * clk_disable_unprepare(bsp_priv->clk_mac); |
| @@ -1424,6 +1482,7 @@ static int rk_gmac_resume(struct device *dev) | |||
| 1424 | static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume); | 1482 | static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume); |
| 1425 | 1483 | ||
| 1426 | static const struct of_device_id rk_gmac_dwmac_match[] = { | 1484 | static const struct of_device_id rk_gmac_dwmac_match[] = { |
| 1485 | { .compatible = "rockchip,px30-gmac", .data = &px30_ops }, | ||
| 1427 | { .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops }, | 1486 | { .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops }, |
| 1428 | { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, | 1487 | { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, |
| 1429 | { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, | 1488 | { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, |
