Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac802...
[sfrench/cifs-2.6.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/pci.h>
21 #include <linux/pci_ids.h>
22 #include <linux/sched.h>
23 #include <linux/completion.h>
24 #include <linux/scatterlist.h>
25 #include <linux/mmc/sdio.h>
26 #include <linux/mmc/sdio_func.h>
27 #include <linux/mmc/card.h>
28 #include <linux/platform_data/brcmfmac-sdio.h>
29
30 #include <defs.h>
31 #include <brcm_hw_ids.h>
32 #include <brcmu_utils.h>
33 #include <brcmu_wifi.h>
34 #include <soc.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
42 static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
43 {
44         struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
45         struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
46
47         brcmf_dbg(INTR, "OOB intr triggered\n");
48
49         /* out-of-band interrupt is level-triggered which won't
50          * be cleared until dpc
51          */
52         if (sdiodev->irq_en) {
53                 disable_irq_nosync(irq);
54                 sdiodev->irq_en = false;
55         }
56
57         brcmf_sdbrcm_isr(sdiodev->bus);
58
59         return IRQ_HANDLED;
60 }
61
62 static void brcmf_sdio_ib_irqhandler(struct sdio_func *func)
63 {
64         struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
65         struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
66
67         brcmf_dbg(INTR, "IB intr triggered\n");
68
69         brcmf_sdbrcm_isr(sdiodev->bus);
70 }
71
72 /* dummy handler for SDIO function 2 interrupt */
73 static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
74 {
75 }
76
77 int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
78 {
79         int ret = 0;
80         u8 data;
81         unsigned long flags;
82
83         if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
84                 brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
85                           sdiodev->pdata->oob_irq_nr);
86                 ret = request_irq(sdiodev->pdata->oob_irq_nr,
87                                   brcmf_sdio_oob_irqhandler,
88                                   sdiodev->pdata->oob_irq_flags,
89                                   "brcmf_oob_intr",
90                                   &sdiodev->func[1]->dev);
91                 if (ret != 0) {
92                         brcmf_err("request_irq failed %d\n", ret);
93                         return ret;
94                 }
95                 sdiodev->oob_irq_requested = true;
96                 spin_lock_init(&sdiodev->irq_en_lock);
97                 spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
98                 sdiodev->irq_en = true;
99                 spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
100
101                 ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr);
102                 if (ret != 0) {
103                         brcmf_err("enable_irq_wake failed %d\n", ret);
104                         return ret;
105                 }
106                 sdiodev->irq_wake = true;
107
108                 sdio_claim_host(sdiodev->func[1]);
109
110                 /* must configure SDIO_CCCR_IENx to enable irq */
111                 data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
112                 data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
113                 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
114
115                 /* redirect, configure and enable io for interrupt signal */
116                 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
117                 if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
118                         data |= SDIO_SEPINT_ACT_HI;
119                 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
120
121                 sdio_release_host(sdiodev->func[1]);
122         } else {
123                 brcmf_dbg(SDIO, "Entering\n");
124                 sdio_claim_host(sdiodev->func[1]);
125                 sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler);
126                 sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
127                 sdio_release_host(sdiodev->func[1]);
128         }
129
130         return 0;
131 }
132
133 int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
134 {
135         brcmf_dbg(SDIO, "Entering\n");
136
137         if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
138                 sdio_claim_host(sdiodev->func[1]);
139                 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
140                 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
141                 sdio_release_host(sdiodev->func[1]);
142
143                 if (sdiodev->oob_irq_requested) {
144                         sdiodev->oob_irq_requested = false;
145                         if (sdiodev->irq_wake) {
146                                 disable_irq_wake(sdiodev->pdata->oob_irq_nr);
147                                 sdiodev->irq_wake = false;
148                         }
149                         free_irq(sdiodev->pdata->oob_irq_nr,
150                                  &sdiodev->func[1]->dev);
151                         sdiodev->irq_en = false;
152                 }
153         } else {
154                 sdio_claim_host(sdiodev->func[1]);
155                 sdio_release_irq(sdiodev->func[2]);
156                 sdio_release_irq(sdiodev->func[1]);
157                 sdio_release_host(sdiodev->func[1]);
158         }
159
160         return 0;
161 }
162
163 static int
164 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
165 {
166         int err = 0, i;
167         u8 addr[3];
168         s32 retry;
169
170         addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
171         addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
172         addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
173
174         for (i = 0; i < 3; i++) {
175                 retry = 0;
176                 do {
177                         if (retry)
178                                 usleep_range(1000, 2000);
179                         err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE,
180                                         SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i,
181                                         &addr[i]);
182                 } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
183
184                 if (err) {
185                         brcmf_err("failed at addr:0x%0x\n",
186                                   SBSDIO_FUNC1_SBADDRLOW + i);
187                         break;
188                 }
189         }
190
191         return err;
192 }
193
194 static int
195 brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
196 {
197         uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
198         int err = 0;
199
200         if (bar0 != sdiodev->sbwad) {
201                 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
202                 if (err)
203                         return err;
204
205                 sdiodev->sbwad = bar0;
206         }
207
208         *addr &= SBSDIO_SB_OFT_ADDR_MASK;
209
210         if (width == 4)
211                 *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
212
213         return 0;
214 }
215
216 int
217 brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
218                         void *data, bool write)
219 {
220         u8 func_num, reg_size;
221         s32 retry = 0;
222         int ret;
223
224         /*
225          * figure out how to read the register based on address range
226          * 0x00 ~ 0x7FF: function 0 CCCR and FBR
227          * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
228          * The rest: function 1 silicon backplane core registers
229          */
230         if ((addr & ~REG_F0_REG_MASK) == 0) {
231                 func_num = SDIO_FUNC_0;
232                 reg_size = 1;
233         } else if ((addr & ~REG_F1_MISC_MASK) == 0) {
234                 func_num = SDIO_FUNC_1;
235                 reg_size = 1;
236         } else {
237                 func_num = SDIO_FUNC_1;
238                 reg_size = 4;
239
240                 ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
241                 if (ret)
242                         goto done;
243         }
244
245         do {
246                 if (!write)
247                         memset(data, 0, reg_size);
248                 if (retry)      /* wait for 1 ms till bus get settled down */
249                         usleep_range(1000, 2000);
250                 if (reg_size == 1)
251                         ret = brcmf_sdioh_request_byte(sdiodev, write,
252                                                        func_num, addr, data);
253                 else
254                         ret = brcmf_sdioh_request_word(sdiodev, write,
255                                                        func_num, addr, data, 4);
256         } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
257
258 done:
259         if (ret != 0)
260                 brcmf_err("failed with %d\n", ret);
261
262         return ret;
263 }
264
265 u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
266 {
267         u8 data;
268         int retval;
269
270         brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
271         retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
272         brcmf_dbg(SDIO, "data:0x%02x\n", data);
273
274         if (ret)
275                 *ret = retval;
276
277         return data;
278 }
279
280 u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
281 {
282         u32 data;
283         int retval;
284
285         brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
286         retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
287         brcmf_dbg(SDIO, "data:0x%08x\n", data);
288
289         if (ret)
290                 *ret = retval;
291
292         return data;
293 }
294
295 void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
296                       u8 data, int *ret)
297 {
298         int retval;
299
300         brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
301         retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
302
303         if (ret)
304                 *ret = retval;
305 }
306
307 void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
308                       u32 data, int *ret)
309 {
310         int retval;
311
312         brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
313         retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
314
315         if (ret)
316                 *ret = retval;
317 }
318
319 static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
320                              bool write, u32 addr, struct sk_buff *pkt)
321 {
322         unsigned int req_sz;
323
324         brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
325         if (brcmf_pm_resume_error(sdiodev))
326                 return -EIO;
327
328         /* Single skb use the standard mmc interface */
329         req_sz = pkt->len + 3;
330         req_sz &= (uint)~3;
331
332         if (write)
333                 return sdio_memcpy_toio(sdiodev->func[fn], addr,
334                                         ((u8 *)(pkt->data)),
335                                         req_sz);
336         else if (fn == 1)
337                 return sdio_memcpy_fromio(sdiodev->func[fn],
338                                           ((u8 *)(pkt->data)),
339                                           addr, req_sz);
340         else
341                 /* function 2 read is FIFO operation */
342                 return sdio_readsb(sdiodev->func[fn],
343                                    ((u8 *)(pkt->data)), addr,
344                                    req_sz);
345 }
346
347 /**
348  * brcmf_sdio_sglist_rw - SDIO interface function for block data access
349  * @sdiodev: brcmfmac sdio device
350  * @fn: SDIO function number
351  * @write: direction flag
352  * @addr: dongle memory address as source/destination
353  * @pkt: skb pointer
354  *
355  * This function takes the respbonsibility as the interface function to MMC
356  * stack for block data access. It assumes that the skb passed down by the
357  * caller has already been padded and aligned.
358  */
359 static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
360                                 bool write, u32 addr,
361                                 struct sk_buff_head *pktlist)
362 {
363         unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
364         unsigned int max_req_sz, orig_offset, dst_offset;
365         unsigned short max_seg_cnt, seg_sz;
366         unsigned char *pkt_data, *orig_data, *dst_data;
367         struct sk_buff *pkt_next = NULL, *local_pkt_next;
368         struct sk_buff_head local_list, *target_list;
369         struct mmc_request mmc_req;
370         struct mmc_command mmc_cmd;
371         struct mmc_data mmc_dat;
372         struct sg_table st;
373         struct scatterlist *sgl;
374         int ret = 0;
375
376         if (!pktlist->qlen)
377                 return -EINVAL;
378
379         brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
380         if (brcmf_pm_resume_error(sdiodev))
381                 return -EIO;
382
383         target_list = pktlist;
384         /* for host with broken sg support, prepare a page aligned list */
385         __skb_queue_head_init(&local_list);
386         if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
387                 req_sz = 0;
388                 skb_queue_walk(pktlist, pkt_next)
389                         req_sz += pkt_next->len;
390                 req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize);
391                 while (req_sz > PAGE_SIZE) {
392                         pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
393                         if (pkt_next == NULL) {
394                                 ret = -ENOMEM;
395                                 goto exit;
396                         }
397                         __skb_queue_tail(&local_list, pkt_next);
398                         req_sz -= PAGE_SIZE;
399                 }
400                 pkt_next = brcmu_pkt_buf_get_skb(req_sz);
401                 if (pkt_next == NULL) {
402                         ret = -ENOMEM;
403                         goto exit;
404                 }
405                 __skb_queue_tail(&local_list, pkt_next);
406                 target_list = &local_list;
407         }
408
409         func_blk_sz = sdiodev->func[fn]->cur_blksize;
410         max_req_sz = sdiodev->max_request_size;
411         max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
412                             target_list->qlen);
413         seg_sz = target_list->qlen;
414         pkt_offset = 0;
415         pkt_next = target_list->next;
416
417         if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) {
418                 ret = -ENOMEM;
419                 goto exit;
420         }
421
422         memset(&mmc_req, 0, sizeof(struct mmc_request));
423         memset(&mmc_cmd, 0, sizeof(struct mmc_command));
424         memset(&mmc_dat, 0, sizeof(struct mmc_data));
425
426         mmc_dat.sg = st.sgl;
427         mmc_dat.blksz = func_blk_sz;
428         mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
429         mmc_cmd.opcode = SD_IO_RW_EXTENDED;
430         mmc_cmd.arg = write ? 1<<31 : 0;        /* write flag  */
431         mmc_cmd.arg |= (fn & 0x7) << 28;        /* SDIO func num */
432         mmc_cmd.arg |= 1<<27;                   /* block mode */
433         /* for function 1 the addr will be incremented */
434         mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
435         mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
436         mmc_req.cmd = &mmc_cmd;
437         mmc_req.data = &mmc_dat;
438
439         while (seg_sz) {
440                 req_sz = 0;
441                 sg_cnt = 0;
442                 sgl = st.sgl;
443                 /* prep sg table */
444                 while (pkt_next != (struct sk_buff *)target_list) {
445                         pkt_data = pkt_next->data + pkt_offset;
446                         sg_data_sz = pkt_next->len - pkt_offset;
447                         if (sg_data_sz > sdiodev->max_segment_size)
448                                 sg_data_sz = sdiodev->max_segment_size;
449                         if (sg_data_sz > max_req_sz - req_sz)
450                                 sg_data_sz = max_req_sz - req_sz;
451
452                         sg_set_buf(sgl, pkt_data, sg_data_sz);
453
454                         sg_cnt++;
455                         sgl = sg_next(sgl);
456                         req_sz += sg_data_sz;
457                         pkt_offset += sg_data_sz;
458                         if (pkt_offset == pkt_next->len) {
459                                 pkt_offset = 0;
460                                 pkt_next = pkt_next->next;
461                         }
462
463                         if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt)
464                                 break;
465                 }
466                 seg_sz -= sg_cnt;
467
468                 if (req_sz % func_blk_sz != 0) {
469                         brcmf_err("sg request length %u is not %u aligned\n",
470                                   req_sz, func_blk_sz);
471                         ret = -ENOTBLK;
472                         goto exit;
473                 }
474
475                 mmc_dat.sg_len = sg_cnt;
476                 mmc_dat.blocks = req_sz / func_blk_sz;
477                 mmc_cmd.arg |= (addr & 0x1FFFF) << 9;   /* address */
478                 mmc_cmd.arg |= mmc_dat.blocks & 0x1FF;  /* block count */
479                 /* incrementing addr for function 1 */
480                 if (fn == 1)
481                         addr += req_sz;
482
483                 mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
484                 mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
485
486                 ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
487                 if (ret != 0) {
488                         brcmf_err("CMD53 sg block %s failed %d\n",
489                                   write ? "write" : "read", ret);
490                         ret = -EIO;
491                         break;
492                 }
493         }
494
495         if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
496                 local_pkt_next = local_list.next;
497                 orig_offset = 0;
498                 skb_queue_walk(pktlist, pkt_next) {
499                         dst_offset = 0;
500                         do {
501                                 req_sz = local_pkt_next->len - orig_offset;
502                                 req_sz = min_t(uint, pkt_next->len - dst_offset,
503                                                req_sz);
504                                 orig_data = local_pkt_next->data + orig_offset;
505                                 dst_data = pkt_next->data + dst_offset;
506                                 memcpy(dst_data, orig_data, req_sz);
507                                 orig_offset += req_sz;
508                                 dst_offset += req_sz;
509                                 if (orig_offset == local_pkt_next->len) {
510                                         orig_offset = 0;
511                                         local_pkt_next = local_pkt_next->next;
512                                 }
513                                 if (dst_offset == pkt_next->len)
514                                         break;
515                         } while (!skb_queue_empty(&local_list));
516                 }
517         }
518
519 exit:
520         sg_free_table(&st);
521         while ((pkt_next = __skb_dequeue(&local_list)) != NULL)
522                 brcmu_pkt_buf_free_skb(pkt_next);
523
524         return ret;
525 }
526
527 int
528 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
529                       uint flags, u8 *buf, uint nbytes)
530 {
531         struct sk_buff *mypkt;
532         int err;
533
534         mypkt = brcmu_pkt_buf_get_skb(nbytes);
535         if (!mypkt) {
536                 brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
537                           nbytes);
538                 return -EIO;
539         }
540
541         err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt);
542         if (!err)
543                 memcpy(buf, mypkt->data, nbytes);
544
545         brcmu_pkt_buf_free_skb(mypkt);
546         return err;
547 }
548
549 int
550 brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
551                       uint flags, struct sk_buff *pkt)
552 {
553         uint width;
554         int err = 0;
555
556         brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
557                   fn, addr, pkt->len);
558
559         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
560         err = brcmf_sdio_addrprep(sdiodev, width, &addr);
561         if (err)
562                 goto done;
563
564         err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt);
565
566 done:
567         return err;
568 }
569
570 int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
571                             uint flags, struct sk_buff_head *pktq, uint totlen)
572 {
573         struct sk_buff *glom_skb;
574         struct sk_buff *skb;
575         uint width;
576         int err = 0;
577
578         brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
579                   fn, addr, pktq->qlen);
580
581         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
582         err = brcmf_sdio_addrprep(sdiodev, width, &addr);
583         if (err)
584                 goto done;
585
586         if (pktq->qlen == 1)
587                 err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next);
588         else if (!sdiodev->sg_support) {
589                 glom_skb = brcmu_pkt_buf_get_skb(totlen);
590                 if (!glom_skb)
591                         return -ENOMEM;
592                 err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb);
593                 if (err)
594                         goto done;
595
596                 skb_queue_walk(pktq, skb) {
597                         memcpy(skb->data, glom_skb->data, skb->len);
598                         skb_pull(glom_skb, skb->len);
599                 }
600         } else
601                 err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
602
603 done:
604         return err;
605 }
606
607 int
608 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
609                       uint flags, u8 *buf, uint nbytes)
610 {
611         struct sk_buff *mypkt;
612         uint width;
613         int err;
614
615         mypkt = brcmu_pkt_buf_get_skb(nbytes);
616         if (!mypkt) {
617                 brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
618                           nbytes);
619                 return -EIO;
620         }
621
622         memcpy(mypkt->data, buf, nbytes);
623
624         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
625         err = brcmf_sdio_addrprep(sdiodev, width, &addr);
626
627         if (!err)
628                 err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
629
630         brcmu_pkt_buf_free_skb(mypkt);
631         return err;
632
633 }
634
635 int
636 brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
637                       uint flags, struct sk_buff_head *pktq)
638 {
639         struct sk_buff *skb;
640         uint width;
641         int err;
642
643         brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
644                   fn, addr, pktq->qlen);
645
646         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
647         err = brcmf_sdio_addrprep(sdiodev, width, &addr);
648         if (err)
649                 return err;
650
651         if (pktq->qlen == 1 || !sdiodev->sg_support)
652                 skb_queue_walk(pktq, skb) {
653                         err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb);
654                         if (err)
655                                 break;
656                 }
657         else
658                 err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
659
660         return err;
661 }
662
663 int
664 brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
665                  u8 *data, uint size)
666 {
667         int bcmerror = 0;
668         struct sk_buff *pkt;
669         u32 sdaddr;
670         uint dsize;
671
672         dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
673         pkt = dev_alloc_skb(dsize);
674         if (!pkt) {
675                 brcmf_err("dev_alloc_skb failed: len %d\n", dsize);
676                 return -EIO;
677         }
678         pkt->priority = 0;
679
680         /* Determine initial transfer parameters */
681         sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
682         if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
683                 dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
684         else
685                 dsize = size;
686
687         sdio_claim_host(sdiodev->func[1]);
688
689         /* Do the transfer(s) */
690         while (size) {
691                 /* Set the backplane window to include the start address */
692                 bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address);
693                 if (bcmerror)
694                         break;
695
696                 brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
697                           write ? "write" : "read", dsize,
698                           sdaddr, address & SBSDIO_SBWINDOW_MASK);
699
700                 sdaddr &= SBSDIO_SB_OFT_ADDR_MASK;
701                 sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
702
703                 skb_put(pkt, dsize);
704                 if (write)
705                         memcpy(pkt->data, data, dsize);
706                 bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
707                                              sdaddr, pkt);
708                 if (bcmerror) {
709                         brcmf_err("membytes transfer failed\n");
710                         break;
711                 }
712                 if (!write)
713                         memcpy(data, pkt->data, dsize);
714                 skb_trim(pkt, dsize);
715
716                 /* Adjust for next transfer (if any) */
717                 size -= dsize;
718                 if (size) {
719                         data += dsize;
720                         address += dsize;
721                         sdaddr = 0;
722                         dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
723                 }
724         }
725
726         dev_kfree_skb(pkt);
727
728         /* Return the window to backplane enumeration space for core access */
729         if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad))
730                 brcmf_err("FAILED to set window back to 0x%x\n",
731                           sdiodev->sbwad);
732
733         sdio_release_host(sdiodev->func[1]);
734
735         return bcmerror;
736 }
737
738 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
739 {
740         char t_func = (char)fn;
741         brcmf_dbg(SDIO, "Enter\n");
742
743         /* issue abort cmd52 command through F0 */
744         brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
745                                  SDIO_CCCR_ABORT, &t_func);
746
747         brcmf_dbg(SDIO, "Exit\n");
748         return 0;
749 }
750
751 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
752 {
753         u32 regs = 0;
754         int ret = 0;
755
756         ret = brcmf_sdioh_attach(sdiodev);
757         if (ret)
758                 goto out;
759
760         regs = SI_ENUM_BASE;
761
762         /* try to attach to the target device */
763         sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
764         if (!sdiodev->bus) {
765                 brcmf_err("device attach failed\n");
766                 ret = -ENODEV;
767                 goto out;
768         }
769
770 out:
771         if (ret)
772                 brcmf_sdio_remove(sdiodev);
773
774         return ret;
775 }
776
777 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
778 {
779         sdiodev->bus_if->state = BRCMF_BUS_DOWN;
780
781         if (sdiodev->bus) {
782                 brcmf_sdbrcm_disconnect(sdiodev->bus);
783                 sdiodev->bus = NULL;
784         }
785
786         brcmf_sdioh_detach(sdiodev);
787
788         sdiodev->sbwad = 0;
789
790         return 0;
791 }
792
793 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
794 {
795         if (enable)
796                 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
797         else
798                 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
799 }