OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | /* This program is free software; you can redistribute it and/or modify |
2 | * it under the terms of the GNU General Public License as published by |
||
3 | * the Free Software Foundation; version 2 of the License |
||
4 | * |
||
5 | * This program is distributed in the hope that it will be useful, |
||
6 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
7 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
8 | * GNU General Public License for more details. |
||
9 | * |
||
10 | * Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> |
||
11 | * Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> |
||
12 | * Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> |
||
13 | */ |
||
14 | |||
15 | #include <linux/module.h> |
||
16 | #include <linux/platform_device.h> |
||
17 | #include <linux/if_vlan.h> |
||
18 | #include <linux/of_net.h> |
||
19 | |||
20 | #include <asm/mach-ralink/ralink_regs.h> |
||
21 | |||
22 | #include <mt7620.h> |
||
23 | #include "mtk_eth_soc.h" |
||
24 | #include "gsw_mt7620.h" |
||
25 | #include "mt7530.h" |
||
26 | #include "mdio.h" |
||
27 | |||
28 | #define MT7620A_CDMA_CSG_CFG 0x400 |
||
29 | #define MT7620_DMA_VID (MT7620A_CDMA_CSG_CFG | 0x30) |
||
30 | #define MT7621_CDMP_IG_CTRL (MT7620A_CDMA_CSG_CFG + 0x00) |
||
31 | #define MT7621_CDMP_EG_CTRL (MT7620A_CDMA_CSG_CFG + 0x04) |
||
32 | #define MT7620A_RESET_FE BIT(21) |
||
33 | #define MT7621_RESET_FE BIT(6) |
||
34 | #define MT7620A_RESET_ESW BIT(23) |
||
35 | #define MT7620_L4_VALID BIT(23) |
||
36 | #define MT7621_L4_VALID BIT(24) |
||
37 | |||
38 | #define MT7620_TX_DMA_UDF BIT(15) |
||
39 | #define MT7621_TX_DMA_UDF BIT(19) |
||
40 | #define TX_DMA_FP_BMAP ((0xff) << 19) |
||
41 | |||
42 | #define CDMA_ICS_EN BIT(2) |
||
43 | #define CDMA_UCS_EN BIT(1) |
||
44 | #define CDMA_TCS_EN BIT(0) |
||
45 | |||
46 | #define GDMA_ICS_EN BIT(22) |
||
47 | #define GDMA_TCS_EN BIT(21) |
||
48 | #define GDMA_UCS_EN BIT(20) |
||
49 | |||
50 | /* frame engine counters */ |
||
51 | #define MT7620_REG_MIB_OFFSET 0x1000 |
||
52 | #define MT7620_PPE_AC_BCNT0 (MT7620_REG_MIB_OFFSET + 0x00) |
||
53 | #define MT7620_GDM1_TX_GBCNT (MT7620_REG_MIB_OFFSET + 0x300) |
||
54 | #define MT7620_GDM2_TX_GBCNT (MT7620_GDM1_TX_GBCNT + 0x40) |
||
55 | |||
56 | #define MT7621_REG_MIB_OFFSET 0x2000 |
||
57 | #define MT7621_PPE_AC_BCNT0 (MT7621_REG_MIB_OFFSET + 0x00) |
||
58 | #define MT7621_GDM1_TX_GBCNT (MT7621_REG_MIB_OFFSET + 0x400) |
||
59 | #define MT7621_GDM2_TX_GBCNT (MT7621_GDM1_TX_GBCNT + 0x40) |
||
60 | |||
61 | #define GSW_REG_GDMA1_MAC_ADRL 0x508 |
||
62 | #define GSW_REG_GDMA1_MAC_ADRH 0x50C |
||
63 | |||
64 | #define MT7621_FE_RST_GL (FE_FE_OFFSET + 0x04) |
||
65 | #define MT7620_FE_INT_STATUS2 (FE_FE_OFFSET + 0x08) |
||
66 | |||
67 | /* FE_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29) |
||
68 | * but after test it should be BIT(13). |
||
69 | */ |
||
70 | #define MT7620_FE_GDM1_AF BIT(13) |
||
71 | #define MT7621_FE_GDM1_AF BIT(28) |
||
72 | #define MT7621_FE_GDM2_AF BIT(29) |
||
73 | |||
74 | static const u16 mt7620_reg_table[FE_REG_COUNT] = { |
||
75 | [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, |
||
76 | [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, |
||
77 | [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, |
||
78 | [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, |
||
79 | [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, |
||
80 | [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, |
||
81 | [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, |
||
82 | [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, |
||
83 | [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, |
||
84 | [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, |
||
85 | [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, |
||
86 | [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, |
||
87 | [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, |
||
88 | [FE_REG_FE_DMA_VID_BASE] = MT7620_DMA_VID, |
||
89 | [FE_REG_FE_COUNTER_BASE] = MT7620_GDM1_TX_GBCNT, |
||
90 | [FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, |
||
91 | [FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, |
||
92 | }; |
||
93 | |||
94 | static int mt7620_gsw_config(struct fe_priv *priv) |
||
95 | { |
||
96 | struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; |
||
97 | |||
98 | /* is the mt7530 internal or external */ |
||
99 | if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, 0x1f)) { |
||
100 | mt7530_probe(priv->dev, gsw->base, NULL, 0); |
||
101 | mt7530_probe(priv->dev, NULL, priv->mii_bus, 1); |
||
102 | } else { |
||
103 | mt7530_probe(priv->dev, gsw->base, NULL, 1); |
||
104 | } |
||
105 | |||
106 | return 0; |
||
107 | } |
||
108 | |||
109 | static void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac) |
||
110 | { |
||
111 | struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; |
||
112 | unsigned long flags; |
||
113 | |||
114 | spin_lock_irqsave(&priv->page_lock, flags); |
||
115 | mtk_switch_w32(gsw, (mac[0] << 8) | mac[1], GSW_REG_SMACCR1); |
||
116 | mtk_switch_w32(gsw, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], |
||
117 | GSW_REG_SMACCR0); |
||
118 | spin_unlock_irqrestore(&priv->page_lock, flags); |
||
119 | } |
||
120 | |||
121 | static void mt7620_auto_poll(struct mt7620_gsw *gsw) |
||
122 | { |
||
123 | int phy; |
||
124 | int lsb = -1, msb = 0; |
||
125 | |||
126 | for_each_set_bit(phy, &gsw->autopoll, 32) { |
||
127 | if (lsb < 0) |
||
128 | lsb = phy; |
||
129 | msb = phy; |
||
130 | } |
||
131 | |||
132 | if (lsb == msb) |
||
133 | lsb--; |
||
134 | |||
135 | mtk_switch_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | |
||
136 | (msb << 8) | lsb, ESW_PHY_POLLING); |
||
137 | } |
||
138 | |||
139 | static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) |
||
140 | { |
||
141 | struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; |
||
142 | const __be32 *_id = of_get_property(np, "reg", NULL); |
||
143 | int phy_mode, size, id; |
||
144 | int shift = 12; |
||
145 | u32 val, mask = 0; |
||
146 | int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4); |
||
147 | |||
148 | if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) { |
||
149 | if (_id) |
||
150 | pr_err("%s: invalid port id %d\n", np->name, |
||
151 | be32_to_cpu(*_id)); |
||
152 | else |
||
153 | pr_err("%s: invalid port id\n", np->name); |
||
154 | return; |
||
155 | } |
||
156 | |||
157 | id = be32_to_cpu(*_id); |
||
158 | |||
159 | if (id == 4) |
||
160 | shift = 14; |
||
161 | |||
162 | priv->phy->phy_fixed[id] = of_get_property(np, "mediatek,fixed-link", |
||
163 | &size); |
||
164 | if (priv->phy->phy_fixed[id] && |
||
165 | (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) { |
||
166 | pr_err("%s: invalid fixed link property\n", np->name); |
||
167 | priv->phy->phy_fixed[id] = NULL; |
||
168 | return; |
||
169 | } |
||
170 | |||
171 | phy_mode = of_get_phy_mode(np); |
||
172 | switch (phy_mode) { |
||
173 | case PHY_INTERFACE_MODE_RGMII: |
||
174 | mask = 0; |
||
175 | break; |
||
176 | case PHY_INTERFACE_MODE_MII: |
||
177 | mask = 1; |
||
178 | break; |
||
179 | case PHY_INTERFACE_MODE_RMII: |
||
180 | mask = 2; |
||
181 | break; |
||
182 | default: |
||
183 | dev_err(priv->dev, "port %d - invalid phy mode\n", id); |
||
184 | return; |
||
185 | } |
||
186 | |||
187 | priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); |
||
188 | if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id]) |
||
189 | return; |
||
190 | |||
191 | val = rt_sysc_r32(SYSC_REG_CFG1); |
||
192 | val &= ~(3 << shift); |
||
193 | val |= mask << shift; |
||
194 | rt_sysc_w32(val, SYSC_REG_CFG1); |
||
195 | |||
196 | if (priv->phy->phy_fixed[id]) { |
||
197 | const __be32 *link = priv->phy->phy_fixed[id]; |
||
198 | int tx_fc, rx_fc; |
||
199 | u32 val = 0; |
||
200 | |||
201 | priv->phy->speed[id] = be32_to_cpup(link++); |
||
202 | tx_fc = be32_to_cpup(link++); |
||
203 | rx_fc = be32_to_cpup(link++); |
||
204 | priv->phy->duplex[id] = be32_to_cpup(link++); |
||
205 | priv->link[id] = 1; |
||
206 | |||
207 | switch (priv->phy->speed[id]) { |
||
208 | case SPEED_10: |
||
209 | val = 0; |
||
210 | break; |
||
211 | case SPEED_100: |
||
212 | val = 1; |
||
213 | break; |
||
214 | case SPEED_1000: |
||
215 | val = 2; |
||
216 | break; |
||
217 | default: |
||
218 | dev_err(priv->dev, "invalid link speed: %d\n", |
||
219 | priv->phy->speed[id]); |
||
220 | priv->phy->phy_fixed[id] = 0; |
||
221 | return; |
||
222 | } |
||
223 | val = PMCR_SPEED(val); |
||
224 | val |= PMCR_LINK | PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | |
||
225 | PMCR_TX_EN | PMCR_FORCE | PMCR_MAC_MODE | PMCR_IPG; |
||
226 | if (tx_fc) |
||
227 | val |= PMCR_TX_FC; |
||
228 | if (rx_fc) |
||
229 | val |= PMCR_RX_FC; |
||
230 | if (priv->phy->duplex[id]) |
||
231 | val |= PMCR_DUPLEX; |
||
232 | mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); |
||
233 | dev_info(priv->dev, "using fixed link parameters\n"); |
||
234 | return; |
||
235 | } |
||
236 | |||
237 | if (priv->phy->phy_node[id] && mdiobus_get_phy(priv->mii_bus, id)) { |
||
238 | u32 val = PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | |
||
239 | PMCR_TX_EN | PMCR_MAC_MODE | PMCR_IPG; |
||
240 | |||
241 | mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); |
||
242 | fe_connect_phy_node(priv, priv->phy->phy_node[id]); |
||
243 | gsw->autopoll |= BIT(id); |
||
244 | mt7620_auto_poll(gsw); |
||
245 | return; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | static void mt7620_fe_reset(void) |
||
250 | { |
||
251 | fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); |
||
252 | } |
||
253 | |||
254 | static void mt7620_rxcsum_config(bool enable) |
||
255 | { |
||
256 | if (enable) |
||
257 | fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | |
||
258 | GDMA_TCS_EN | GDMA_UCS_EN), |
||
259 | MT7620A_GDMA1_FWD_CFG); |
||
260 | else |
||
261 | fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~(GDMA_ICS_EN | |
||
262 | GDMA_TCS_EN | GDMA_UCS_EN), |
||
263 | MT7620A_GDMA1_FWD_CFG); |
||
264 | } |
||
265 | |||
266 | static void mt7620_txcsum_config(bool enable) |
||
267 | { |
||
268 | if (enable) |
||
269 | fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) | (CDMA_ICS_EN | |
||
270 | CDMA_UCS_EN | CDMA_TCS_EN), |
||
271 | MT7620A_CDMA_CSG_CFG); |
||
272 | else |
||
273 | fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) & ~(CDMA_ICS_EN | |
||
274 | CDMA_UCS_EN | CDMA_TCS_EN), |
||
275 | MT7620A_CDMA_CSG_CFG); |
||
276 | } |
||
277 | |||
278 | static int mt7620_fwd_config(struct fe_priv *priv) |
||
279 | { |
||
280 | struct net_device *dev = priv_netdev(priv); |
||
281 | |||
282 | fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~7, MT7620A_GDMA1_FWD_CFG); |
||
283 | |||
284 | mt7620_txcsum_config((dev->features & NETIF_F_IP_CSUM)); |
||
285 | mt7620_rxcsum_config((dev->features & NETIF_F_RXCSUM)); |
||
286 | |||
287 | return 0; |
||
288 | } |
||
289 | |||
290 | static void mt7620_tx_dma(struct fe_tx_dma *txd) |
||
291 | { |
||
292 | } |
||
293 | |||
294 | static void mt7620_init_data(struct fe_soc_data *data, |
||
295 | struct net_device *netdev) |
||
296 | { |
||
297 | struct fe_priv *priv = netdev_priv(netdev); |
||
298 | |||
299 | priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | |
||
300 | FE_FLAG_RX_SG_DMA | FE_FLAG_HAS_SWITCH; |
||
301 | |||
302 | netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | |
||
303 | NETIF_F_HW_VLAN_CTAG_TX; |
||
304 | if (mt7620_get_eco() >= 5) |
||
305 | netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | |
||
306 | NETIF_F_IPV6_CSUM; |
||
307 | } |
||
308 | |||
309 | static struct fe_soc_data mt7620_data = { |
||
310 | .init_data = mt7620_init_data, |
||
311 | .reset_fe = mt7620_fe_reset, |
||
312 | .set_mac = mt7620_set_mac, |
||
313 | .fwd_config = mt7620_fwd_config, |
||
314 | .tx_dma = mt7620_tx_dma, |
||
315 | .switch_init = mtk_gsw_init, |
||
316 | .switch_config = mt7620_gsw_config, |
||
317 | .port_init = mt7620_port_init, |
||
318 | .reg_table = mt7620_reg_table, |
||
319 | .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, |
||
320 | .rx_int = RT5350_RX_DONE_INT, |
||
321 | .tx_int = RT5350_TX_DONE_INT, |
||
322 | .status_int = MT7620_FE_GDM1_AF, |
||
323 | .checksum_bit = MT7620_L4_VALID, |
||
324 | .has_carrier = mt7620_has_carrier, |
||
325 | .mdio_read = mt7620_mdio_read, |
||
326 | .mdio_write = mt7620_mdio_write, |
||
327 | .mdio_adjust_link = mt7620_mdio_link_adjust, |
||
328 | }; |
||
329 | |||
330 | const struct of_device_id of_fe_match[] = { |
||
331 | { .compatible = "mediatek,mt7620-eth", .data = &mt7620_data }, |
||
332 | {}, |
||
333 | }; |
||
334 | |||
335 | MODULE_DEVICE_TABLE(of, of_fe_match); |