18
18
#include <linux/io.h>
19
19
#include <linux/ioport.h>
20
20
#include <linux/module.h>
21
+ #include <linux/of_device.h>
21
22
#include <linux/of_net.h>
22
23
#include <linux/mfd/syscon.h>
23
24
#include <linux/platform_device.h>
29
30
30
31
#define PRG_ETH0_RGMII_MODE BIT(0)
31
32
33
+ #define PRG_ETH0_EXT_PHY_MODE_MASK GENMASK(2, 0)
34
+ #define PRG_ETH0_EXT_RGMII_MODE 1
35
+ #define PRG_ETH0_EXT_RMII_MODE 4
36
+
32
37
/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
33
38
#define PRG_ETH0_CLK_M250_SEL_SHIFT 4
34
39
#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)
47
52
48
53
#define MUX_CLK_NUM_PARENTS 2
49
54
55
+ struct meson8b_dwmac ;
56
+
57
+ struct meson8b_dwmac_data {
58
+ int (* set_phy_mode )(struct meson8b_dwmac * dwmac );
59
+ };
60
+
50
61
struct meson8b_dwmac {
51
- struct device * dev ;
52
- void __iomem * regs ;
53
- phy_interface_t phy_mode ;
54
- struct clk * rgmii_tx_clk ;
55
- u32 tx_delay_ns ;
62
+ struct device * dev ;
63
+ void __iomem * regs ;
64
+
65
+ const struct meson8b_dwmac_data * data ;
66
+ phy_interface_t phy_mode ;
67
+ struct clk * rgmii_tx_clk ;
68
+ u32 tx_delay_ns ;
56
69
};
57
70
58
71
struct meson8b_dwmac_clk_configs {
@@ -171,6 +184,59 @@ static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
171
184
return 0 ;
172
185
}
173
186
187
+ static int meson8b_set_phy_mode (struct meson8b_dwmac * dwmac )
188
+ {
189
+ switch (dwmac -> phy_mode ) {
190
+ case PHY_INTERFACE_MODE_RGMII :
191
+ case PHY_INTERFACE_MODE_RGMII_RXID :
192
+ case PHY_INTERFACE_MODE_RGMII_ID :
193
+ case PHY_INTERFACE_MODE_RGMII_TXID :
194
+ /* enable RGMII mode */
195
+ meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 ,
196
+ PRG_ETH0_RGMII_MODE ,
197
+ PRG_ETH0_RGMII_MODE );
198
+ break ;
199
+ case PHY_INTERFACE_MODE_RMII :
200
+ /* disable RGMII mode -> enables RMII mode */
201
+ meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 ,
202
+ PRG_ETH0_RGMII_MODE , 0 );
203
+ break ;
204
+ default :
205
+ dev_err (dwmac -> dev , "fail to set phy-mode %s\n" ,
206
+ phy_modes (dwmac -> phy_mode ));
207
+ return - EINVAL ;
208
+ }
209
+
210
+ return 0 ;
211
+ }
212
+
213
+ static int meson_axg_set_phy_mode (struct meson8b_dwmac * dwmac )
214
+ {
215
+ switch (dwmac -> phy_mode ) {
216
+ case PHY_INTERFACE_MODE_RGMII :
217
+ case PHY_INTERFACE_MODE_RGMII_RXID :
218
+ case PHY_INTERFACE_MODE_RGMII_ID :
219
+ case PHY_INTERFACE_MODE_RGMII_TXID :
220
+ /* enable RGMII mode */
221
+ meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 ,
222
+ PRG_ETH0_EXT_PHY_MODE_MASK ,
223
+ PRG_ETH0_EXT_RGMII_MODE );
224
+ break ;
225
+ case PHY_INTERFACE_MODE_RMII :
226
+ /* disable RGMII mode -> enables RMII mode */
227
+ meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 ,
228
+ PRG_ETH0_EXT_PHY_MODE_MASK ,
229
+ PRG_ETH0_EXT_RMII_MODE );
230
+ break ;
231
+ default :
232
+ dev_err (dwmac -> dev , "fail to set phy-mode %s\n" ,
233
+ phy_modes (dwmac -> phy_mode ));
234
+ return - EINVAL ;
235
+ }
236
+
237
+ return 0 ;
238
+ }
239
+
174
240
static int meson8b_init_prg_eth (struct meson8b_dwmac * dwmac )
175
241
{
176
242
int ret ;
@@ -188,10 +254,6 @@ static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
188
254
189
255
case PHY_INTERFACE_MODE_RGMII_ID :
190
256
case PHY_INTERFACE_MODE_RGMII_TXID :
191
- /* enable RGMII mode */
192
- meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 , PRG_ETH0_RGMII_MODE ,
193
- PRG_ETH0_RGMII_MODE );
194
-
195
257
/* only relevant for RMII mode -> disable in RGMII mode */
196
258
meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 ,
197
259
PRG_ETH0_INVERTED_RMII_CLK , 0 );
@@ -224,10 +286,6 @@ static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
224
286
break ;
225
287
226
288
case PHY_INTERFACE_MODE_RMII :
227
- /* disable RGMII mode -> enables RMII mode */
228
- meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 , PRG_ETH0_RGMII_MODE ,
229
- 0 );
230
-
231
289
/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
232
290
meson8b_dwmac_mask_bits (dwmac , PRG_ETH0 ,
233
291
PRG_ETH0_INVERTED_RMII_CLK ,
@@ -274,6 +332,11 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
274
332
goto err_remove_config_dt ;
275
333
}
276
334
335
+ dwmac -> data = (const struct meson8b_dwmac_data * )
336
+ of_device_get_match_data (& pdev -> dev );
337
+ if (!dwmac -> data )
338
+ return - EINVAL ;
339
+
277
340
res = platform_get_resource (pdev , IORESOURCE_MEM , 1 );
278
341
dwmac -> regs = devm_ioremap_resource (& pdev -> dev , res );
279
342
if (IS_ERR (dwmac -> regs )) {
@@ -298,6 +361,10 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
298
361
if (ret )
299
362
goto err_remove_config_dt ;
300
363
364
+ ret = dwmac -> data -> set_phy_mode (dwmac );
365
+ if (ret )
366
+ goto err_remove_config_dt ;
367
+
301
368
ret = meson8b_init_prg_eth (dwmac );
302
369
if (ret )
303
370
goto err_remove_config_dt ;
@@ -316,10 +383,31 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
316
383
return ret ;
317
384
}
318
385
386
+ static const struct meson8b_dwmac_data meson8b_dwmac_data = {
387
+ .set_phy_mode = meson8b_set_phy_mode ,
388
+ };
389
+
390
+ static const struct meson8b_dwmac_data meson_axg_dwmac_data = {
391
+ .set_phy_mode = meson_axg_set_phy_mode ,
392
+ };
393
+
319
394
static const struct of_device_id meson8b_dwmac_match [] = {
320
- { .compatible = "amlogic,meson8b-dwmac" },
321
- { .compatible = "amlogic,meson8m2-dwmac" },
322
- { .compatible = "amlogic,meson-gxbb-dwmac" },
395
+ {
396
+ .compatible = "amlogic,meson8b-dwmac" ,
397
+ .data = & meson8b_dwmac_data ,
398
+ },
399
+ {
400
+ .compatible = "amlogic,meson8m2-dwmac" ,
401
+ .data = & meson8b_dwmac_data ,
402
+ },
403
+ {
404
+ .compatible = "amlogic,meson-gxbb-dwmac" ,
405
+ .data = & meson8b_dwmac_data ,
406
+ },
407
+ {
408
+ .compatible = "amlogic,meson-axg-dwmac" ,
409
+ .data = & meson_axg_dwmac_data ,
410
+ },
323
411
{ }
324
412
};
325
413
MODULE_DEVICE_TABLE (of , meson8b_dwmac_match );
0 commit comments