2 * emac-rockchip.c - Rockchip EMAC specific glue layer
4 * Copyright (C) 2014 Romain Perier <romain.perier@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/etherdevice.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/module.h>
20 #include <linux/of_net.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
23 #include <linux/regulator/consumer.h>
27 #define DRV_NAME "rockchip_emac"
28 #define DRV_VERSION "1.1"
30 struct emac_rockchip_soc_data
{
31 unsigned int grf_offset
;
32 unsigned int grf_mode_offset
;
33 unsigned int grf_speed_offset
;
37 struct rockchip_priv_data
{
38 struct arc_emac_priv emac
;
40 const struct emac_rockchip_soc_data
*soc_data
;
41 struct regulator
*regulator
;
46 static void emac_rockchip_set_mac_speed(void *priv
, unsigned int speed
)
48 struct rockchip_priv_data
*emac
= priv
;
49 u32 speed_offset
= emac
->soc_data
->grf_speed_offset
;
55 data
= (1 << (speed_offset
+ 16)) | (0 << speed_offset
);
58 data
= (1 << (speed_offset
+ 16)) | (1 << speed_offset
);
61 pr_err("speed %u not supported\n", speed
);
65 err
= regmap_write(emac
->grf
, emac
->soc_data
->grf_offset
, data
);
67 pr_err("unable to apply speed %u to grf (%d)\n", speed
, err
);
70 static const struct emac_rockchip_soc_data emac_rk3036_emac_data
= {
71 .grf_offset
= 0x140, .grf_mode_offset
= 8,
72 .grf_speed_offset
= 9, .need_div_macclk
= 1,
75 static const struct emac_rockchip_soc_data emac_rk3066_emac_data
= {
76 .grf_offset
= 0x154, .grf_mode_offset
= 0,
77 .grf_speed_offset
= 1, .need_div_macclk
= 0,
80 static const struct emac_rockchip_soc_data emac_rk3188_emac_data
= {
81 .grf_offset
= 0x0a4, .grf_mode_offset
= 0,
82 .grf_speed_offset
= 1, .need_div_macclk
= 0,
85 static const struct of_device_id emac_rockchip_dt_ids
[] = {
87 .compatible
= "rockchip,rk3036-emac",
88 .data
= &emac_rk3036_emac_data
,
91 .compatible
= "rockchip,rk3066-emac",
92 .data
= &emac_rk3066_emac_data
,
95 .compatible
= "rockchip,rk3188-emac",
96 .data
= &emac_rk3188_emac_data
,
101 MODULE_DEVICE_TABLE(of
, emac_rockchip_dt_ids
);
103 static int emac_rockchip_probe(struct platform_device
*pdev
)
105 struct device
*dev
= &pdev
->dev
;
106 struct net_device
*ndev
;
107 struct rockchip_priv_data
*priv
;
108 const struct of_device_id
*match
;
112 if (!pdev
->dev
.of_node
)
115 ndev
= alloc_etherdev(sizeof(struct rockchip_priv_data
));
118 platform_set_drvdata(pdev
, ndev
);
119 SET_NETDEV_DEV(ndev
, dev
);
121 priv
= netdev_priv(ndev
);
122 priv
->emac
.drv_name
= DRV_NAME
;
123 priv
->emac
.drv_version
= DRV_VERSION
;
124 priv
->emac
.set_mac_speed
= emac_rockchip_set_mac_speed
;
126 interface
= of_get_phy_mode(dev
->of_node
);
128 /* RK3036/RK3066/RK3188 SoCs only support RMII */
129 if (interface
!= PHY_INTERFACE_MODE_RMII
) {
130 dev_err(dev
, "unsupported phy interface mode %d\n", interface
);
135 priv
->grf
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
137 if (IS_ERR(priv
->grf
)) {
138 dev_err(dev
, "failed to retrieve global register file (%ld)\n",
140 err
= PTR_ERR(priv
->grf
);
144 match
= of_match_node(emac_rockchip_dt_ids
, dev
->of_node
);
145 priv
->soc_data
= match
->data
;
147 priv
->emac
.clk
= devm_clk_get(dev
, "hclk");
148 if (IS_ERR(priv
->emac
.clk
)) {
149 dev_err(dev
, "failed to retrieve host clock (%ld)\n",
150 PTR_ERR(priv
->emac
.clk
));
151 err
= PTR_ERR(priv
->emac
.clk
);
155 priv
->refclk
= devm_clk_get(dev
, "macref");
156 if (IS_ERR(priv
->refclk
)) {
157 dev_err(dev
, "failed to retrieve reference clock (%ld)\n",
158 PTR_ERR(priv
->refclk
));
159 err
= PTR_ERR(priv
->refclk
);
163 err
= clk_prepare_enable(priv
->refclk
);
165 dev_err(dev
, "failed to enable reference clock (%d)\n", err
);
169 /* Optional regulator for PHY */
170 priv
->regulator
= devm_regulator_get_optional(dev
, "phy");
171 if (IS_ERR(priv
->regulator
)) {
172 if (PTR_ERR(priv
->regulator
) == -EPROBE_DEFER
)
173 return -EPROBE_DEFER
;
174 dev_err(dev
, "no regulator found\n");
175 priv
->regulator
= NULL
;
178 if (priv
->regulator
) {
179 err
= regulator_enable(priv
->regulator
);
181 dev_err(dev
, "failed to enable phy-supply (%d)\n", err
);
182 goto out_clk_disable
;
187 data
= (1 << (priv
->soc_data
->grf_speed_offset
+ 16)) |
188 (1 << priv
->soc_data
->grf_speed_offset
);
190 data
|= (1 << (priv
->soc_data
->grf_mode_offset
+ 16)) |
191 (0 << priv
->soc_data
->grf_mode_offset
);
193 err
= regmap_write(priv
->grf
, priv
->soc_data
->grf_offset
, data
);
195 dev_err(dev
, "unable to apply initial settings to grf (%d)\n",
197 goto out_regulator_disable
;
200 /* RMII interface needs always a rate of 50MHz */
201 err
= clk_set_rate(priv
->refclk
, 50000000);
204 "failed to change reference clock rate (%d)\n", err
);
206 if (priv
->soc_data
->need_div_macclk
) {
207 priv
->macclk
= devm_clk_get(dev
, "macclk");
208 if (IS_ERR(priv
->macclk
)) {
209 dev_err(dev
, "failed to retrieve mac clock (%ld)\n",
210 PTR_ERR(priv
->macclk
));
211 err
= PTR_ERR(priv
->macclk
);
212 goto out_regulator_disable
;
215 err
= clk_prepare_enable(priv
->macclk
);
217 dev_err(dev
, "failed to enable mac clock (%d)\n", err
);
218 goto out_regulator_disable
;
221 /* RMII TX/RX needs always a rate of 25MHz */
222 err
= clk_set_rate(priv
->macclk
, 25000000);
225 "failed to change mac clock rate (%d)\n", err
);
228 err
= arc_emac_probe(ndev
, interface
);
230 dev_err(dev
, "failed to probe arc emac (%d)\n", err
);
231 goto out_regulator_disable
;
236 out_regulator_disable
:
238 regulator_disable(priv
->regulator
);
240 clk_disable_unprepare(priv
->refclk
);
246 static int emac_rockchip_remove(struct platform_device
*pdev
)
248 struct net_device
*ndev
= platform_get_drvdata(pdev
);
249 struct rockchip_priv_data
*priv
= netdev_priv(ndev
);
252 err
= arc_emac_remove(ndev
);
254 clk_disable_unprepare(priv
->refclk
);
257 regulator_disable(priv
->regulator
);
263 static struct platform_driver emac_rockchip_driver
= {
264 .probe
= emac_rockchip_probe
,
265 .remove
= emac_rockchip_remove
,
268 .of_match_table
= emac_rockchip_dt_ids
,
272 module_platform_driver(emac_rockchip_driver
);
274 MODULE_AUTHOR("Romain Perier <romain.perier@gmail.com>");
275 MODULE_DESCRIPTION("Rockchip EMAC platform driver");
276 MODULE_LICENSE("GPL");