aboutsummaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches/410-ar231x_2.6.28.patch
blob: 30d1c56a4c74e18cef86ee1ffc8225765c25577d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
--- a/ath/if_ath_ahb.c
+++ b/ath/if_ath_ahb.c
@@ -33,20 +33,15 @@
 #include "if_ath_ahb.h"
 #include "ah_soc.h"
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-#error "Kernel versions older than 2.6.19 are not supported!"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+#include <ar231x_platform.h>
 #endif
 
 struct ath_ahb_softc {
 	struct ath_softc	aps_sc;
-#ifdef CONFIG_PM
-	u32 aps_pmstate[16];
-#endif
+	struct ar531x_config aps_config;
 };
 
-static struct ath_ahb_softc *sclist[2] = {NULL, NULL};
-static u_int8_t num_activesc = 0;
-
 /*
  * Module glue.
  */
@@ -101,13 +96,13 @@ ahb_enable_wmac(u_int16_t devid, u_int16
 		while (REG_READ(AR5315_PCI_MAC_PCICFG) & AR5315_PCI_MAC_PCICFG_SPWR_DN);
 	} else {
 		switch (wlanNum) {
-		case AR531X_WLAN0_NUM:
+		case 0:
 			reset = (AR531X_RESET_WLAN0 |
 				AR531X_RESET_WARM_WLAN0_MAC |
 				AR531X_RESET_WARM_WLAN0_BB);
 			enable = AR531X_ENABLE_WLAN0;
 			break;
-		case AR531X_WLAN1_NUM:
+		case 1:
 			reset = (AR531X_RESET_WLAN1 |
 				AR531X_RESET_WARM_WLAN1_MAC |
 				AR531X_RESET_WARM_WLAN1_BB);
@@ -144,10 +139,10 @@ ahb_disable_wmac(u_int16_t devid, u_int1
 		*en &= ~AR5315_ARB_WLAN;
 	} else {
 		switch (wlanNum) {
-		case AR531X_WLAN0_NUM:
+		case 0:
 			enable = AR531X_ENABLE_WLAN0;
 			break;
-		case AR531X_WLAN1_NUM:
+		case 1:
 			enable = AR531X_ENABLE_WLAN1;
 			break;
 		default:
@@ -159,29 +154,6 @@ ahb_disable_wmac(u_int16_t devid, u_int1
 }
 
 
-static int
-exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
-{
-	struct ath_ahb_softc *sc = sclist[wlanNum];
-	struct net_device *dev;
-	u_int16_t devid;
-
-	if (sc == NULL)
-		return -ENODEV; /* XXX: correct return value? */
-
-	dev = sc->aps_sc.sc_dev;
-	ath_detach(dev);
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-	devid = sc->aps_sc.devid;
-	config->tag = (void *)((unsigned long) devid);
-
-	ahb_disable_wmac(devid, wlanNum);
-	free_netdev(dev);
-	sclist[wlanNum] = NULL;
-	return 0;
-}
-
 static const char ubnt[] = "Ubiquiti Networks";
 /* { vendorname, cardname, vendorid, cardid, subsys vendorid, subsys id, poweroffset } */
 static const struct ath_hw_detect cards[] = {
@@ -201,6 +173,114 @@ static const struct ath_hw_detect cards[
 	{ ubnt, "Bullet5",             PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc205 },
 };
 
+static void
+ahb_hw_detect(struct ath_ahb_softc *sc, const char *radio)
+{
+	u16 *radio_data = (u16 *) radio;
+	if (radio_data) {
+		u16 vendor, id, subvendor, subid;
+		vendor = radio_data[1];
+		id = radio_data[0];
+		subvendor = radio_data[8];
+		subid = radio_data[7];
+		ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);
+	}
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+
+static int ahb_wmac_probe(struct platform_device *pdev)
+{
+	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+	struct ath_ahb_softc *sc;
+	struct net_device *dev;
+	struct resource *res;
+	const char *athname;
+	int err;
+
+	ahb_enable_wmac(bcfg->devid, pdev->id);
+	dev = alloc_netdev(sizeof(struct ath_ahb_softc), "wifi%d", ether_setup);
+	if (!dev)
+		return -ENOMEM;
+
+	sc = dev->priv;
+	sc->aps_sc.sc_dev = dev;
+
+	dev->irq = platform_get_irq(pdev, 0);
+	if (dev->irq <= 0) {
+		printk("%s: Cannot find IRQ resource\n", dev->name);
+		goto error;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		printk("%s: Cannot find MMIO resource\n", dev->name);
+		goto error;
+	}
+
+	dev->mem_start = KSEG1ADDR(res->start);
+	dev->mem_end = KSEG1ADDR(res->end);
+	sc->aps_sc.sc_iobase = (void __iomem *) dev->mem_start;
+	sc->aps_sc.sc_bdev = NULL;
+
+	/* bus information for the HAL */
+	sc->aps_config.board = (const struct ar531x_boarddata *) bcfg->config;
+	sc->aps_config.radio = bcfg->radio;
+	sc->aps_config.unit = pdev->id;
+	sc->aps_config.tag = NULL;
+
+	err = ath_attach(bcfg->devid, dev, &sc->aps_config);
+	if (err != 0) {
+		printk("%s: ath_attach failed: %d\n", dev->name, err);
+		goto error;
+	}
+
+	athname = ath_hal_probe(ATHEROS_VENDOR_ID, bcfg->devid);
+	printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
+		dev_info, dev->name, athname ? athname : "Atheros ???", dev->mem_start, dev->irq);
+
+	if (request_irq(dev->irq, ath_intr, IRQF_SHARED|IRQF_DISABLED, dev->name, dev)) {
+		printk(KERN_WARNING "%s: %s: request_irq failed\n", dev_info, dev->name);
+		goto error;
+	}
+
+	sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
+	sc->aps_sc.sc_ledpin = bcfg->config->sysLedGpio;
+	sc->aps_sc.sc_invalid = 0;
+	ahb_hw_detect(sc, bcfg->radio);
+	platform_set_drvdata(pdev, dev);
+	return 0;
+
+error_dev:
+	free_irq(dev->irq, dev);
+error:
+	free_netdev(dev);
+
+	return -ENODEV;
+}
+
+
+static int ahb_wmac_remove(struct platform_device *pdev)
+{
+	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+	struct net_device *dev;
+
+	dev = platform_get_drvdata(pdev);
+	ath_detach(dev);
+
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+
+	ahb_disable_wmac(bcfg->devid, pdev->id);
+	free_netdev(dev);
+
+	return 0;
+}
+
+#else
+
+static struct ath_ahb_softc *sclist[2] = {NULL, NULL};
+
 static int
 init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
 {
@@ -253,7 +333,7 @@ init_ath_wmac(u_int16_t devid, u_int16_t
 	sc->aps_sc.sc_iobase = (void __iomem *) dev->mem_start;
 	sc->aps_sc.sc_bdev = NULL;
 
-	if (request_irq(dev->irq, ath_intr, IRQF_SHARED, dev->name, dev)) {
+	if (request_irq(dev->irq, ath_intr, IRQF_SHARED|IRQF_DISABLED, dev->name, dev)) {
 		printk(KERN_WARNING "%s: %s: request_irq failed\n", dev_info, dev->name);
 		goto bad3;
 	}
@@ -263,21 +343,12 @@ init_ath_wmac(u_int16_t devid, u_int16_t
 	athname = ath_hal_probe(ATHEROS_VENDOR_ID, devid);
 	printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
 		dev_info, dev->name, athname ? athname : "Atheros ???", dev->mem_start, dev->irq);
-	num_activesc++;
 	/* Ready to process interrupts */
 
 	sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
 	sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
 	sc->aps_sc.sc_invalid = 0;
-	radio_data = (u16 *) config->radio;
-	if (radio_data) {
-		u16 vendor, id, subvendor, subid;
-		vendor = radio_data[1];
-		id = radio_data[0];
-		subvendor = radio_data[8];
-		subid = radio_data[7];
-		ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);
-	}
+	ahb_hw_detect(sc, config->radio);
 
 	return 0;
 
@@ -292,6 +363,29 @@ init_ath_wmac(u_int16_t devid, u_int16_t
 	return -ENODEV;
 }
 
+static int
+exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
+{
+	struct ath_ahb_softc *sc = sclist[wlanNum];
+	struct net_device *dev;
+	u_int16_t devid;
+
+	if (sc == NULL)
+		return -ENODEV; /* XXX: correct return value? */
+
+	dev = sc->aps_sc.sc_dev;
+	ath_detach(dev);
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	devid = sc->aps_sc.devid;
+	config->tag = (void *)((unsigned long) devid);
+
+	ahb_disable_wmac(devid, wlanNum);
+	free_netdev(dev);
+	sclist[wlanNum] = NULL;
+	return 0;
+}
+
 static int ahb_wmac_probe(struct platform_device *pdev)
 {
 	u_int16_t devid;
@@ -312,11 +406,18 @@ static int ahb_wmac_remove(struct platfo
 	return 0;
 }
 
+#endif
+
 static struct platform_driver ahb_wmac_driver = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+	.driver.name = "ar231x-wmac",
+#else
 	.driver.name = "ar531x-wmac",
+#endif
 	.probe = ahb_wmac_probe,
 	.remove = ahb_wmac_remove
 };
+
 int
 ath_ioctl_ethtool(struct ath_softc *sc, int cmd, void __user *addr)
 {