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