]>
Commit | Line | Data |
---|---|---|
798424e8 NA |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2021 BayLibre, SAS | |
4 | */ | |
5 | ||
798424e8 NA |
6 | #include <asm/io.h> |
7 | #include <dm.h> | |
8 | #include <phy.h> | |
9 | #include "designware.h" | |
10 | #include <dm/device_compat.h> | |
11 | #include <linux/err.h> | |
12 | ||
13 | #define ETH_REG_0 0x0 | |
14 | #define ETH_REG_1 0x4 | |
15 | #define ETH_REG_2 0x18 | |
16 | #define ETH_REG_3 0x1c | |
17 | ||
18 | #define GX_ETH_REG_0_PHY_INTF BIT(0) | |
19 | #define GX_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5) | |
20 | #define GX_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7) | |
21 | #define GX_ETH_REG_0_PHY_CLK_EN BIT(10) | |
22 | #define GX_ETH_REG_0_INVERT_RMII_CLK BIT(11) | |
23 | #define GX_ETH_REG_0_CLK_EN BIT(12) | |
24 | ||
25 | #define AXG_ETH_REG_0_PHY_INTF_RGMII BIT(0) | |
26 | #define AXG_ETH_REG_0_PHY_INTF_RMII BIT(2) | |
27 | #define AXG_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5) | |
28 | #define AXG_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7) | |
29 | #define AXG_ETH_REG_0_PHY_CLK_EN BIT(10) | |
30 | #define AXG_ETH_REG_0_INVERT_RMII_CLK BIT(11) | |
31 | #define AXG_ETH_REG_0_CLK_EN BIT(12) | |
32 | ||
33 | struct dwmac_meson8b_plat { | |
34 | struct dw_eth_pdata dw_eth_pdata; | |
35 | int (*dwmac_setup)(struct udevice *dev, struct eth_pdata *edata); | |
36 | void *regs; | |
37 | }; | |
38 | ||
39 | static int dwmac_meson8b_of_to_plat(struct udevice *dev) | |
40 | { | |
41 | struct dwmac_meson8b_plat *pdata = dev_get_plat(dev); | |
42 | ||
e5822ecb JJ |
43 | pdata->regs = dev_read_addr_index_ptr(dev, 1); |
44 | if (!pdata->regs) | |
798424e8 NA |
45 | return -EINVAL; |
46 | ||
47 | pdata->dwmac_setup = (void *)dev_get_driver_data(dev); | |
48 | if (!pdata->dwmac_setup) | |
49 | return -EINVAL; | |
50 | ||
51 | return designware_eth_of_to_plat(dev); | |
52 | } | |
53 | ||
54 | static int dwmac_setup_axg(struct udevice *dev, struct eth_pdata *edata) | |
55 | { | |
56 | struct dwmac_meson8b_plat *plat = dev_get_plat(dev); | |
57 | ||
58 | switch (edata->phy_interface) { | |
59 | case PHY_INTERFACE_MODE_RGMII: | |
60 | case PHY_INTERFACE_MODE_RGMII_ID: | |
798424e8 NA |
61 | /* Set RGMII mode */ |
62 | setbits_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII | | |
63 | AXG_ETH_REG_0_TX_PHASE(1) | | |
64 | AXG_ETH_REG_0_TX_RATIO(4) | | |
65 | AXG_ETH_REG_0_PHY_CLK_EN | | |
66 | AXG_ETH_REG_0_CLK_EN); | |
67 | break; | |
68 | ||
81d0edaf NA |
69 | case PHY_INTERFACE_MODE_RGMII_RXID: |
70 | case PHY_INTERFACE_MODE_RGMII_TXID: | |
71 | /* TOFIX: handle amlogic,tx-delay-ns & rx-internal-delay-ps from DT */ | |
72 | setbits_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII | | |
73 | AXG_ETH_REG_0_TX_RATIO(4) | | |
74 | AXG_ETH_REG_0_PHY_CLK_EN | | |
75 | AXG_ETH_REG_0_CLK_EN); | |
76 | break; | |
77 | ||
798424e8 NA |
78 | case PHY_INTERFACE_MODE_RMII: |
79 | /* Set RMII mode */ | |
80 | out_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RMII | | |
81 | AXG_ETH_REG_0_INVERT_RMII_CLK | | |
82 | AXG_ETH_REG_0_CLK_EN); | |
83 | break; | |
84 | default: | |
85 | dev_err(dev, "Unsupported PHY mode\n"); | |
86 | return -EINVAL; | |
87 | } | |
88 | ||
89 | return 0; | |
90 | } | |
91 | ||
92 | static int dwmac_setup_gx(struct udevice *dev, struct eth_pdata *edata) | |
93 | { | |
94 | struct dwmac_meson8b_plat *plat = dev_get_plat(dev); | |
95 | ||
96 | switch (edata->phy_interface) { | |
97 | case PHY_INTERFACE_MODE_RGMII: | |
98 | case PHY_INTERFACE_MODE_RGMII_ID: | |
798424e8 NA |
99 | /* Set RGMII mode */ |
100 | setbits_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_PHY_INTF | | |
101 | GX_ETH_REG_0_TX_PHASE(1) | | |
102 | GX_ETH_REG_0_TX_RATIO(4) | | |
103 | GX_ETH_REG_0_PHY_CLK_EN | | |
104 | GX_ETH_REG_0_CLK_EN); | |
105 | ||
106 | break; | |
107 | ||
81d0edaf NA |
108 | case PHY_INTERFACE_MODE_RGMII_RXID: |
109 | case PHY_INTERFACE_MODE_RGMII_TXID: | |
110 | /* TOFIX: handle amlogic,tx-delay-ns & rx-internal-delay-ps from DT */ | |
111 | setbits_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_PHY_INTF | | |
112 | GX_ETH_REG_0_TX_RATIO(4) | | |
113 | GX_ETH_REG_0_PHY_CLK_EN | | |
114 | GX_ETH_REG_0_CLK_EN); | |
115 | ||
116 | break; | |
117 | ||
798424e8 NA |
118 | case PHY_INTERFACE_MODE_RMII: |
119 | /* Set RMII mode */ | |
120 | out_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK | | |
121 | GX_ETH_REG_0_CLK_EN); | |
122 | ||
123 | if (!IS_ENABLED(CONFIG_MESON_GXBB)) | |
124 | writel(0x10110181, plat->regs + ETH_REG_2); | |
125 | ||
126 | break; | |
127 | default: | |
128 | dev_err(dev, "Unsupported PHY mode\n"); | |
129 | return -EINVAL; | |
130 | } | |
131 | ||
132 | return 0; | |
133 | } | |
134 | ||
135 | static int dwmac_meson8b_probe(struct udevice *dev) | |
136 | { | |
137 | struct dwmac_meson8b_plat *pdata = dev_get_plat(dev); | |
138 | struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata; | |
139 | int ret; | |
140 | ||
141 | ret = pdata->dwmac_setup(dev, edata); | |
142 | if (ret) | |
143 | return ret; | |
144 | ||
145 | return designware_eth_probe(dev); | |
146 | } | |
147 | ||
148 | static const struct udevice_id dwmac_meson8b_ids[] = { | |
149 | { .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx }, | |
4c2eb955 | 150 | { .compatible = "amlogic,meson-g12a-dwmac", .data = (ulong)dwmac_setup_axg }, |
798424e8 NA |
151 | { .compatible = "amlogic,meson-axg-dwmac", .data = (ulong)dwmac_setup_axg }, |
152 | { } | |
153 | }; | |
154 | ||
155 | U_BOOT_DRIVER(dwmac_meson8b) = { | |
156 | .name = "dwmac_meson8b", | |
157 | .id = UCLASS_ETH, | |
158 | .of_match = dwmac_meson8b_ids, | |
159 | .of_to_plat = dwmac_meson8b_of_to_plat, | |
160 | .probe = dwmac_meson8b_probe, | |
161 | .ops = &designware_eth_ops, | |
162 | .priv_auto = sizeof(struct dw_eth_dev), | |
163 | .plat_auto = sizeof(struct dwmac_meson8b_plat), | |
164 | .flags = DM_FLAG_ALLOC_PRIV_DMA, | |
165 | }; |