]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
[karo-tx-linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /* ****************** SDIO CARD Interface Functions **************************/
17
18 #include <linux/types.h>
19 #include <linux/netdevice.h>
20 #include <linux/export.h>
21 #include <linux/pci.h>
22 #include <linux/pci_ids.h>
23 #include <linux/sched.h>
24 #include <linux/completion.h>
25 #include <linux/mmc/sdio.h>
26 #include <linux/mmc/sdio_func.h>
27 #include <linux/mmc/card.h>
28
29 #include <defs.h>
30 #include <brcm_hw_ids.h>
31 #include <brcmu_utils.h>
32 #include <brcmu_wifi.h>
33 #include <soc.h>
34 #include "dhd.h"
35 #include "dhd_bus.h"
36 #include "dhd_dbg.h"
37 #include "sdio_host.h"
38
39 #define SDIOH_API_ACCESS_RETRY_LIMIT    2
40
41 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
42 {
43         struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
44
45         brcmf_dbg(TRACE, "***IRQHandler\n");
46
47         sdio_release_host(func);
48
49         brcmf_sdbrcm_isr(sdiodev->bus);
50
51         sdio_claim_host(func);
52 }
53
54 int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
55 {
56         brcmf_dbg(TRACE, "Entering\n");
57
58         sdio_claim_host(sdiodev->func[1]);
59         sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
60         sdio_release_host(sdiodev->func[1]);
61
62         return 0;
63 }
64
65 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
66 {
67         brcmf_dbg(TRACE, "Entering\n");
68
69         sdio_claim_host(sdiodev->func[1]);
70         sdio_release_irq(sdiodev->func[1]);
71         sdio_release_host(sdiodev->func[1]);
72
73         return 0;
74 }
75
76 u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
77                          int *err)
78 {
79         int status;
80         s32 retry = 0;
81         u8 data = 0;
82
83         do {
84                 if (retry)      /* wait for 1 ms till bus get settled down */
85                         udelay(1000);
86                 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
87                                                   addr, (u8 *) &data);
88         } while (status != 0
89                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
90         if (err)
91                 *err = status;
92
93         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
94                   fnc_num, addr, data);
95
96         return data;
97 }
98
99 void
100 brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
101                        u8 data, int *err)
102 {
103         int status;
104         s32 retry = 0;
105
106         do {
107                 if (retry)      /* wait for 1 ms till bus get settled down */
108                         udelay(1000);
109                 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
110                                                   addr, (u8 *) &data);
111         } while (status != 0
112                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
113         if (err)
114                 *err = status;
115
116         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
117                   fnc_num, addr, data);
118 }
119
120 int
121 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
122 {
123         int err = 0;
124         brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
125                          (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
126         if (!err)
127                 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
128                                        SBSDIO_FUNC1_SBADDRMID,
129                                        (address >> 16) & SBSDIO_SBADDRMID_MASK,
130                                        &err);
131         if (!err)
132                 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
133                                        SBSDIO_FUNC1_SBADDRHIGH,
134                                        (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
135                                        &err);
136
137         return err;
138 }
139
140 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
141 {
142         int status;
143         u32 word = 0;
144         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
145
146         brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
147
148         if (bar0 != sdiodev->sbwad) {
149                 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
150                         return 0xFFFFFFFF;
151
152                 sdiodev->sbwad = bar0;
153         }
154
155         addr &= SBSDIO_SB_OFT_ADDR_MASK;
156         if (size == 4)
157                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
158
159         status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
160                                           addr, &word, size);
161
162         sdiodev->regfail = (status != 0);
163
164         brcmf_dbg(INFO, "u32data = 0x%x\n", word);
165
166         /* if ok, return appropriately masked word */
167         if (status == 0) {
168                 switch (size) {
169                 case sizeof(u8):
170                         return word & 0xff;
171                 case sizeof(u16):
172                         return word & 0xffff;
173                 case sizeof(u32):
174                         return word;
175                 default:
176                         sdiodev->regfail = true;
177
178                 }
179         }
180
181         /* otherwise, bad sdio access or invalid size */
182         brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
183         return 0xFFFFFFFF;
184 }
185
186 u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
187                            u32 data)
188 {
189         int status;
190         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
191         int err = 0;
192
193         brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
194                   addr, size * 8, data);
195
196         if (bar0 != sdiodev->sbwad) {
197                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
198                 if (err)
199                         return err;
200
201                 sdiodev->sbwad = bar0;
202         }
203
204         addr &= SBSDIO_SB_OFT_ADDR_MASK;
205         if (size == 4)
206                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
207         status =
208             brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
209                                      addr, &data, size);
210         sdiodev->regfail = (status != 0);
211
212         if (status == 0)
213                 return 0;
214
215         brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
216                   data, addr, size);
217         return 0xFFFFFFFF;
218 }
219
220 bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
221 {
222         return sdiodev->regfail;
223 }
224
225 int
226 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
227                       uint flags,
228                       u8 *buf, uint nbytes, struct sk_buff *pkt)
229 {
230         int status;
231         uint incr_fix;
232         uint width;
233         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
234         int err = 0;
235
236         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
237
238         /* Async not implemented yet */
239         if (flags & SDIO_REQ_ASYNC)
240                 return -ENOTSUPP;
241
242         if (bar0 != sdiodev->sbwad) {
243                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
244                 if (err)
245                         return err;
246
247                 sdiodev->sbwad = bar0;
248         }
249
250         addr &= SBSDIO_SB_OFT_ADDR_MASK;
251
252         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
253         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
254         if (width == 4)
255                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
256
257         status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
258                                             fn, addr, width, nbytes, buf, pkt);
259
260         return status;
261 }
262
263 int
264 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
265                       uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt)
266 {
267         uint incr_fix;
268         uint width;
269         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
270         int err = 0;
271
272         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
273
274         /* Async not implemented yet */
275         if (flags & SDIO_REQ_ASYNC)
276                 return -ENOTSUPP;
277
278         if (bar0 != sdiodev->sbwad) {
279                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
280                 if (err)
281                         return err;
282
283                 sdiodev->sbwad = bar0;
284         }
285
286         addr &= SBSDIO_SB_OFT_ADDR_MASK;
287
288         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
289         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
290         if (width == 4)
291                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
292
293         return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
294                                           addr, width, nbytes, buf, pkt);
295 }
296
297 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
298                         u8 *buf, uint nbytes)
299 {
300         addr &= SBSDIO_SB_OFT_ADDR_MASK;
301         addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
302
303         return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
304                 (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
305                 addr, 4, nbytes, buf, NULL);
306 }
307
308 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
309 {
310         char t_func = (char)fn;
311         brcmf_dbg(TRACE, "Enter\n");
312
313         /* issue abort cmd52 command through F0 */
314         brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
315                                  SDIO_CCCR_ABORT, &t_func);
316
317         brcmf_dbg(TRACE, "Exit\n");
318         return 0;
319 }
320
321 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
322 {
323         u32 regs = 0;
324         int ret = 0;
325
326         ret = brcmf_sdioh_attach(sdiodev);
327         if (ret)
328                 goto out;
329
330         regs = SI_ENUM_BASE;
331
332         /* Report the BAR, to fix if needed */
333         sdiodev->sbwad = SI_ENUM_BASE;
334
335         /* try to attach to the target device */
336         sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
337         if (!sdiodev->bus) {
338                 brcmf_dbg(ERROR, "device attach failed\n");
339                 ret = -ENODEV;
340                 goto out;
341         }
342
343 out:
344         if (ret)
345                 brcmf_sdio_remove(sdiodev);
346
347         return ret;
348 }
349 EXPORT_SYMBOL(brcmf_sdio_probe);
350
351 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
352 {
353         if (sdiodev->bus) {
354                 brcmf_sdbrcm_disconnect(sdiodev->bus);
355                 sdiodev->bus = NULL;
356         }
357
358         brcmf_sdioh_detach(sdiodev);
359
360         sdiodev->sbwad = 0;
361
362         return 0;
363 }
364 EXPORT_SYMBOL(brcmf_sdio_remove);
365
366 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
367 {
368         if (enable)
369                 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
370         else
371                 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
372 }