]> Pileus Git - ~andy/linux/blob - drivers/staging/brcm80211/brcmfmac/bcmsdh.c
staging: brcm80211: remove duplicate set sb window address function
[~andy/linux] / 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.h>
25 #include <linux/mmc/sdio_func.h>
26 #include <linux/mmc/card.h>
27
28 #include <defs.h>
29 #include <brcm_hw_ids.h>
30 #include <brcmu_utils.h>
31 #include <brcmu_wifi.h>
32 #include <soc.h>
33 #include "dhd.h"
34 #include "dhd_bus.h"
35 #include "dhd_dbg.h"
36 #include "sdio_host.h"
37
38 #define SDIOH_API_ACCESS_RETRY_LIMIT    2
39
40 #define SDIOH_CMD_TYPE_NORMAL   0       /* Normal command */
41 #define SDIOH_CMD_TYPE_APPEND   1       /* Append command */
42 #define SDIOH_CMD_TYPE_CUTTHRU  2       /* Cut-through command */
43
44 #define SDIOH_DATA_PIO          0       /* PIO mode */
45 #define SDIOH_DATA_DMA          1       /* DMA mode */
46
47 /* Module parameters specific to each host-controller driver */
48
49 module_param(sd_f2_blocksize, int, 0);
50
51 /* IOVar table */
52 enum {
53         IOV_MSGLEVEL = 1,
54         IOV_DEVREG,
55         IOV_HCIREGS,
56         IOV_RXCHAIN
57 };
58
59 const struct brcmu_iovar sdioh_iovars[] = {
60         {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
61         ,
62         {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
63         ,
64         {NULL, 0, 0, 0, 0}
65 };
66
67 int
68 brcmf_sdcard_iovar_op(struct brcmf_sdio_dev *sdiodev, const char *name,
69                 void *params, int plen, void *arg, int len, bool set)
70 {
71         const struct brcmu_iovar *vi = NULL;
72         int bcmerror = 0;
73         int val_size;
74         s32 int_val = 0;
75         bool bool_val;
76         u32 actionid;
77
78         if (name == NULL || len < 0)
79                 return -EINVAL;
80
81         /* Set does not take qualifiers */
82         if (set && (params || plen))
83                 return -EINVAL;
84
85         /* Get must have return space;*/
86         if (!set && !(arg && len))
87                 return -EINVAL;
88
89         brcmf_dbg(TRACE, "Enter (%s %s)\n", set ? "set" : "get", 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_request_byte(sdiodev, SDIOH_READ,
133                                         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_request_byte(sdiodev, SDIOH_WRITE,
150                                         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_dbg(TRACE, "***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_dbg(TRACE, "Entering\n");
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_dbg(TRACE, "Entering\n");
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 = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
212                                                   addr, (u8 *) &data);
213         } while (status != 0
214                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
215         if (err)
216                 *err = status;
217
218         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
219                   fnc_num, addr, data);
220
221         return data;
222 }
223
224 void
225 brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
226                        u8 data, int *err)
227 {
228         int status;
229         s32 retry = 0;
230
231         do {
232                 if (retry)      /* wait for 1 ms till bus get settled down */
233                         udelay(1000);
234                 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
235                                                   addr, (u8 *) &data);
236         } while (status != 0
237                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
238         if (err)
239                 *err = status;
240
241         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
242                   fnc_num, addr, data);
243 }
244
245 int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, u8 * cis,
246                           uint length)
247 {
248         int status;
249
250         u8 *tmp_buf, *tmp_ptr;
251         u8 *ptr;
252         bool ascii = func & ~0xf;
253         func &= 0x7;
254
255         status = brcmf_sdioh_cis_read(sdiodev, func, cis, length);
256
257         if (ascii) {
258                 /* Move binary bits to tmp and format them
259                          into the provided buffer. */
260                 tmp_buf = kmalloc(length, GFP_ATOMIC);
261                 if (tmp_buf == NULL) {
262                         brcmf_dbg(ERROR, "out of memory\n");
263                         return -ENOMEM;
264                 }
265                 memcpy(tmp_buf, cis, length);
266                 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
267                      tmp_ptr++) {
268                         ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
269                         if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
270                                 ptr += sprintf((char *)ptr, "\n");
271                 }
272                 kfree(tmp_buf);
273         }
274
275         return status;
276 }
277
278 int
279 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
280 {
281         int err = 0;
282         brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
283                          (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
284         if (!err)
285                 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
286                                        SBSDIO_FUNC1_SBADDRMID,
287                                        (address >> 16) & SBSDIO_SBADDRMID_MASK,
288                                        &err);
289         if (!err)
290                 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
291                                        SBSDIO_FUNC1_SBADDRHIGH,
292                                        (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
293                                        &err);
294
295         return err;
296 }
297
298 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
299 {
300         int status;
301         u32 word = 0;
302         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
303
304         brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
305
306         if (bar0 != sdiodev->sbwad) {
307                 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
308                         return 0xFFFFFFFF;
309
310                 sdiodev->sbwad = bar0;
311         }
312
313         addr &= SBSDIO_SB_OFT_ADDR_MASK;
314         if (size == 4)
315                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
316
317         status = brcmf_sdioh_request_word(sdiodev, SDIOH_CMD_TYPE_NORMAL,
318                                     SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
319
320         sdiodev->regfail = (status != 0);
321
322         brcmf_dbg(INFO, "u32data = 0x%x\n", word);
323
324         /* if ok, return appropriately masked word */
325         if (status == 0) {
326                 switch (size) {
327                 case sizeof(u8):
328                         return word & 0xff;
329                 case sizeof(u16):
330                         return word & 0xffff;
331                 case sizeof(u32):
332                         return word;
333                 default:
334                         sdiodev->regfail = true;
335
336                 }
337         }
338
339         /* otherwise, bad sdio access or invalid size */
340         brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
341         return 0xFFFFFFFF;
342 }
343
344 u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
345                            u32 data)
346 {
347         int status;
348         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
349         int err = 0;
350
351         brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
352                   addr, size * 8, data);
353
354         if (bar0 != sdiodev->sbwad) {
355                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
356                 if (err)
357                         return err;
358
359                 sdiodev->sbwad = bar0;
360         }
361
362         addr &= SBSDIO_SB_OFT_ADDR_MASK;
363         if (size == 4)
364                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
365         status =
366             brcmf_sdioh_request_word(sdiodev, SDIOH_CMD_TYPE_NORMAL,
367                                SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
368         sdiodev->regfail = (status != 0);
369
370         if (status == 0)
371                 return 0;
372
373         brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
374                   data, addr, size);
375         return 0xFFFFFFFF;
376 }
377
378 bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
379 {
380         return sdiodev->regfail;
381 }
382
383 int
384 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
385                       uint flags,
386                       u8 *buf, uint nbytes, struct sk_buff *pkt)
387 {
388         int status;
389         uint incr_fix;
390         uint width;
391         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
392         int err = 0;
393
394         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
395
396         /* Async not implemented yet */
397         if (flags & SDIO_REQ_ASYNC)
398                 return -ENOTSUPP;
399
400         if (bar0 != sdiodev->sbwad) {
401                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
402                 if (err)
403                         return err;
404
405                 sdiodev->sbwad = bar0;
406         }
407
408         addr &= SBSDIO_SB_OFT_ADDR_MASK;
409
410         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
411         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
412         if (width == 4)
413                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
414
415         status = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO,
416                 incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
417
418         return status;
419 }
420
421 int
422 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
423                       uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt)
424 {
425         uint incr_fix;
426         uint width;
427         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
428         int err = 0;
429
430         brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
431
432         /* Async not implemented yet */
433         if (flags & SDIO_REQ_ASYNC)
434                 return -ENOTSUPP;
435
436         if (bar0 != sdiodev->sbwad) {
437                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
438                 if (err)
439                         return err;
440
441                 sdiodev->sbwad = bar0;
442         }
443
444         addr &= SBSDIO_SB_OFT_ADDR_MASK;
445
446         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
447         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
448         if (width == 4)
449                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
450
451         return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO,
452                 incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
453 }
454
455 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
456                         u8 *buf, uint nbytes)
457 {
458         addr &= SBSDIO_SB_OFT_ADDR_MASK;
459         addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
460
461         return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO,
462                 SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
463                 addr, 4, nbytes, buf, NULL);
464 }
465
466 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
467 {
468         char t_func = (char)fn;
469         brcmf_dbg(TRACE, "Enter\n");
470
471         /* issue abort cmd52 command through F0 */
472         brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
473                                  SDIO_CCCR_ABORT, &t_func);
474
475         brcmf_dbg(TRACE, "Exit\n");
476         return 0;
477 }
478
479 u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_dev *sdiodev)
480 {
481         return sdiodev->sbwad;
482 }
483
484 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
485 {
486         u32 regs = 0;
487         int ret = 0;
488
489         ret = brcmf_sdioh_attach(sdiodev);
490         if (ret)
491                 goto out;
492
493         regs = SI_ENUM_BASE;
494
495         /* Report the BAR, to fix if needed */
496         sdiodev->sbwad = SI_ENUM_BASE;
497
498         /* try to attach to the target device */
499         sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
500         if (!sdiodev->bus) {
501                 brcmf_dbg(ERROR, "device attach failed\n");
502                 ret = -ENODEV;
503                 goto out;
504         }
505
506 out:
507         if (ret)
508                 brcmf_sdio_remove(sdiodev);
509
510         return ret;
511 }
512 EXPORT_SYMBOL(brcmf_sdio_probe);
513
514 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
515 {
516         if (sdiodev->bus) {
517                 brcmf_sdbrcm_disconnect(sdiodev->bus);
518                 sdiodev->bus = NULL;
519         }
520
521         brcmf_sdioh_detach(sdiodev);
522
523         sdiodev->sbwad = 0;
524
525         return 0;
526 }
527 EXPORT_SYMBOL(brcmf_sdio_remove);
528
529 int brcmf_sdio_register(void)
530 {
531         return brcmf_sdio_function_init();
532 }
533
534 void brcmf_sdio_unregister(void)
535 {
536         brcmf_sdio_function_cleanup();
537 }
538
539 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
540 {
541         if (enable)
542                 brcmf_sdbrcm_wd_timer(sdiodev->bus, brcmf_watchdog_ms);
543         else
544                 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
545 }