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