OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --- a/drivers/net/wireless/ath/ath9k/ahb.c |
2 | +++ b/drivers/net/wireless/ath/ath9k/ahb.c |
||
3 | @@ -20,7 +20,15 @@ |
||
4 | #include <linux/platform_device.h> |
||
5 | #include <linux/module.h> |
||
6 | #include <linux/mod_devicetable.h> |
||
7 | +#include <linux/of_device.h> |
||
8 | #include "ath9k.h" |
||
9 | +#include <linux/ath9k_platform.h> |
||
10 | + |
||
11 | +#ifdef CONFIG_OF |
||
12 | +#include <asm/mach-ath79/ath79.h> |
||
13 | +#include <asm/mach-ath79/ar71xx_regs.h> |
||
14 | +#include <linux/mtd/mtd.h> |
||
15 | +#endif |
||
16 | |||
17 | static const struct platform_device_id ath9k_platform_id_table[] = { |
||
18 | { |
||
19 | @@ -69,6 +77,235 @@ static const struct ath_bus_ops ath_ahb_ |
||
20 | .eeprom_read = ath_ahb_eeprom_read, |
||
21 | }; |
||
22 | |||
23 | +#ifdef CONFIG_OF |
||
24 | + |
||
25 | +#define QCA955X_DDR_CTL_CONFIG 0x108 |
||
26 | +#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) |
||
27 | + |
||
28 | +static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata) |
||
29 | +{ |
||
30 | +#ifdef CONFIG_MTD |
||
31 | + struct device_node *mtd_np = NULL; |
||
32 | + size_t retlen; |
||
33 | + int size, ret; |
||
34 | + struct mtd_info *mtd; |
||
35 | + const char *part; |
||
36 | + const __be32 *list; |
||
37 | + phandle phandle; |
||
38 | + |
||
39 | + list = of_get_property(np, "mtd-cal-data", &size); |
||
40 | + if (!list) |
||
41 | + return 0; |
||
42 | + |
||
43 | + if (size != (2 * sizeof(*list))) |
||
44 | + return 1; |
||
45 | + |
||
46 | + phandle = be32_to_cpup(list++); |
||
47 | + if (phandle) |
||
48 | + mtd_np = of_find_node_by_phandle(phandle); |
||
49 | + |
||
50 | + if (!mtd_np) |
||
51 | + return 1; |
||
52 | + |
||
53 | + part = of_get_property(mtd_np, "label", NULL); |
||
54 | + if (!part) |
||
55 | + part = mtd_np->name; |
||
56 | + |
||
57 | + mtd = get_mtd_device_nm(part); |
||
58 | + if (IS_ERR(mtd)) |
||
59 | + return 1; |
||
60 | + |
||
61 | + ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data), |
||
62 | + &retlen, (u8*)pdata->eeprom_data); |
||
63 | + put_mtd_device(mtd); |
||
64 | + |
||
65 | +#endif |
||
66 | + return 0; |
||
67 | +} |
||
68 | + |
||
69 | +static int ar913x_wmac_reset(void) |
||
70 | +{ |
||
71 | + ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); |
||
72 | + mdelay(10); |
||
73 | + |
||
74 | + ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); |
||
75 | + mdelay(10); |
||
76 | + |
||
77 | + return 0; |
||
78 | +} |
||
79 | + |
||
80 | +static int ar933x_wmac_reset(void) |
||
81 | +{ |
||
82 | + int retries = 20; |
||
83 | + |
||
84 | + ath79_device_reset_set(AR933X_RESET_WMAC); |
||
85 | + ath79_device_reset_clear(AR933X_RESET_WMAC); |
||
86 | + |
||
87 | + while (1) { |
||
88 | + u32 bootstrap; |
||
89 | + |
||
90 | + bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); |
||
91 | + if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0) |
||
92 | + return 0; |
||
93 | + |
||
94 | + if (retries-- == 0) |
||
95 | + break; |
||
96 | + |
||
97 | + udelay(10000); |
||
98 | + } |
||
99 | + |
||
100 | + pr_err("ar933x: WMAC reset timed out"); |
||
101 | + return -ETIMEDOUT; |
||
102 | +} |
||
103 | + |
||
104 | +static int qca955x_wmac_reset(void) |
||
105 | +{ |
||
106 | + int i; |
||
107 | + |
||
108 | + /* Try to wait for WMAC DDR activity to stop */ |
||
109 | + for (i = 0; i < 10; i++) { |
||
110 | + if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) & |
||
111 | + QCA955X_DDR_CTL_CONFIG_ACT_WMAC)) |
||
112 | + break; |
||
113 | + |
||
114 | + udelay(10); |
||
115 | + } |
||
116 | + |
||
117 | + ath79_device_reset_set(QCA955X_RESET_RTC); |
||
118 | + udelay(10); |
||
119 | + ath79_device_reset_clear(QCA955X_RESET_RTC); |
||
120 | + udelay(10); |
||
121 | + |
||
122 | + return 0; |
||
123 | +} |
||
124 | + |
||
125 | +enum { |
||
126 | + AR913X_WMAC = 0, |
||
127 | + AR933X_WMAC, |
||
128 | + AR934X_WMAC, |
||
129 | + QCA953X_WMAC, |
||
130 | + QCA955X_WMAC, |
||
131 | + QCA956X_WMAC, |
||
132 | +}; |
||
133 | + |
||
134 | +static int ar9330_get_soc_revision(void) |
||
135 | +{ |
||
136 | + if (ath79_soc_rev == 1) |
||
137 | + return ath79_soc_rev; |
||
138 | + |
||
139 | + return 0; |
||
140 | +} |
||
141 | + |
||
142 | +static int ath79_get_soc_revision(void) |
||
143 | +{ |
||
144 | + return ath79_soc_rev; |
||
145 | +} |
||
146 | + |
||
147 | +static const struct of_ath_ahb_data { |
||
148 | + u16 dev_id; |
||
149 | + u32 bootstrap_reg; |
||
150 | + u32 bootstrap_ref; |
||
151 | + |
||
152 | + int (*soc_revision)(void); |
||
153 | + int (*wmac_reset)(void); |
||
154 | +} of_ath_ahb_data[] = { |
||
155 | + [AR913X_WMAC] = { |
||
156 | + .dev_id = AR5416_AR9100_DEVID, |
||
157 | + .wmac_reset = ar913x_wmac_reset, |
||
158 | + |
||
159 | + }, |
||
160 | + [AR933X_WMAC] = { |
||
161 | + .dev_id = AR9300_DEVID_AR9330, |
||
162 | + .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP, |
||
163 | + .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40, |
||
164 | + .soc_revision = ar9330_get_soc_revision, |
||
165 | + .wmac_reset = ar933x_wmac_reset, |
||
166 | + }, |
||
167 | + [AR934X_WMAC] = { |
||
168 | + .dev_id = AR9300_DEVID_AR9340, |
||
169 | + .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP, |
||
170 | + .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40, |
||
171 | + .soc_revision = ath79_get_soc_revision, |
||
172 | + }, |
||
173 | + [QCA953X_WMAC] = { |
||
174 | + .dev_id = AR9300_DEVID_AR953X, |
||
175 | + .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP, |
||
176 | + .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40, |
||
177 | + .soc_revision = ath79_get_soc_revision, |
||
178 | + }, |
||
179 | + [QCA955X_WMAC] = { |
||
180 | + .dev_id = AR9300_DEVID_QCA955X, |
||
181 | + .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP, |
||
182 | + .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40, |
||
183 | + .wmac_reset = qca955x_wmac_reset, |
||
184 | + }, |
||
185 | + [QCA956X_WMAC] = { |
||
186 | + .dev_id = AR9300_DEVID_QCA956X, |
||
187 | + .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP, |
||
188 | + .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40, |
||
189 | + .soc_revision = ath79_get_soc_revision, |
||
190 | + }, |
||
191 | +}; |
||
192 | + |
||
193 | +const struct of_device_id of_ath_ahb_match[] = { |
||
194 | + { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] }, |
||
195 | + { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] }, |
||
196 | + { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] }, |
||
197 | + { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] }, |
||
198 | + { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] }, |
||
199 | + { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] }, |
||
200 | + {}, |
||
201 | +}; |
||
202 | +MODULE_DEVICE_TABLE(of, of_ath_ahb_match); |
||
203 | + |
||
204 | +static int of_ath_ahb_probe(struct platform_device *pdev) |
||
205 | +{ |
||
206 | + struct ath9k_platform_data *pdata; |
||
207 | + const struct of_device_id *match; |
||
208 | + const struct of_ath_ahb_data *data; |
||
209 | + u8 led_pin; |
||
210 | + |
||
211 | + match = of_match_device(of_ath_ahb_match, &pdev->dev); |
||
212 | + data = (const struct of_ath_ahb_data *)match->data; |
||
213 | + |
||
214 | + pdata = dev_get_platdata(&pdev->dev); |
||
215 | + |
||
216 | + if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin)) |
||
217 | + pdata->led_pin = led_pin; |
||
218 | + else |
||
219 | + pdata->led_pin = -1; |
||
220 | + |
||
221 | + if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz")) |
||
222 | + pdata->disable_2ghz = true; |
||
223 | + |
||
224 | + if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz")) |
||
225 | + pdata->disable_5ghz = true; |
||
226 | + |
||
227 | + if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo")) |
||
228 | + pdata->tx_gain_buffalo = true; |
||
229 | + |
||
230 | + if (data->wmac_reset) { |
||
231 | + data->wmac_reset(); |
||
232 | + pdata->external_reset = data->wmac_reset; |
||
233 | + } |
||
234 | + |
||
235 | + if (data->bootstrap_reg && data->bootstrap_ref) { |
||
236 | + u32 t = ath79_reset_rr(data->bootstrap_reg); |
||
237 | + if (t & data->bootstrap_ref) |
||
238 | + pdata->is_clk_25mhz = false; |
||
239 | + else |
||
240 | + pdata->is_clk_25mhz = true; |
||
241 | + } |
||
242 | + |
||
243 | + pdata->get_mac_revision = data->soc_revision; |
||
244 | + |
||
245 | + if (of_get_wifi_cal(pdev->dev.of_node, pdata)) |
||
246 | + dev_err(&pdev->dev, "failed to load calibration data from mtd device\n"); |
||
247 | + |
||
248 | + return data->dev_id; |
||
249 | +} |
||
250 | +#endif |
||
251 | + |
||
252 | static int ath_ahb_probe(struct platform_device *pdev) |
||
253 | { |
||
254 | void __iomem *mem; |
||
255 | @@ -80,6 +317,17 @@ static int ath_ahb_probe(struct platform |
||
256 | int ret = 0; |
||
257 | struct ath_hw *ah; |
||
258 | char hw_name[64]; |
||
259 | + u16 dev_id; |
||
260 | + |
||
261 | + if (id) |
||
262 | + dev_id = id->driver_data; |
||
263 | + |
||
264 | +#ifdef CONFIG_OF |
||
265 | + if (pdev->dev.of_node) |
||
266 | + pdev->dev.platform_data = devm_kzalloc(&pdev->dev, |
||
267 | + sizeof(struct ath9k_platform_data), |
||
268 | + GFP_KERNEL); |
||
269 | +#endif |
||
270 | |||
271 | if (!dev_get_platdata(&pdev->dev)) { |
||
272 | dev_err(&pdev->dev, "no platform data specified\n"); |
||
273 | @@ -122,13 +370,16 @@ static int ath_ahb_probe(struct platform |
||
274 | sc->mem = mem; |
||
275 | sc->irq = irq; |
||
276 | |||
277 | +#ifdef CONFIG_OF |
||
278 | + dev_id = of_ath_ahb_probe(pdev); |
||
279 | +#endif |
||
280 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
||
281 | if (ret) { |
||
282 | dev_err(&pdev->dev, "request_irq failed\n"); |
||
283 | goto err_free_hw; |
||
284 | } |
||
285 | |||
286 | - ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops); |
||
287 | + ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops); |
||
288 | if (ret) { |
||
289 | dev_err(&pdev->dev, "failed to initialize device\n"); |
||
290 | goto err_irq; |
||
291 | @@ -159,6 +410,9 @@ static int ath_ahb_remove(struct platfor |
||
292 | free_irq(sc->irq, sc); |
||
293 | ieee80211_free_hw(sc->hw); |
||
294 | } |
||
295 | +#ifdef CONFIG_OF |
||
296 | + pdev->dev.platform_data = NULL; |
||
297 | +#endif |
||
298 | |||
299 | return 0; |
||
300 | } |
||
301 | @@ -168,6 +422,9 @@ static struct platform_driver ath_ahb_dr |
||
302 | .remove = ath_ahb_remove, |
||
303 | .driver = { |
||
304 | .name = "ath9k", |
||
305 | +#ifdef CONFIG_OF |
||
306 | + .of_match_table = of_ath_ahb_match, |
||
307 | +#endif |
||
308 | }, |
||
309 | .id_table = ath9k_platform_id_table, |
||
310 | }; |
||
311 | --- a/drivers/net/wireless/ath/ath9k/ath9k.h |
||
312 | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
||
313 | @@ -25,6 +25,7 @@ |
||
314 | #include <linux/time.h> |
||
315 | #include <linux/hw_random.h> |
||
316 | #include <linux/gpio/driver.h> |
||
317 | +#include <linux/reset.h> |
||
318 | |||
319 | #include "common.h" |
||
320 | #include "debug.h" |
||
321 | @@ -1023,6 +1024,9 @@ struct ath_softc { |
||
322 | struct ath_hw *sc_ah; |
||
323 | void __iomem *mem; |
||
324 | int irq; |
||
325 | +#ifdef CONFIG_OF |
||
326 | + struct reset_control *reset; |
||
327 | +#endif |
||
328 | spinlock_t sc_serial_rw; |
||
329 | spinlock_t sc_pm_lock; |
||
330 | spinlock_t sc_pcu_lock; |