[lantiq]
[openwrt.git] / target / linux / lantiq / patches-3.0 / 0015-MIPS-lantiq-adds-etop-support-for-ase-ar9.patch
1 From c7881d8d2b3aed9a90aa37dcf797328a9cfbe7b6 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Wed, 10 Aug 2011 15:32:16 +0200
4 Subject: [PATCH 15/24] MIPS: lantiq: adds etop support for ase/ar9
5
6 Extend the driver to handle the different DMA channel layout for AR9 and
7 SoCs. The patch also adds support for the integrated PHY found on Amazon-SE
8 and the gigabit switch found inside the AR9.
9
10 Signed-off-by: John Crispin <blogic@openwrt.org>
11 Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
12 ---
13  .../mips/include/asm/mach-lantiq/xway/lantiq_irq.h |   22 +---
14  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   10 ++
15  arch/mips/lantiq/xway/devices.c                    |   11 +-
16  arch/mips/lantiq/xway/mach-easy50601.c             |    5 +
17  drivers/net/lantiq_etop.c                          |  172 ++++++++++++++++++--
18  5 files changed, 180 insertions(+), 40 deletions(-)
19
20 Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
21 ===================================================================
22 --- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h        2011-10-04 20:05:23.000000000 +0200
23 +++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h     2011-10-04 20:05:44.146312365 +0200
24 @@ -40,26 +40,8 @@
25  
26  #define MIPS_CPU_TIMER_IRQ             7
27  
28 -#define LTQ_DMA_CH0_INT                (INT_NUM_IM2_IRL0)
29 -#define LTQ_DMA_CH1_INT                (INT_NUM_IM2_IRL0 + 1)
30 -#define LTQ_DMA_CH2_INT                (INT_NUM_IM2_IRL0 + 2)
31 -#define LTQ_DMA_CH3_INT                (INT_NUM_IM2_IRL0 + 3)
32 -#define LTQ_DMA_CH4_INT                (INT_NUM_IM2_IRL0 + 4)
33 -#define LTQ_DMA_CH5_INT                (INT_NUM_IM2_IRL0 + 5)
34 -#define LTQ_DMA_CH6_INT                (INT_NUM_IM2_IRL0 + 6)
35 -#define LTQ_DMA_CH7_INT                (INT_NUM_IM2_IRL0 + 7)
36 -#define LTQ_DMA_CH8_INT                (INT_NUM_IM2_IRL0 + 8)
37 -#define LTQ_DMA_CH9_INT                (INT_NUM_IM2_IRL0 + 9)
38 -#define LTQ_DMA_CH10_INT       (INT_NUM_IM2_IRL0 + 10)
39 -#define LTQ_DMA_CH11_INT       (INT_NUM_IM2_IRL0 + 11)
40 -#define LTQ_DMA_CH12_INT       (INT_NUM_IM2_IRL0 + 25)
41 -#define LTQ_DMA_CH13_INT       (INT_NUM_IM2_IRL0 + 26)
42 -#define LTQ_DMA_CH14_INT       (INT_NUM_IM2_IRL0 + 27)
43 -#define LTQ_DMA_CH15_INT       (INT_NUM_IM2_IRL0 + 28)
44 -#define LTQ_DMA_CH16_INT       (INT_NUM_IM2_IRL0 + 29)
45 -#define LTQ_DMA_CH17_INT       (INT_NUM_IM2_IRL0 + 30)
46 -#define LTQ_DMA_CH18_INT       (INT_NUM_IM2_IRL0 + 16)
47 -#define LTQ_DMA_CH19_INT       (INT_NUM_IM2_IRL0 + 21)
48 +#define LTQ_DMA_ETOP           ((ltq_is_ase()) ? \
49 +                               (INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0))
50  
51  #define LTQ_PPE_MBOX_INT       (INT_NUM_IM2_IRL0 + 24)
52  
53 Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
54 ===================================================================
55 --- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h        2011-10-04 20:05:23.000000000 +0200
56 +++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h     2011-10-04 20:05:44.146312365 +0200
57 @@ -80,6 +80,7 @@
58  #define LTQ_PMU_SIZE           0x1000
59  
60  #define PMU_DMA                        0x0020
61 +#define PMU_EPHY               0x0080
62  #define PMU_USB                        0x8041
63  #define PMU_SPI                        0x0100
64  #define PMU_LED                        0x0800
65 @@ -92,6 +93,10 @@
66  #define LTQ_ETOP_BASE_ADDR     0x1E180000
67  #define LTQ_ETOP_SIZE          0x40000
68  
69 +/* GBIT - gigabit switch */
70 +#define LTQ_GBIT_BASE_ADDR     0x1E108000
71 +#define LTQ_GBIT_SIZE          0x200
72 +
73  /* DMA */
74  #define LTQ_DMA_BASE_ADDR      0x1E104100
75  #define LTQ_DMA_SIZE           0x800
76 @@ -148,6 +153,11 @@
77  extern void ltq_pmu_disable(unsigned int module);
78  extern void ltq_cgu_enable(unsigned int clk);
79  
80 +static inline int ltq_is_ase(void)
81 +{
82 +       return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
83 +}
84 +
85  static inline int ltq_is_ar9(void)
86  {
87         return (ltq_get_soc_type() == SOC_TYPE_AR9);
88 Index: linux-3.0.3/arch/mips/lantiq/xway/devices.c
89 ===================================================================
90 --- linux-3.0.3.orig/arch/mips/lantiq/xway/devices.c    2011-10-04 20:03:54.000000000 +0200
91 +++ linux-3.0.3/arch/mips/lantiq/xway/devices.c 2011-10-04 20:05:44.146312365 +0200
92 @@ -79,18 +79,23 @@
93  }
94  
95  /* ethernet */
96 -static struct resource ltq_etop_resources =
97 -       MEM_RES("etop", LTQ_ETOP_BASE_ADDR, LTQ_ETOP_SIZE);
98 +static struct resource ltq_etop_resources[] = {
99 +       MEM_RES("etop", LTQ_ETOP_BASE_ADDR, LTQ_ETOP_SIZE),
100 +       MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
101 +};
102  
103  static struct platform_device ltq_etop = {
104         .name           = "ltq_etop",
105 -       .resource       = &ltq_etop_resources,
106 +       .resource       = ltq_etop_resources,
107         .num_resources  = 1,
108  };
109  
110  void __init
111  ltq_register_etop(struct ltq_eth_data *eth)
112  {
113 +       /* only register the gphy on socs that have one */
114 +       if (ltq_is_ar9() | ltq_is_vr9())
115 +               ltq_etop.num_resources = 2;
116         if (eth) {
117                 ltq_etop.dev.platform_data = eth;
118                 platform_device_register(&ltq_etop);
119 Index: linux-3.0.3/drivers/net/lantiq_etop.c
120 ===================================================================
121 --- linux-3.0.3.orig/drivers/net/lantiq_etop.c  2011-08-17 19:57:16.000000000 +0200
122 +++ linux-3.0.3/drivers/net/lantiq_etop.c       2011-10-04 20:05:44.146312365 +0200
123 @@ -34,6 +34,7 @@
124  #include <linux/init.h>
125  #include <linux/delay.h>
126  #include <linux/io.h>
127 +#include <linux/dma-mapping.h>
128  
129  #include <asm/checksum.h>
130  
131 @@ -69,10 +70,43 @@
132  #define ETOP_MII_REVERSE       0xe
133  #define ETOP_PLEN_UNDER                0x40
134  #define ETOP_CGEN              0x800
135 +#define ETOP_CFG_MII0          0x01
136  
137 -/* use 2 static channels for TX/RX */
138 +#define LTQ_GBIT_MDIO_CTL      0xCC
139 +#define LTQ_GBIT_MDIO_DATA     0xd0
140 +#define LTQ_GBIT_GCTL0         0x68
141 +#define LTQ_GBIT_PMAC_HD_CTL   0x8c
142 +#define LTQ_GBIT_P0_CTL                0x4
143 +#define LTQ_GBIT_PMAC_RX_IPG   0xa8
144 +
145 +#define PMAC_HD_CTL_AS         (1 << 19)
146 +#define PMAC_HD_CTL_RXSH       (1 << 22)
147 +
148 +/* Switch Enable (0=disable, 1=enable) */
149 +#define GCTL0_SE               0x80000000
150 +/* Disable MDIO auto polling (0=disable, 1=enable) */
151 +#define PX_CTL_DMDIO           0x00400000
152 +
153 +/* register information for the gbit's MDIO bus */
154 +#define MDIO_XR9_REQUEST       0x00008000
155 +#define MDIO_XR9_READ          0x00000800
156 +#define MDIO_XR9_WRITE         0x00000400
157 +#define MDIO_XR9_REG_MASK      0x1f
158 +#define MDIO_XR9_ADDR_MASK     0x1f
159 +#define MDIO_XR9_RD_MASK       0xffff
160 +#define MDIO_XR9_REG_OFFSET    0
161 +#define MDIO_XR9_ADDR_OFFSET   5
162 +#define MDIO_XR9_WR_OFFSET     16
163 +
164 +/* the newer xway socks have a embedded 3/7 port gbit multiplexer */
165 +#define ltq_has_gbit()         (ltq_is_ar9() || ltq_is_vr9())
166 +
167 +/* use 2 static channels for TX/RX
168 +   depending on the SoC we need to use different DMA channels for ethernet */
169  #define LTQ_ETOP_TX_CHANNEL    1
170 -#define LTQ_ETOP_RX_CHANNEL    6
171 +#define LTQ_ETOP_RX_CHANNEL    ((ltq_is_ase()) ? (5) : \
172 +                               ((ltq_has_gbit()) ? (0) : (6)))
173 +
174  #define IS_TX(x)               (x == LTQ_ETOP_TX_CHANNEL)
175  #define IS_RX(x)               (x == LTQ_ETOP_RX_CHANNEL)
176  
177 @@ -81,9 +115,15 @@
178  #define ltq_etop_w32_mask(x, y, z)     \
179                 ltq_w32_mask(x, y, ltq_etop_membase + (z))
180  
181 +#define ltq_gbit_r32(x)                ltq_r32(ltq_gbit_membase + (x))
182 +#define ltq_gbit_w32(x, y)     ltq_w32(x, ltq_gbit_membase + (y))
183 +#define ltq_gbit_w32_mask(x, y, z)     \
184 +               ltq_w32_mask(x, y, ltq_gbit_membase + (z))
185 +
186  #define DRV_VERSION    "1.0"
187  
188  static void __iomem *ltq_etop_membase;
189 +static void __iomem *ltq_gbit_membase;
190  
191  struct ltq_etop_chan {
192         int idx;
193 @@ -108,6 +148,9 @@
194         spinlock_t lock;
195  };
196  
197 +static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr,
198 +                               int phy_reg, u16 phy_data);
199 +
200  static int
201  ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
202  {
203 @@ -209,7 +252,7 @@
204  ltq_etop_dma_irq(int irq, void *_priv)
205  {
206         struct ltq_etop_priv *priv = _priv;
207 -       int ch = irq - LTQ_DMA_CH0_INT;
208 +       int ch = irq - LTQ_DMA_ETOP;
209  
210         napi_schedule(&priv->ch[ch].napi);
211         return IRQ_HANDLED;
212 @@ -242,26 +285,66 @@
213                         ltq_etop_free_channel(dev, &priv->ch[i]);
214  }
215  
216 +static void
217 +ltq_etop_gbit_init(void)
218 +{
219 +       ltq_pmu_enable(PMU_SWITCH);
220 +
221 +       ltq_gpio_request(42, 1, 0, 1, "MDIO");
222 +       ltq_gpio_request(43, 1, 0, 1, "MDC");
223 +
224 +       ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
225 +       /** Disable MDIO auto polling mode */
226 +       ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL);
227 +       /* set 1522 packet size */
228 +       ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0);
229 +       /* disable pmac & dmac headers */
230 +       ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0,
231 +               LTQ_GBIT_PMAC_HD_CTL);
232 +       /* Due to traffic halt when burst length 8,
233 +               replace default IPG value with 0x3B */
234 +       ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG);
235 +}
236 +
237  static int
238  ltq_etop_hw_init(struct net_device *dev)
239  {
240         struct ltq_etop_priv *priv = netdev_priv(dev);
241 +       unsigned int mii_mode = priv->pldata->mii_mode;
242         int i;
243  
244         ltq_pmu_enable(PMU_PPE);
245  
246 -       switch (priv->pldata->mii_mode) {
247 +       if (ltq_has_gbit()) {
248 +               ltq_etop_gbit_init();
249 +       }
250 +
251 +       switch (mii_mode) {
252 +       case PHY_INTERFACE_MODE_RGMII:
253         case PHY_INTERFACE_MODE_RMII:
254                 ltq_etop_w32_mask(ETOP_MII_MASK,
255                         ETOP_MII_REVERSE, LTQ_ETOP_CFG);
256                 break;
257  
258 +       case PHY_INTERFACE_MODE_GMII:
259         case PHY_INTERFACE_MODE_MII:
260                 ltq_etop_w32_mask(ETOP_MII_MASK,
261                         ETOP_MII_NORMAL, LTQ_ETOP_CFG);
262                 break;
263  
264         default:
265 +               if (ltq_is_ase()) {
266 +                       ltq_pmu_enable(PMU_EPHY);
267 +                       /* disable external MII */
268 +                       ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG);
269 +                       /* enable clock for internal PHY */
270 +                       ltq_cgu_enable(CGU_EPHY);
271 +                       /* we need to write this magic to the internal phy to
272 +                          make it work */
273 +                       ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
274 +                       pr_info("Selected EPHY mode\n");
275 +                       break;
276 +               }
277                 netdev_err(dev, "unknown mii mode %d\n",
278                         priv->pldata->mii_mode);
279                 return -ENOTSUPP;
280 @@ -273,7 +356,7 @@
281         ltq_dma_init_port(DMA_PORT_ETOP);
282  
283         for (i = 0; i < MAX_DMA_CHAN; i++) {
284 -               int irq = LTQ_DMA_CH0_INT + i;
285 +               int irq = LTQ_DMA_ETOP + i;
286                 struct ltq_etop_chan *ch = &priv->ch[i];
287  
288                 ch->idx = ch->dma.nr = i;
289 @@ -337,6 +420,39 @@
290  };
291  
292  static int
293 +ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr,
294 +               int phy_reg, u16 phy_data)
295 +{
296 +       u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE |
297 +               (phy_data << MDIO_XR9_WR_OFFSET) |
298 +               ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
299 +               ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
300 +
301 +       while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
302 +               ;
303 +       ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
304 +       while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
305 +               ;
306 +       return 0;
307 +}
308 +
309 +static int
310 +ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg)
311 +{
312 +       u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ |
313 +               ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
314 +               ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
315 +
316 +       while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
317 +               ;
318 +       ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
319 +       while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
320 +               ;
321 +       val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK;
322 +       return val;
323 +}
324 +
325 +static int
326  ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
327  {
328         u32 val = MDIO_REQUEST |
329 @@ -377,14 +493,11 @@
330  {
331         struct ltq_etop_priv *priv = netdev_priv(dev);
332         struct phy_device *phydev = NULL;
333 -       int phy_addr;
334  
335 -       for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
336 -               if (priv->mii_bus->phy_map[phy_addr]) {
337 -                       phydev = priv->mii_bus->phy_map[phy_addr];
338 -                       break;
339 -               }
340 -       }
341 +       if (ltq_is_ase())
342 +               phydev = priv->mii_bus->phy_map[8];
343 +       else
344 +               phydev = priv->mii_bus->phy_map[0];
345  
346         if (!phydev) {
347                 netdev_err(dev, "no PHY found\n");
348 @@ -406,6 +519,9 @@
349                               | SUPPORTED_Autoneg
350                               | SUPPORTED_MII
351                               | SUPPORTED_TP);
352 +       if (ltq_has_gbit())
353 +               phydev->supported &= SUPPORTED_1000baseT_Half
354 +                                       | SUPPORTED_1000baseT_Full;
355  
356         phydev->advertising = phydev->supported;
357         priv->phydev = phydev;
358 @@ -431,8 +547,13 @@
359         }
360  
361         priv->mii_bus->priv = dev;
362 -       priv->mii_bus->read = ltq_etop_mdio_rd;
363 -       priv->mii_bus->write = ltq_etop_mdio_wr;
364 +       if (ltq_has_gbit()) {
365 +               priv->mii_bus->read = ltq_etop_mdio_rd_xr9;
366 +               priv->mii_bus->write = ltq_etop_mdio_wr_xr9;
367 +       } else {
368 +               priv->mii_bus->read = ltq_etop_mdio_rd;
369 +               priv->mii_bus->write = ltq_etop_mdio_wr;
370 +       }
371         priv->mii_bus->name = "ltq_mii";
372         snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
373         priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
374 @@ -522,9 +643,9 @@
375         struct ltq_etop_priv *priv = netdev_priv(dev);
376         struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
377         struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
378 -       int len;
379         unsigned long flags;
380         u32 byte_offset;
381 +       int len;
382  
383         len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
384  
385 @@ -698,7 +819,7 @@
386  {
387         struct net_device *dev;
388         struct ltq_etop_priv *priv;
389 -       struct resource *res;
390 +       struct resource *res, *gbit_res;
391         int err;
392         int i;
393  
394 @@ -726,6 +847,23 @@
395                 goto err_out;
396         }
397  
398 +       if (ltq_has_gbit()) {
399 +               gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
400 +               if (!gbit_res) {
401 +                       dev_err(&pdev->dev, "failed to get gbit resource\n");
402 +                       err = -ENOENT;
403 +                       goto err_out;
404 +               }
405 +               ltq_gbit_membase = devm_ioremap_nocache(&pdev->dev,
406 +                       gbit_res->start, resource_size(gbit_res));
407 +               if (!ltq_gbit_membase) {
408 +                       dev_err(&pdev->dev, "failed to remap gigabit switch %d\n",
409 +                               pdev->id);
410 +                       err = -ENOMEM;
411 +                       goto err_out;
412 +               }
413 +       }
414 +
415         dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
416         strcpy(dev->name, "eth%d");
417         dev->netdev_ops = &ltq_eth_netdev_ops;