ramips: fix subtarget kernel version assignment (only mt7621 is ready for now)
[openwrt.git] / target / linux / ramips / patches-4.3 / 0505-net-next-mediatek-add-support-for-rt2880.patch
1 From f8c8f4bd2a13e0cc060c93812377373d436f7f02 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Wed, 18 Nov 2015 03:13:05 +0100
4 Subject: [PATCH 505/513] net-next: mediatek: add support for rt2880
5
6 rt2880 is the oldest SoC with this core. It has a single gBit port that will
7 normally be attached to an external phy of switch. The patch also adds the
8 code required to drive the mdio bus.
9
10 Signed-off-by: John Crispin <blogic@openwrt.org>
11 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
12 Signed-off-by: Michael Lee <igvtee@gmail.com>
13 ---
14  drivers/net/ethernet/mediatek/mdio_rt2880.c |  222 +++++++++++++++++++++++++++
15  drivers/net/ethernet/mediatek/mdio_rt2880.h |   23 +++
16  drivers/net/ethernet/mediatek/soc_rt2880.c  |   76 +++++++++
17  3 files changed, 321 insertions(+)
18  create mode 100644 drivers/net/ethernet/mediatek/mdio_rt2880.c
19  create mode 100644 drivers/net/ethernet/mediatek/mdio_rt2880.h
20  create mode 100644 drivers/net/ethernet/mediatek/soc_rt2880.c
21
22 --- /dev/null
23 +++ b/drivers/net/ethernet/mediatek/mdio_rt2880.c
24 @@ -0,0 +1,222 @@
25 +/*   This program is free software; you can redistribute it and/or modify
26 + *   it under the terms of the GNU General Public License as published by
27 + *   the Free Software Foundation; version 2 of the License
28 + *
29 + *   This program is distributed in the hope that it will be useful,
30 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
31 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32 + *   GNU General Public License for more details.
33 + *
34 + *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
35 + *   Copyright (C) 2009-2015 Felix Fietkau <nbd@openwrt.org>
36 + *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
37 + */
38 +
39 +#include <linux/module.h>
40 +#include <linux/kernel.h>
41 +#include <linux/types.h>
42 +#include <linux/of_net.h>
43 +#include <linux/of_mdio.h>
44 +
45 +#include "mtk_eth_soc.h"
46 +#include "mdio_rt2880.h"
47 +#include "mdio.h"
48 +
49 +#define FE_MDIO_RETRY  1000
50 +
51 +static unsigned char *rt2880_speed_str(struct fe_priv *priv)
52 +{
53 +       switch (priv->phy->speed[0]) {
54 +       case SPEED_1000:
55 +               return "1000";
56 +       case SPEED_100:
57 +               return "100";
58 +       case SPEED_10:
59 +               return "10";
60 +       }
61 +
62 +       return "?";
63 +}
64 +
65 +void rt2880_mdio_link_adjust(struct fe_priv *priv, int port)
66 +{
67 +       u32 mdio_cfg;
68 +
69 +       if (!priv->link[0]) {
70 +               netif_carrier_off(priv->netdev);
71 +               netdev_info(priv->netdev, "link down\n");
72 +               return;
73 +       }
74 +
75 +       mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 |
76 +                  FE_MDIO_CFG_RX_CLK_SKEW_200 |
77 +                  FE_MDIO_CFG_GP1_FRC_EN;
78 +
79 +       if (priv->phy->duplex[0] == DUPLEX_FULL)
80 +               mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX;
81 +
82 +       if (priv->phy->tx_fc[0])
83 +               mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX;
84 +
85 +       if (priv->phy->rx_fc[0])
86 +               mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX;
87 +
88 +       switch (priv->phy->speed[0]) {
89 +       case SPEED_10:
90 +               mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10;
91 +               break;
92 +       case SPEED_100:
93 +               mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100;
94 +               break;
95 +       case SPEED_1000:
96 +               mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000;
97 +               break;
98 +       default:
99 +               BUG();
100 +       }
101 +
102 +       fe_w32(mdio_cfg, FE_MDIO_CFG);
103 +
104 +       netif_carrier_on(priv->netdev);
105 +       netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n",
106 +                   rt2880_speed_str(priv),
107 +                   (priv->phy->duplex[0] == DUPLEX_FULL) ? "Full" : "Half");
108 +}
109 +
110 +static int rt2880_mdio_wait_ready(struct fe_priv *priv)
111 +{
112 +       int retries;
113 +
114 +       retries = FE_MDIO_RETRY;
115 +       while (1) {
116 +               u32 t;
117 +
118 +               t = fe_r32(FE_MDIO_ACCESS);
119 +               if ((t & BIT(31)) == 0)
120 +                       return 0;
121 +
122 +               if (retries-- == 0)
123 +                       break;
124 +
125 +               udelay(1);
126 +       }
127 +
128 +       dev_err(priv->device, "MDIO operation timed out\n");
129 +       return -ETIMEDOUT;
130 +}
131 +
132 +int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
133 +{
134 +       struct fe_priv *priv = bus->priv;
135 +       int err;
136 +       u32 t;
137 +
138 +       err = rt2880_mdio_wait_ready(priv);
139 +       if (err)
140 +               return 0xffff;
141 +
142 +       t = (phy_addr << 24) | (phy_reg << 16);
143 +       fe_w32(t, FE_MDIO_ACCESS);
144 +       t |= BIT(31);
145 +       fe_w32(t, FE_MDIO_ACCESS);
146 +
147 +       err = rt2880_mdio_wait_ready(priv);
148 +       if (err)
149 +               return 0xffff;
150 +
151 +       pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
152 +                phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff);
153 +
154 +       return fe_r32(FE_MDIO_ACCESS) & 0xffff;
155 +}
156 +
157 +int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
158 +{
159 +       struct fe_priv *priv = bus->priv;
160 +       int err;
161 +       u32 t;
162 +
163 +       pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
164 +                phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff);
165 +
166 +       err = rt2880_mdio_wait_ready(priv);
167 +       if (err)
168 +               return err;
169 +
170 +       t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val;
171 +       fe_w32(t, FE_MDIO_ACCESS);
172 +       t |= BIT(31);
173 +       fe_w32(t, FE_MDIO_ACCESS);
174 +
175 +       return rt2880_mdio_wait_ready(priv);
176 +}
177 +
178 +void rt2880_port_init(struct fe_priv *priv, struct device_node *np)
179 +{
180 +       const __be32 *id = of_get_property(np, "reg", NULL);
181 +       const __be32 *link;
182 +       int size;
183 +       int phy_mode;
184 +
185 +       if (!id || (be32_to_cpu(*id) != 0)) {
186 +               pr_err("%s: invalid port id\n", np->name);
187 +               return;
188 +       }
189 +
190 +       priv->phy->phy_fixed[0] = of_get_property(np,
191 +                                                 "mediatek,fixed-link", &size);
192 +       if (priv->phy->phy_fixed[0] &&
193 +           (size != (4 * sizeof(*priv->phy->phy_fixed[0])))) {
194 +               pr_err("%s: invalid fixed link property\n", np->name);
195 +               priv->phy->phy_fixed[0] = NULL;
196 +               return;
197 +       }
198 +
199 +       phy_mode = of_get_phy_mode(np);
200 +       switch (phy_mode) {
201 +       case PHY_INTERFACE_MODE_RGMII:
202 +               break;
203 +       case PHY_INTERFACE_MODE_MII:
204 +               break;
205 +       case PHY_INTERFACE_MODE_RMII:
206 +               break;
207 +       default:
208 +               if (!priv->phy->phy_fixed[0])
209 +                       dev_err(priv->device, "port %d - invalid phy mode\n",
210 +                               priv->phy->speed[0]);
211 +               break;
212 +       }
213 +
214 +       priv->phy->phy_node[0] = of_parse_phandle(np, "phy-handle", 0);
215 +       if (!priv->phy->phy_node[0] && !priv->phy->phy_fixed[0])
216 +               return;
217 +
218 +       if (priv->phy->phy_fixed[0]) {
219 +               link = priv->phy->phy_fixed[0];
220 +               priv->phy->speed[0] = be32_to_cpup(link++);
221 +               priv->phy->duplex[0] = be32_to_cpup(link++);
222 +               priv->phy->tx_fc[0] = be32_to_cpup(link++);
223 +               priv->phy->rx_fc[0] = be32_to_cpup(link++);
224 +
225 +               priv->link[0] = 1;
226 +               switch (priv->phy->speed[0]) {
227 +               case SPEED_10:
228 +                       break;
229 +               case SPEED_100:
230 +                       break;
231 +               case SPEED_1000:
232 +                       break;
233 +               default:
234 +                       dev_err(priv->device, "invalid link speed: %d\n",
235 +                               priv->phy->speed[0]);
236 +                       priv->phy->phy_fixed[0] = 0;
237 +                       return;
238 +               }
239 +               dev_info(priv->device, "using fixed link parameters\n");
240 +               rt2880_mdio_link_adjust(priv, 0);
241 +               return;
242 +       }
243 +
244 +       if (priv->phy->phy_node[0] && priv->mii_bus->phy_map[0])
245 +               fe_connect_phy_node(priv, priv->phy->phy_node[0]);
246 +}
247 --- /dev/null
248 +++ b/drivers/net/ethernet/mediatek/mdio_rt2880.h
249 @@ -0,0 +1,23 @@
250 +/*   This program is free software; you can redistribute it and/or modify
251 + *   it under the terms of the GNU General Public License as published by
252 + *   the Free Software Foundation; version 2 of the License
253 + *
254 + *   This program is distributed in the hope that it will be useful,
255 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
256 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
257 + *   GNU General Public License for more details.
258 + *
259 + *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
260 + *   Copyright (C) 2009-2015 Felix Fietkau <nbd@openwrt.org>
261 + *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
262 + */
263 +
264 +#ifndef _RALINK_MDIO_RT2880_H__
265 +#define _RALINK_MDIO_RT2880_H__
266 +
267 +void rt2880_mdio_link_adjust(struct fe_priv *priv, int port);
268 +int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg);
269 +int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val);
270 +void rt2880_port_init(struct fe_priv *priv, struct device_node *np);
271 +
272 +#endif
273 --- /dev/null
274 +++ b/drivers/net/ethernet/mediatek/soc_rt2880.c
275 @@ -0,0 +1,76 @@
276 +/*   This program is free software; you can redistribute it and/or modify
277 + *   it under the terms of the GNU General Public License as published by
278 + *   the Free Software Foundation; version 2 of the License
279 + *
280 + *   This program is distributed in the hope that it will be useful,
281 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
282 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
283 + *   GNU General Public License for more details.
284 + *
285 + *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
286 + *   Copyright (C) 2009-2015 Felix Fietkau <nbd@openwrt.org>
287 + *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
288 + */
289 +
290 +#include <linux/module.h>
291 +
292 +#include <asm/mach-ralink/ralink_regs.h>
293 +
294 +#include "mtk_eth_soc.h"
295 +#include "mdio_rt2880.h"
296 +
297 +#define RT2880_RESET_FE                        BIT(18)
298 +
299 +static void rt2880_init_data(struct fe_soc_data *data,
300 +                            struct net_device *netdev)
301 +{
302 +       struct fe_priv *priv = netdev_priv(netdev);
303 +
304 +       priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG |
305 +               FE_FLAG_JUMBO_FRAME | FE_FLAG_CALIBRATE_CLK;
306 +       netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX;
307 +       /* this should work according to the datasheet but actually does not*/
308 +       /* netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; */
309 +}
310 +
311 +void rt2880_fe_reset(void)
312 +{
313 +       fe_reset(RT2880_RESET_FE);
314 +}
315 +
316 +static int rt2880_fwd_config(struct fe_priv *priv)
317 +{
318 +       int ret;
319 +
320 +       ret = fe_set_clock_cycle(priv);
321 +       if (ret)
322 +               return ret;
323 +
324 +       fe_fwd_config(priv);
325 +       fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG);
326 +       fe_csum_config(priv);
327 +
328 +       return ret;
329 +}
330 +
331 +struct fe_soc_data rt2880_data = {
332 +       .init_data = rt2880_init_data,
333 +       .reset_fe = rt2880_fe_reset,
334 +       .fwd_config = rt2880_fwd_config,
335 +       .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS,
336 +       .checksum_bit = RX_DMA_L4VALID,
337 +       .rx_int = FE_RX_DONE_INT,
338 +       .tx_int = FE_TX_DONE_INT,
339 +       .status_int = FE_CNT_GDM_AF,
340 +       .mdio_read = rt2880_mdio_read,
341 +       .mdio_write = rt2880_mdio_write,
342 +       .mdio_adjust_link = rt2880_mdio_link_adjust,
343 +       .port_init = rt2880_port_init,
344 +};
345 +
346 +const struct of_device_id of_fe_match[] = {
347 +       { .compatible = "ralink,rt2880-eth", .data = &rt2880_data },
348 +       {},
349 +};
350 +
351 +MODULE_DEVICE_TABLE(of, of_fe_match);