]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/brcm80211/brcmfmac/bcmsdh.c
staging: brcm80211: absorb brcmf_sdioh_interrupt_deregister into brcmf_sdcard_intr_dereg
[mv-sheeva.git] / drivers / staging / 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/pci.h>
21 #include <linux/pci_ids.h>
22 #include <linux/sched.h>
23 #include <linux/completion.h>
24 #include <linux/mmc/sdio_func.h>
25 #include <linux/mmc/card.h>
26
27 #include <defs.h>
28 #include <brcm_hw_ids.h>
29 #include <brcmu_utils.h>
30 #include <brcmu_wifi.h>
31 #include <soc.h>
32 #include "dhd.h"
33 #include "dhd_bus.h"
34 #include "dhd_dbg.h"
35 #include "sdio_host.h"
36
37 #define SDIOH_API_ACCESS_RETRY_LIMIT    2
38
39 #define SDIOH_CMD_TYPE_NORMAL   0       /* Normal command */
40 #define SDIOH_CMD_TYPE_APPEND   1       /* Append command */
41 #define SDIOH_CMD_TYPE_CUTTHRU  2       /* Cut-through command */
42
43 #define SDIOH_DATA_PIO          0       /* PIO mode */
44 #define SDIOH_DATA_DMA          1       /* DMA mode */
45
46 /* Module parameters specific to each host-controller driver */
47
48 module_param(sd_f2_blocksize, int, 0);
49
50 /* IOVar table */
51 enum {
52         IOV_MSGLEVEL = 1,
53         IOV_DEVREG,
54         IOV_HCIREGS,
55         IOV_RXCHAIN
56 };
57
58 const struct brcmu_iovar sdioh_iovars[] = {
59         {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
60         ,
61         {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
62         ,
63         {NULL, 0, 0, 0, 0}
64 };
65
66 int
67 brcmf_sdcard_iovar_op(struct brcmf_sdio_dev *sdiodev, const char *name,
68                 void *params, int plen, void *arg, int len, bool set)
69 {
70         const struct brcmu_iovar *vi = NULL;
71         int bcmerror = 0;
72         int val_size;
73         s32 int_val = 0;
74         bool bool_val;
75         u32 actionid;
76
77         if (name == NULL || len < 0)
78                 return -EINVAL;
79
80         /* Set does not take qualifiers */
81         if (set && (params || plen))
82                 return -EINVAL;
83
84         /* Get must have return space;*/
85         if (!set && !(arg && len))
86                 return -EINVAL;
87
88         BRCMF_TRACE(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
89                   name));
90
91         vi = brcmu_iovar_lookup(sdioh_iovars, name);
92         if (vi == NULL) {
93                 bcmerror = -ENOTSUPP;
94                 goto exit;
95         }
96
97         bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
98         if (bcmerror != 0)
99                 goto exit;
100
101         /* Set up params so get and set can share the convenience variables */
102         if (params == NULL) {
103                 params = arg;
104                 plen = len;
105         }
106
107         if (vi->type == IOVT_VOID)
108                 val_size = 0;
109         else if (vi->type == IOVT_BUFFER)
110                 val_size = len;
111         else
112                 val_size = sizeof(int);
113
114         if (plen >= (int)sizeof(int_val))
115                 memcpy(&int_val, params, sizeof(int_val));
116
117         bool_val = (int_val != 0) ? true : false;
118
119         actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
120         switch (actionid) {
121         case IOV_GVAL(IOV_RXCHAIN):
122                 int_val = false;
123                 memcpy(arg, &int_val, val_size);
124                 break;
125
126         case IOV_GVAL(IOV_DEVREG):
127                 {
128                         struct brcmf_sdreg *sd_ptr =
129                                         (struct brcmf_sdreg *) params;
130                         u8 data = 0;
131
132                         if (brcmf_sdioh_cfg_read
133                             (sdiodev, sd_ptr->func, sd_ptr->offset, &data)) {
134                                 bcmerror = -EIO;
135                                 break;
136                         }
137
138                         int_val = (int)data;
139                         memcpy(arg, &int_val, sizeof(int_val));
140                         break;
141                 }
142
143         case IOV_SVAL(IOV_DEVREG):
144                 {
145                         struct brcmf_sdreg *sd_ptr =
146                                         (struct brcmf_sdreg *) params;
147                         u8 data = (u8) sd_ptr->value;
148
149                         if (brcmf_sdioh_cfg_write
150                             (sdiodev, sd_ptr->func, sd_ptr->offset, &data)) {
151                                 bcmerror = -EIO;
152                                 break;
153                         }
154                         break;
155                 }
156
157         default:
158                 bcmerror = -ENOTSUPP;
159                 break;
160         }
161 exit:
162
163         return bcmerror;
164 }
165
166 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
167 {
168         struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
169
170         BRCMF_TRACE(("brcmf: ***IRQHandler\n"));
171
172         sdio_release_host(func);
173
174         brcmf_sdbrcm_isr(sdiodev->bus);
175
176         sdio_claim_host(func);
177 }
178
179 int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
180 {
181         BRCMF_TRACE(("%s: Entering\n", __func__));
182
183         sdio_claim_host(sdiodev->func[1]);
184         sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
185         sdio_release_host(sdiodev->func[1]);
186
187         return 0;
188 }
189
190 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
191 {
192         BRCMF_TRACE(("%s: Entering\n", __func__));
193
194         sdio_claim_host(sdiodev->func[1]);
195         sdio_release_irq(sdiodev->func[1]);
196         sdio_release_host(sdiodev->func[1]);
197
198         return 0;
199 }
200
201 u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
202                          int *err)
203 {
204         int status;
205         s32 retry = 0;
206         u8 data = 0;
207
208         do {
209                 if (retry)      /* wait for 1 ms till bus get settled down */
210                         udelay(1000);
211                 status =
212                     brcmf_sdioh_cfg_read(sdiodev, fnc_num, addr,
213                                    (u8 *) &data);
214         } while (status != 0
215                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
216         if (err)
217                 *err = status;
218
219         BRCMF_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
220                      __func__, fnc_num, addr, data));
221
222         return data;
223 }
224
225 void
226 brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
227                        u8 data, int *err)
228 {
229         int status;
230         s32 retry = 0;
231
232         do {
233                 if (retry)      /* wait for 1 ms till bus get settled down */
234                         udelay(1000);
235                 status =
236                     brcmf_sdioh_cfg_write(sdiodev, fnc_num, addr,
237                                     (u8 *) &data);
238         } while (status != 0
239                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
240         if (err)
241                 *err = status;
242
243         BRCMF_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
244                      __func__, fnc_num, addr, data));
245 }
246
247 int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, u8 * cis,
248                           uint length)
249 {
250         int status;
251
252         u8 *tmp_buf, *tmp_ptr;
253         u8 *ptr;
254         bool ascii = func & ~0xf;
255         func &= 0x7;
256
257         status = brcmf_sdioh_cis_read(sdiodev, func, cis, length);
258
259         if (ascii) {
260                 /* Move binary bits to tmp and format them
261                          into the provided buffer. */
262                 tmp_buf = kmalloc(length, GFP_ATOMIC);
263                 if (tmp_buf == NULL) {
264                         BRCMF_ERROR(("%s: out of memory\n", __func__));
265                         return -ENOMEM;
266                 }
267                 memcpy(tmp_buf, cis, length);
268                 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
269                      tmp_ptr++) {
270                         ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
271                         if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
272                                 ptr += sprintf((char *)ptr, "\n");
273                 }
274                 kfree(tmp_buf);
275         }
276
277         return status;
278 }
279
280 static int
281 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
282 {
283         int err = 0;
284         brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
285                          (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
286         if (!err)
287                 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
288                                        SBSDIO_FUNC1_SBADDRMID,
289                                        (address >> 16) & SBSDIO_SBADDRMID_MASK,
290                                        &err);
291         if (!err)
292                 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
293                                        SBSDIO_FUNC1_SBADDRHIGH,
294                                        (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
295                                        &err);
296
297         return err;
298 }
299
300 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
301 {
302         int status;
303         u32 word = 0;
304         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
305
306         BRCMF_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
307
308         if (bar0 != sdiodev->sbwad) {
309                 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
310                         return 0xFFFFFFFF;
311
312                 sdiodev->sbwad = bar0;
313         }
314
315         addr &= SBSDIO_SB_OFT_ADDR_MASK;
316         if (size == 4)
317                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
318
319         status = brcmf_sdioh_request_word(sdiodev, SDIOH_CMD_TYPE_NORMAL,
320                                     SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
321
322         sdiodev->regfail = (status != 0);
323
324         BRCMF_INFO(("u32data = 0x%x\n", word));
325
326         /* if ok, return appropriately masked word */
327         if (status == 0) {
328                 switch (size) {
329                 case sizeof(u8):
330                         return word & 0xff;
331                 case sizeof(u16):
332                         return word & 0xffff;
333                 case sizeof(u32):
334                         return word;
335                 default:
336                         sdiodev->regfail = true;
337
338                 }
339         }
340
341         /* otherwise, bad sdio access or invalid size */
342         BRCMF_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
343                       addr, size));
344         return 0xFFFFFFFF;
345 }
346
347 u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
348                            u32 data)
349 {
350         int status;
351         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
352         int err = 0;
353
354         BRCMF_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
355                      __func__, addr, size * 8, data));
356
357         if (bar0 != sdiodev->sbwad) {
358                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
359                 if (err)
360                         return err;
361
362                 sdiodev->sbwad = bar0;
363         }
364
365         addr &= SBSDIO_SB_OFT_ADDR_MASK;
366         if (size == 4)
367                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
368         status =
369             brcmf_sdioh_request_word(sdiodev, SDIOH_CMD_TYPE_NORMAL,
370                                SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
371         sdiodev->regfail = (status != 0);
372
373         if (status == 0)
374                 return 0;
375
376         BRCMF_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
377                       __func__, data, addr, size));
378         return 0xFFFFFFFF;
379 }
380
381 bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
382 {
383         return sdiodev->regfail;
384 }
385
386 int
387 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
388                       uint flags,
389                       u8 *buf, uint nbytes, struct sk_buff *pkt,
390                       void (*complete)(void *handle, int status,
391                                        bool sync_waiting),
392                       void *handle)
393 {
394         int status;
395         uint incr_fix;
396         uint width;
397         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
398         int err = 0;
399
400         BRCMF_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
401                      __func__, fn, addr, nbytes));
402
403         /* Async not implemented yet */
404         if (flags & SDIO_REQ_ASYNC)
405                 return -ENOTSUPP;
406
407         if (bar0 != sdiodev->sbwad) {
408                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
409                 if (err)
410                         return err;
411
412                 sdiodev->sbwad = bar0;
413         }
414
415         addr &= SBSDIO_SB_OFT_ADDR_MASK;
416
417         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
418         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
419         if (width == 4)
420                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
421
422         status = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO,
423                 incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
424
425         return status;
426 }
427
428 int
429 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
430                       uint flags, u8 *buf, uint nbytes, void *pkt,
431                       void (*complete)(void *handle, int status,
432                                        bool sync_waiting),
433                       void *handle)
434 {
435         uint incr_fix;
436         uint width;
437         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
438         int err = 0;
439
440         BRCMF_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
441                      __func__, fn, addr, nbytes));
442
443         /* Async not implemented yet */
444         if (flags & SDIO_REQ_ASYNC)
445                 return -ENOTSUPP;
446
447         if (bar0 != sdiodev->sbwad) {
448                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
449                 if (err)
450                         return err;
451
452                 sdiodev->sbwad = bar0;
453         }
454
455         addr &= SBSDIO_SB_OFT_ADDR_MASK;
456
457         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
458         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
459         if (width == 4)
460                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
461
462         return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO,
463                 incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
464 }
465
466 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
467                         u8 *buf, uint nbytes)
468 {
469         addr &= SBSDIO_SB_OFT_ADDR_MASK;
470         addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
471
472         return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO,
473                 SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
474                 addr, 4, nbytes, buf, NULL);
475 }
476
477 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
478 {
479         return brcmf_sdioh_abort(sdiodev, fn);
480 }
481
482 u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_dev *sdiodev)
483 {
484         return sdiodev->sbwad;
485 }
486
487 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
488 {
489         u32 regs = 0;
490         int ret = 0;
491
492         ret = brcmf_sdioh_attach(sdiodev);
493         if (ret)
494                 goto out;
495
496         regs = SI_ENUM_BASE;
497
498         /* Report the BAR, to fix if needed */
499         sdiodev->sbwad = SI_ENUM_BASE;
500
501         /* try to attach to the target device */
502         sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
503         if (!sdiodev->bus) {
504                 BRCMF_ERROR(("%s: device attach failed\n", __func__));
505                 ret = -ENODEV;
506                 goto out;
507         }
508
509 out:
510         if (ret)
511                 brcmf_sdio_remove(sdiodev);
512
513         return ret;
514 }
515 EXPORT_SYMBOL(brcmf_sdio_probe);
516
517 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
518 {
519         if (sdiodev->bus) {
520                 brcmf_sdbrcm_disconnect(sdiodev->bus);
521                 sdiodev->bus = NULL;
522         }
523
524         brcmf_sdioh_detach(sdiodev);
525
526         sdiodev->sbwad = 0;
527
528         return 0;
529 }
530 EXPORT_SYMBOL(brcmf_sdio_remove);
531
532 int brcmf_sdio_register(void)
533 {
534         return brcmf_sdio_function_init();
535 }
536
537 void brcmf_sdio_unregister(void)
538 {
539         brcmf_sdio_function_cleanup();
540 }
541
542 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
543 {
544         if (enable)
545                 brcmf_sdbrcm_wd_timer(sdiodev->bus, brcmf_watchdog_ms);
546         else
547                 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
548 }