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