[pxa] refresh 2.6.21 patches
[openwrt.git] / target / linux / pxa / patches-2.6.21 / 044-smc911x-fixup.patch
1 --- a/drivers/net/smc911x.c
2 +++ b/drivers/net/smc911x.c
3 @@ -76,6 +76,7 @@ static const char version[] =
4  #include <linux/etherdevice.h>
5  #include <linux/skbuff.h>
6  
7 +#include <linux/irq.h>
8  #include <asm/io.h>
9  #include <asm/irq.h>
10  
11 @@ -303,14 +304,14 @@ static void smc911x_reset(struct net_dev
12         SMC_SET_AFC_CFG(lp->afc_cfg);
13  
14  
15 -       /* Set to LED outputs */
16 -       SMC_SET_GPIO_CFG(0x70070000);
17 +       /* Set to LED outputs and configure EEPROM pins as GP outputs */
18 +       SMC_SET_GPIO_CFG(GPIO_CFG_LED1_EN_ | GPIO_CFG_LED2_EN_ | 1 << 20);
19  
20         /*
21 -        * Deassert IRQ for 1*10us for edge type interrupts
22 +        * Deassert IRQ for 22*10us for edge type interrupts
23          * and drive IRQ pin push-pull
24          */
25 -       SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ );
26 +       SMC_SET_IRQ_CFG( (22 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ );
27  
28         /* clear anything saved */
29         if (lp->pending_tx_skb != NULL) {
30 @@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(stru
31         if (fifo_count <= 4) {
32                 /* Manually dump the packet data */
33                 while (fifo_count--)
34 -                       SMC_GET_RX_FIFO();
35 +                       (void)SMC_GET_RX_FIFO();
36         } else   {
37                 /* Fast forward through the bad packet */
38                 SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_);
39 @@ -900,6 +901,7 @@ static void smc911x_phy_powerdown(struct
40         unsigned long ioaddr = dev->base_addr;
41         unsigned int bmcr;
42  
43 +       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
44         /* Enter Link Disable state */
45         SMC_GET_PHY_BMCR(phy, bmcr);
46         bmcr |= BMCR_PDOWN;
47 @@ -925,6 +927,7 @@ static void smc911x_phy_check_media(stru
48  
49         if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
50                 /* duplex state has changed */
51 +               DBG(SMC_DEBUG_MISC, "%s: duplex state has changed\n", dev->name);
52                 SMC_GET_PHY_BMCR(phyaddr, bmcr);
53                 SMC_GET_MAC_CR(cr);
54                 if (lp->mii.full_duplex) {
55 @@ -960,6 +963,7 @@ static void smc911x_phy_configure(struct
56         int my_phy_caps; /* My PHY capabilities */
57         int my_ad_caps; /* My Advertised capabilities */
58         int status;
59 +       int bmcr;
60         unsigned long flags;
61  
62         DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
63 @@ -1033,9 +1037,12 @@ static void smc911x_phy_configure(struct
64  
65         DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps);
66         DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps);
67 +       DBG(SMC_DEBUG_MISC, "%s: phy advertised readback caps=0x%04x\n", dev->name, status);
68  
69         /* Restart auto-negotiation process in order to advertise my caps */
70 -       SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART);
71 +       SMC_GET_PHY_BMCR(phyaddr, bmcr);
72 +       bmcr |= BMCR_ANENABLE | BMCR_ANRESTART;
73 +       SMC_SET_PHY_BMCR(phyaddr, bmcr);
74  
75         smc911x_phy_check_media(dev, 1);
76  
77 @@ -1888,6 +1895,39 @@ static int __init smc911x_findirq(unsign
78         return probe_irq_off(cookie);
79  }
80  
81 +static inline unsigned int is_gumstix_oui(u8 *addr)
82 +{
83 +       return (addr[0] == 0x00 && addr[1] == 0x15 && addr[2] == 0xC9);
84 +}
85 +
86 +/**
87 + * gen_serial_ether_addr - Generate software assigned Ethernet address
88 + * based on the system_serial number
89 + * @addr: Pointer to a six-byte array containing the Ethernet address
90 + *
91 + * Generate an Ethernet address (MAC) that is not multicast
92 + * and has the local assigned bit set, keyed on the system_serial
93 + */
94 +static inline void gen_serial_ether_addr(u8 *addr)
95 +{
96 +       static u8 ether_serial_digit = 0;
97 +       addr [0] = system_serial_high >> 8;
98 +       addr [1] = system_serial_high;
99 +       addr [2] = system_serial_low >> 24;
100 +       addr [3] = system_serial_low >> 16;
101 +       addr [4] = system_serial_low >> 8;
102 +       addr [5] = (system_serial_low & 0xc0) | /* top bits are from system serial */
103 +               (1 << 4) |                      /* 2 bits identify interface type 1=ether, 2=usb, 3&4 undef */
104 +               ((ether_serial_digit++) & 0x0f);        /* 15 possible interfaces of each type */
105 +
106 +       if(!is_gumstix_oui(addr))
107 +       {
108 +               addr [0] &= 0xfe;               /* clear multicast bit */
109 +               addr [0] |= 0x02;               /* set local assignment bit (IEEE802) */
110 +       }
111 +}
112 +
113 +
114  /*
115   * Function: smc911x_probe(unsigned long ioaddr)
116   *
117 @@ -2116,15 +2156,13 @@ static int __init smc911x_probe(struct n
118  #endif
119                 printk("\n");
120                 if (!is_valid_ether_addr(dev->dev_addr)) {
121 -                       printk("%s: Invalid ethernet MAC address. Please "
122 -                                       "set using ifconfig\n", dev->name);
123 -               } else {
124 -                       /* Print the Ethernet address */
125 -                       printk("%s: Ethernet addr: ", dev->name);
126 -                       for (i = 0; i < 5; i++)
127 -                               printk("%2.2x:", dev->dev_addr[i]);
128 -                       printk("%2.2x\n", dev->dev_addr[5]);
129 +                       gen_serial_ether_addr(dev->dev_addr);
130                 }
131 +               /* Print the Ethernet address */
132 +               printk("%s: Ethernet addr: ", dev->name);
133 +               for (i = 0; i < 5; i++)
134 +                       printk("%2.2x:", dev->dev_addr[i]);
135 +               printk("%2.2x\n", dev->dev_addr[5]);
136  
137                 if (lp->phy_type == 0) {
138                         PRINTK("%s: No PHY found\n", dev->name);
139 @@ -2300,8 +2338,15 @@ static struct platform_driver smc911x_dr
140         },
141  };
142  
143 +#ifdef CONFIG_ARCH_GUMSTIX
144 +extern void gumstix_smc911x_load(void);
145 +#endif
146 +
147  static int __init smc911x_init(void)
148  {
149 +#ifdef CONFIG_ARCH_GUMSTIX
150 +       gumstix_smc911x_load();
151 +#endif
152         return platform_driver_register(&smc911x_driver);
153  }
154  
155 --- /dev/null
156 +++ b/drivers/net/gumstix-smc911x.c
157 @@ -0,0 +1,148 @@
158 +/*
159 + *  Gumstix SMC911x chip intialization driver
160 + *
161 + *  Author:     Craig Hughes
162 + *  Created:    December 9, 2004
163 + *  Copyright:  (C) 2004 Craig Hughes
164 + *
165 + * This program is free software; you can redistribute it and/or modify
166 + * it under the terms of the GNU General Public License as published by
167 + * the Free Software Foundation; either version 2 of the License, or
168 + * (at your option) any later version.
169 + *
170 + */
171 +
172 +#include <linux/module.h>
173 +#include <linux/ioport.h>
174 +#include <linux/device.h>
175 +#include <linux/platform_device.h>
176 +#include <linux/delay.h>
177 +
178 +#include <asm/hardware.h>
179 +#include <asm/arch/pxa-regs.h>
180 +#include <asm/delay.h>
181 +
182 +#include <asm/arch/gumstix.h>
183 +
184 +#define SMC_DEBUG               9
185 +#include <asm/io.h>
186 +#include "smc911x.h"
187 +
188 +static struct resource gumstix_smc911x0_resources[] = {
189 +       [0] = {
190 +               .name   = "smc911x-regs",
191 +               .start  = PXA_CS1_PHYS,
192 +               .end    = PXA_CS1_PHYS + 0x000fffff,
193 +               .flags  = IORESOURCE_MEM,
194 +       },
195 +       [1] = {
196 +               .start  = GUMSTIX_ETH0_IRQ,
197 +               .end    = GUMSTIX_ETH0_IRQ,
198 +               .flags  = IORESOURCE_IRQ,
199 +       },
200 +};
201 +
202 +static struct resource gumstix_smc911x1_resources[] = {
203 +       [0] = {
204 +               .name   = "smc911x-regs",
205 +               .start  = PXA_CS2_PHYS,
206 +               .end    = PXA_CS2_PHYS + 0x000fffff,
207 +               .flags  = IORESOURCE_MEM,
208 +       },
209 +       [1] = {
210 +               .start  = GUMSTIX_ETH1_IRQ,
211 +               .end    = GUMSTIX_ETH1_IRQ,
212 +               .flags  = IORESOURCE_IRQ,
213 +       },
214 +};
215 +
216 +static struct platform_device gumstix_smc911x0_device = {
217 +       .name           = "smc911x",
218 +       .id             = 0,
219 +       .num_resources  = ARRAY_SIZE(gumstix_smc911x0_resources),
220 +       .resource       = gumstix_smc911x0_resources,
221 +};
222 +
223 +static struct platform_device gumstix_smc911x1_device = {
224 +       .name           = "smc911x",
225 +       .id             = 1,
226 +       .num_resources  = ARRAY_SIZE(gumstix_smc911x1_resources),
227 +       .resource       = gumstix_smc911x1_resources,
228 +};
229 +
230 +static struct platform_device *smc911x_devices[] = {
231 +       &gumstix_smc911x0_device,
232 +       &gumstix_smc911x1_device,
233 +};
234 +
235 +/* First we're going to test if there's a 2nd SMC911x, and if not, then we'll free up those resources and the GPIO lines
236 + * that it would otherwise use.  We have no choice but to probe by doing:
237 + * Set nCS2 to CS2 mode
238 + * Set the reset line to GPIO out mode, and pull it high, then drop it low (to trigger reset)
239 + * Read from the memory space to check for the sentinel sequence identifying a likely SMC911x device
240 + */
241 +int __init gumstix_smc911x_init(void)
242 +{
243 +       unsigned int val, num_devices=ARRAY_SIZE(smc911x_devices);
244 +       void *ioaddr;
245 +
246 +       /* Set up nPWE */
247 +       pxa_gpio_mode(GPIO49_nPWE_MD);
248 +
249 +       pxa_gpio_mode(GPIO78_nCS_2_MD);
250 +       // If either if statement fails, then we'll drop out and turn_off_eth1,
251 +       // if both succeed, then we'll skip that and just proceed with 2 cards
252 +       if(request_mem_region(gumstix_smc911x1_resources[1].start, SMC911X_IO_EXTENT, "smc911x probe"))
253 +       {
254 +               ioaddr = ioremap(gumstix_smc911x1_resources[1].start, SMC911X_IO_EXTENT);
255 +               val = SMC_GET_PN();
256 +               iounmap(ioaddr);
257 +               release_mem_region(gumstix_smc911x1_resources[1].start, SMC911X_IO_EXTENT);
258 +               if (CHIP_9115 == val ||
259 +                       CHIP_9116 == val ||
260 +                       CHIP_9117 == val ||
261 +                       CHIP_9118 == val ) {
262 +                       goto proceed;
263 +               }
264 +       }
265 +
266 +turn_off_eth1:
267 +       // This is apparently not an SMC911x
268 +       // So, let's decrement the number of devices to request, and reset the GPIO lines to GPIO IN mode
269 +       num_devices--;
270 +       smc911x_devices[1] = NULL;
271 +       pxa_gpio_mode(78 | GPIO_IN);
272 +       
273 +proceed:
274 +       pxa_gpio_mode(GPIO15_nCS_1_MD);
275 +
276 +       if(smc911x_devices[1]) pxa_gpio_mode(GPIO_GUMSTIX_ETH1_RST_MD);
277 +       pxa_gpio_mode(GPIO_GUMSTIX_ETH0_RST_MD);
278 +
279 +       if(smc911x_devices[1]) GPCR(GPIO_GUMSTIX_ETH1_RST) = GPIO_bit(GPIO_GUMSTIX_ETH1_RST);
280 +       GPCR(GPIO_GUMSTIX_ETH0_RST) = GPIO_bit(GPIO_GUMSTIX_ETH0_RST);
281 +       msleep(500); // Hold RESET for at least 200µ
282 +
283 +       if(smc911x_devices[1]) GPSR(GPIO_GUMSTIX_ETH1_RST) = GPIO_bit(GPIO_GUMSTIX_ETH1_RST);
284 +       GPSR(GPIO_GUMSTIX_ETH0_RST) = GPIO_bit(GPIO_GUMSTIX_ETH0_RST);
285 +       msleep(50);
286 +
287 +       return platform_add_devices(smc911x_devices, num_devices);
288 +}
289 +
290 +void __exit gumstix_smc911x_exit(void)
291 +{
292 +       if(smc911x_devices[1] != NULL) platform_device_unregister(&gumstix_smc911x1_device);
293 +       platform_device_unregister(&gumstix_smc911x0_device);
294 +}
295 +
296 +void gumstix_smc911x_load(void) {}
297 +EXPORT_SYMBOL(gumstix_smc911x_load);
298 +
299 +module_init(gumstix_smc911x_init);
300 +module_exit(gumstix_smc911x_exit);
301 +
302 +MODULE_LICENSE("GPL");
303 +MODULE_AUTHOR("Craig Hughes <craig@gumstix.com>");
304 +MODULE_DESCRIPTION("Gumstix board SMC911x chip initialization driver");
305 +MODULE_VERSION("1:0.1");
306 --- a/drivers/net/Kconfig
307 +++ b/drivers/net/Kconfig
308 @@ -1020,6 +1020,13 @@ config SMC911X
309           called smc911x.  If you want to compile it as a module, say M 
310           here and read <file:Documentation/modules.txt>
311  
312 +config SMC911X_GUMSTIX
313 +       tristate
314 +       default m if SMC911X=m
315 +       default y if SMC911X=y
316 +       depends on SMC911X && ARCH_GUMSTIX
317 +
318 +
319  config NET_VENDOR_RACAL
320         bool "Racal-Interlan (Micom) NI cards"
321         depends on NET_ETHERNET && ISA
322 --- a/drivers/net/Makefile
323 +++ b/drivers/net/Makefile
324 @@ -202,6 +202,7 @@ obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
325  obj-$(CONFIG_MACB) += macb.o
326  
327  obj-$(CONFIG_SMC91X_GUMSTIX) += gumstix-smc91x.o
328 +obj-$(CONFIG_SMC911X_GUMSTIX) += gumstix-smc911x.o
329  obj-$(CONFIG_ARM) += arm/
330  obj-$(CONFIG_DEV_APPLETALK) += appletalk/
331  obj-$(CONFIG_TR) += tokenring/
332 --- a/include/asm-arm/arch-pxa/gumstix.h
333 +++ b/include/asm-arm/arch-pxa/gumstix.h
334 @@ -52,7 +52,7 @@
335  #define GPIO_GUMSTIX_ETH0_RST          80
336  #define GPIO_GUMSTIX_ETH0              36
337  #else
338 -#define GPIO_GUMSTIX_ETH0_RST          32
339 +#define GPIO_GUMSTIX_ETH0_RST          107
340  #define GPIO_GUMSTIX_ETH0              99
341  #endif
342  #define GPIO_GUMSTIX_ETH1_RST          52
343 --- a/drivers/net/smc911x.h
344 +++ b/drivers/net/smc911x.h
345 @@ -33,7 +33,9 @@
346   * Use the DMA feature on PXA chips
347   */
348  #ifdef CONFIG_ARCH_PXA
349 +#if !defined( CONFIG_SMC911X_GUMSTIX ) && !defined( CONFIG_SMC911X_GUMSTIX_MODULE )
350    #define SMC_USE_PXA_DMA      1
351 +#endif
352    #define SMC_USE_16BIT                0
353    #define SMC_USE_32BIT                1
354  #endif
355 @@ -46,13 +48,13 @@
356  #if    SMC_USE_16BIT
357  #define SMC_inb(a, r)                   readb((a) + (r))
358  #define SMC_inw(a, r)                   readw((a) + (r))
359 -#define SMC_inl(a, r)                   ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16))
360 +#define SMC_inl(a, r)                   ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw((a)+2, r)<<16))
361  #define SMC_outb(v, a, r)               writeb(v, (a) + (r))
362  #define SMC_outw(v, a, r)               writew(v, (a) + (r))
363  #define SMC_outl(v, a, r)                       \
364         do{                                      \
365 -                writel(v & 0xFFFF, (a) + (r));  \
366 -                writel(v >> 16, (a) + (r) + 2); \
367 +                writel((v) & 0xFFFF, (a) + (r));        \
368 +                writel((v) >> 16, (a) + (r) + 2); \
369          } while (0)
370  #define SMC_insl(a, r, p, l)    readsw((short*)((a) + (r)), p, l*2)
371  #define SMC_outsl(a, r, p, l)   writesw((short*)((a) + (r)), p, l*2)