0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/etherdevice.h>
0009 #include <linux/mfd/syscon.h>
0010 #include <linux/module.h>
0011 #include <linux/of_net.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/regmap.h>
0014 #include <linux/regulator/consumer.h>
0015
0016 #include "emac.h"
0017
0018 #define DRV_NAME "rockchip_emac"
0019
0020 struct emac_rockchip_soc_data {
0021 unsigned int grf_offset;
0022 unsigned int grf_mode_offset;
0023 unsigned int grf_speed_offset;
0024 bool need_div_macclk;
0025 };
0026
0027 struct rockchip_priv_data {
0028 struct arc_emac_priv emac;
0029 struct regmap *grf;
0030 const struct emac_rockchip_soc_data *soc_data;
0031 struct regulator *regulator;
0032 struct clk *refclk;
0033 struct clk *macclk;
0034 };
0035
0036 static void emac_rockchip_set_mac_speed(void *priv, unsigned int speed)
0037 {
0038 struct rockchip_priv_data *emac = priv;
0039 u32 speed_offset = emac->soc_data->grf_speed_offset;
0040 u32 data;
0041 int err = 0;
0042
0043 switch (speed) {
0044 case 10:
0045 data = (1 << (speed_offset + 16)) | (0 << speed_offset);
0046 break;
0047 case 100:
0048 data = (1 << (speed_offset + 16)) | (1 << speed_offset);
0049 break;
0050 default:
0051 pr_err("speed %u not supported\n", speed);
0052 return;
0053 }
0054
0055 err = regmap_write(emac->grf, emac->soc_data->grf_offset, data);
0056 if (err)
0057 pr_err("unable to apply speed %u to grf (%d)\n", speed, err);
0058 }
0059
0060 static const struct emac_rockchip_soc_data emac_rk3036_emac_data = {
0061 .grf_offset = 0x140, .grf_mode_offset = 8,
0062 .grf_speed_offset = 9, .need_div_macclk = 1,
0063 };
0064
0065 static const struct emac_rockchip_soc_data emac_rk3066_emac_data = {
0066 .grf_offset = 0x154, .grf_mode_offset = 0,
0067 .grf_speed_offset = 1, .need_div_macclk = 0,
0068 };
0069
0070 static const struct emac_rockchip_soc_data emac_rk3188_emac_data = {
0071 .grf_offset = 0x0a4, .grf_mode_offset = 0,
0072 .grf_speed_offset = 1, .need_div_macclk = 0,
0073 };
0074
0075 static const struct of_device_id emac_rockchip_dt_ids[] = {
0076 {
0077 .compatible = "rockchip,rk3036-emac",
0078 .data = &emac_rk3036_emac_data,
0079 },
0080 {
0081 .compatible = "rockchip,rk3066-emac",
0082 .data = &emac_rk3066_emac_data,
0083 },
0084 {
0085 .compatible = "rockchip,rk3188-emac",
0086 .data = &emac_rk3188_emac_data,
0087 },
0088 { }
0089 };
0090
0091 MODULE_DEVICE_TABLE(of, emac_rockchip_dt_ids);
0092
0093 static int emac_rockchip_probe(struct platform_device *pdev)
0094 {
0095 struct device *dev = &pdev->dev;
0096 struct net_device *ndev;
0097 struct rockchip_priv_data *priv;
0098 const struct of_device_id *match;
0099 phy_interface_t interface;
0100 u32 data;
0101 int err;
0102
0103 if (!pdev->dev.of_node)
0104 return -ENODEV;
0105
0106 ndev = alloc_etherdev(sizeof(struct rockchip_priv_data));
0107 if (!ndev)
0108 return -ENOMEM;
0109 platform_set_drvdata(pdev, ndev);
0110 SET_NETDEV_DEV(ndev, dev);
0111
0112 priv = netdev_priv(ndev);
0113 priv->emac.drv_name = DRV_NAME;
0114 priv->emac.set_mac_speed = emac_rockchip_set_mac_speed;
0115
0116 err = of_get_phy_mode(dev->of_node, &interface);
0117 if (err)
0118 goto out_netdev;
0119
0120
0121 if (interface != PHY_INTERFACE_MODE_RMII) {
0122 dev_err(dev, "unsupported phy interface mode %d\n", interface);
0123 err = -ENOTSUPP;
0124 goto out_netdev;
0125 }
0126
0127 priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
0128 "rockchip,grf");
0129 if (IS_ERR(priv->grf)) {
0130 dev_err(dev, "failed to retrieve global register file (%ld)\n",
0131 PTR_ERR(priv->grf));
0132 err = PTR_ERR(priv->grf);
0133 goto out_netdev;
0134 }
0135
0136 match = of_match_node(emac_rockchip_dt_ids, dev->of_node);
0137 priv->soc_data = match->data;
0138
0139 priv->emac.clk = devm_clk_get(dev, "hclk");
0140 if (IS_ERR(priv->emac.clk)) {
0141 dev_err(dev, "failed to retrieve host clock (%ld)\n",
0142 PTR_ERR(priv->emac.clk));
0143 err = PTR_ERR(priv->emac.clk);
0144 goto out_netdev;
0145 }
0146
0147 priv->refclk = devm_clk_get(dev, "macref");
0148 if (IS_ERR(priv->refclk)) {
0149 dev_err(dev, "failed to retrieve reference clock (%ld)\n",
0150 PTR_ERR(priv->refclk));
0151 err = PTR_ERR(priv->refclk);
0152 goto out_netdev;
0153 }
0154
0155 err = clk_prepare_enable(priv->refclk);
0156 if (err) {
0157 dev_err(dev, "failed to enable reference clock (%d)\n", err);
0158 goto out_netdev;
0159 }
0160
0161
0162 priv->regulator = devm_regulator_get_optional(dev, "phy");
0163 if (IS_ERR(priv->regulator)) {
0164 if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) {
0165 err = -EPROBE_DEFER;
0166 goto out_clk_disable;
0167 }
0168 dev_err(dev, "no regulator found\n");
0169 priv->regulator = NULL;
0170 }
0171
0172 if (priv->regulator) {
0173 err = regulator_enable(priv->regulator);
0174 if (err) {
0175 dev_err(dev, "failed to enable phy-supply (%d)\n", err);
0176 goto out_clk_disable;
0177 }
0178 }
0179
0180
0181 data = (1 << (priv->soc_data->grf_speed_offset + 16)) |
0182 (1 << priv->soc_data->grf_speed_offset);
0183
0184 data |= (1 << (priv->soc_data->grf_mode_offset + 16)) |
0185 (0 << priv->soc_data->grf_mode_offset);
0186
0187 err = regmap_write(priv->grf, priv->soc_data->grf_offset, data);
0188 if (err) {
0189 dev_err(dev, "unable to apply initial settings to grf (%d)\n",
0190 err);
0191 goto out_regulator_disable;
0192 }
0193
0194
0195 err = clk_set_rate(priv->refclk, 50000000);
0196 if (err) {
0197 dev_err(dev,
0198 "failed to change reference clock rate (%d)\n", err);
0199 goto out_regulator_disable;
0200 }
0201
0202 if (priv->soc_data->need_div_macclk) {
0203 priv->macclk = devm_clk_get(dev, "macclk");
0204 if (IS_ERR(priv->macclk)) {
0205 dev_err(dev, "failed to retrieve mac clock (%ld)\n",
0206 PTR_ERR(priv->macclk));
0207 err = PTR_ERR(priv->macclk);
0208 goto out_regulator_disable;
0209 }
0210
0211 err = clk_prepare_enable(priv->macclk);
0212 if (err) {
0213 dev_err(dev, "failed to enable mac clock (%d)\n", err);
0214 goto out_regulator_disable;
0215 }
0216
0217
0218 err = clk_set_rate(priv->macclk, 25000000);
0219 if (err) {
0220 dev_err(dev,
0221 "failed to change mac clock rate (%d)\n", err);
0222 goto out_clk_disable_macclk;
0223 }
0224 }
0225
0226 err = arc_emac_probe(ndev, interface);
0227 if (err) {
0228 dev_err(dev, "failed to probe arc emac (%d)\n", err);
0229 goto out_clk_disable_macclk;
0230 }
0231
0232 return 0;
0233
0234 out_clk_disable_macclk:
0235 if (priv->soc_data->need_div_macclk)
0236 clk_disable_unprepare(priv->macclk);
0237 out_regulator_disable:
0238 if (priv->regulator)
0239 regulator_disable(priv->regulator);
0240 out_clk_disable:
0241 clk_disable_unprepare(priv->refclk);
0242 out_netdev:
0243 free_netdev(ndev);
0244 return err;
0245 }
0246
0247 static int emac_rockchip_remove(struct platform_device *pdev)
0248 {
0249 struct net_device *ndev = platform_get_drvdata(pdev);
0250 struct rockchip_priv_data *priv = netdev_priv(ndev);
0251 int err;
0252
0253 err = arc_emac_remove(ndev);
0254
0255 clk_disable_unprepare(priv->refclk);
0256
0257 if (priv->regulator)
0258 regulator_disable(priv->regulator);
0259
0260 if (priv->soc_data->need_div_macclk)
0261 clk_disable_unprepare(priv->macclk);
0262
0263 free_netdev(ndev);
0264 return err;
0265 }
0266
0267 static struct platform_driver emac_rockchip_driver = {
0268 .probe = emac_rockchip_probe,
0269 .remove = emac_rockchip_remove,
0270 .driver = {
0271 .name = DRV_NAME,
0272 .of_match_table = emac_rockchip_dt_ids,
0273 },
0274 };
0275
0276 module_platform_driver(emac_rockchip_driver);
0277
0278 MODULE_AUTHOR("Romain Perier <romain.perier@gmail.com>");
0279 MODULE_DESCRIPTION("Rockchip EMAC platform driver");
0280 MODULE_LICENSE("GPL");