hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: ISC
12 /*
23 * 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.
154 */
165
176 #include <linux/types.h>
....@@ -27,6 +16,7 @@
2716 #include <linux/mmc/sdio_ids.h>
2817 #include <linux/mmc/sdio_func.h>
2918 #include <linux/mmc/card.h>
19
+#include <linux/mmc/core.h>
3020 #include <linux/semaphore.h>
3121 #include <linux/firmware.h>
3222 #include <linux/module.h>
....@@ -52,6 +42,22 @@
5242 /* watermark expressed in number of words */
5343 #define DEFAULT_F2_WATERMARK 0x8
5444 #define CY_4373_F2_WATERMARK 0x40
45
+#define CY_4373_F1_MESBUSYCTRL (CY_4373_F2_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB)
46
+#define CY_43012_F2_WATERMARK 0x60
47
+#define CY_43012_MES_WATERMARK 0x50
48
+#define CY_43012_MESBUSYCTRL (CY_43012_MES_WATERMARK | \
49
+ SBSDIO_MESBUSYCTRL_ENAB)
50
+#define CY_4339_F2_WATERMARK 48
51
+#define CY_4339_MES_WATERMARK 80
52
+#define CY_4339_MESBUSYCTRL (CY_4339_MES_WATERMARK | \
53
+ SBSDIO_MESBUSYCTRL_ENAB)
54
+#define CY_43455_F2_WATERMARK 0x60
55
+#define CY_43455_MES_WATERMARK 0x50
56
+#define CY_43455_MESBUSYCTRL (CY_43455_MES_WATERMARK | \
57
+ SBSDIO_MESBUSYCTRL_ENAB)
58
+#define CY_435X_F2_WATERMARK 0x40
59
+#define CY_435X_F1_MESBUSYCTRL (CY_435X_F2_WATERMARK | \
60
+ SBSDIO_MESBUSYCTRL_ENAB)
5561
5662 #ifdef DEBUG
5763
....@@ -323,15 +329,6 @@
323329 #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
324330 #define BRCMF_SDIO_MAX_ACCESS_ERRORS 5
325331
326
-/*
327
- * Conversion of 802.1D priority to precedence level
328
- */
329
-static uint prio2prec(u32 prio)
330
-{
331
- return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ?
332
- (prio^2) : prio;
333
-}
334
-
335332 #ifdef DEBUG
336333 /* Device console log buffer state */
337334 struct brcmf_console {
....@@ -560,7 +557,7 @@
560557 BRCMF_SDIO_FT_SUB,
561558 };
562559
563
-#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
560
+#define SDIOD_DRVSTR_KEY(chip, pmu) (((unsigned int)(chip) << 16) | (pmu))
564561
565562 /* SDIO Pad drive strength to select value mappings */
566563 struct sdiod_drive_str {
....@@ -621,9 +618,12 @@
621618 /* Note the names are not postfixed with a1 for backward compatibility */
622619 BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio");
623620 BRCMF_FW_DEF(43455, "brcmfmac43455-sdio");
621
+BRCMF_FW_DEF(43456, "brcmfmac43456-sdio");
624622 BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");
625623 BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");
624
+BRCMF_FW_DEF(4359, "brcmfmac4359-sdio");
626625 BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
626
+BRCMF_FW_DEF(43012, "brcmfmac43012-sdio");
627627
628628 static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
629629 BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
....@@ -640,11 +640,16 @@
640640 BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
641641 BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
642642 BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
643
- BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
643
+ BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0x00000200, 43456),
644
+ BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455),
644645 BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
645646 BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
646
- BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373)
647
+ BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
648
+ BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
649
+ BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012)
647650 };
651
+
652
+#define TXCTL_CREDITS 2
648653
649654 static void pkt_align(struct sk_buff *p, int len, int align)
650655 {
....@@ -659,8 +664,22 @@
659664 /* To check if there's window offered */
660665 static bool data_ok(struct brcmf_sdio *bus)
661666 {
662
- return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
663
- ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
667
+ u8 tx_rsv = 0;
668
+
669
+ /* Reserve TXCTL_CREDITS credits for txctl when it is ready to send */
670
+ if (bus->ctrl_frame_stat)
671
+ tx_rsv = TXCTL_CREDITS;
672
+
673
+ return (bus->tx_max - bus->tx_seq - tx_rsv) != 0 &&
674
+ ((bus->tx_max - bus->tx_seq - tx_rsv) & 0x80) == 0;
675
+
676
+}
677
+
678
+/* To check if there's window offered */
679
+static bool txctl_ok(struct brcmf_sdio *bus)
680
+{
681
+ return (bus->tx_max - bus->tx_seq) != 0 &&
682
+ ((bus->tx_max - bus->tx_seq) & 0x80) == 0;
664683 }
665684
666685 static int
....@@ -682,6 +701,14 @@
682701 wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
683702 /* 1st KSO write goes to AOS wake up core if device is asleep */
684703 brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
704
+
705
+ /* In case of 43012 chip, the chip could go down immediately after
706
+ * KSO bit is cleared. So the further reads of KSO register could
707
+ * fail. Thereby just bailing out immediately after clearing KSO
708
+ * bit, to avoid polling of KSO bit.
709
+ */
710
+ if (!on && bus->ci->chip == CY_CC_43012_CHIP_ID)
711
+ return err;
685712
686713 if (on) {
687714 /* device WAKEUP through KSO:
....@@ -1090,8 +1117,8 @@
10901117
10911118 /* dongle indicates the firmware has halted/crashed */
10921119 if (hmb_data & HMB_DATA_FWHALT) {
1093
- brcmf_err("mailbox indicates firmware halted\n");
1094
- brcmf_dev_coredump(&sdiod->func1->dev);
1120
+ brcmf_dbg(SDIO, "mailbox indicates firmware halted\n");
1121
+ brcmf_fw_crashed(&sdiod->func1->dev);
10951122 }
10961123
10971124 /* Dongle recomposed rx frames, accept them again */
....@@ -1480,7 +1507,7 @@
14801507 struct sk_buff *pfirst, *pnext;
14811508
14821509 int errcode;
1483
- u8 doff, sfdoff;
1510
+ u8 doff;
14841511
14851512 struct brcmf_sdio_hdrinfo rd_new;
14861513
....@@ -1614,7 +1641,6 @@
16141641
16151642 /* Remove superframe header, remember offset */
16161643 skb_pull(pfirst, rd_new.dat_offset);
1617
- sfdoff = rd_new.dat_offset;
16181644 num = 0;
16191645
16201646 /* Validate all the subframe headers */
....@@ -1678,7 +1704,7 @@
16781704 brcmf_rx_event(bus->sdiodev->dev, pfirst);
16791705 else
16801706 brcmf_rx_frame(bus->sdiodev->dev, pfirst,
1681
- false);
1707
+ false, false);
16821708 bus->sdcnt.rxglompkts++;
16831709 }
16841710
....@@ -2012,7 +2038,7 @@
20122038 brcmf_rx_event(bus->sdiodev->dev, pkt);
20132039 else
20142040 brcmf_rx_frame(bus->sdiodev->dev, pkt,
2015
- false);
2041
+ false, false);
20162042
20172043 /* prepare the descriptor for the next read */
20182044 rd->len = rd->len_nxtfrm << 4;
....@@ -2209,7 +2235,7 @@
22092235 * length of the chain (including padding)
22102236 */
22112237 if (bus->txglom)
2212
- brcmf_sdio_update_hwhdr(pktq->next->data, total_len);
2238
+ brcmf_sdio_update_hwhdr(__skb_peek(pktq)->data, total_len);
22132239 return 0;
22142240 }
22152241
....@@ -2417,6 +2443,14 @@
24172443 return ret;
24182444 }
24192445
2446
+static bool brcmf_chip_is_ulp(struct brcmf_chip *ci)
2447
+{
2448
+ if (ci->chip == CY_CC_43012_CHIP_ID)
2449
+ return true;
2450
+ else
2451
+ return false;
2452
+}
2453
+
24202454 static void brcmf_sdio_bus_stop(struct device *dev)
24212455 {
24222456 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
....@@ -2424,7 +2458,7 @@
24242458 struct brcmf_sdio *bus = sdiodev->bus;
24252459 struct brcmf_core *core = bus->sdio_core;
24262460 u32 local_hostintmask;
2427
- u8 saveclk;
2461
+ u8 saveclk, bpreq;
24282462 int err;
24292463
24302464 brcmf_dbg(TRACE, "Enter\n");
....@@ -2451,9 +2485,14 @@
24512485 /* Force backplane clocks to assure F2 interrupt propagates */
24522486 saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
24532487 &err);
2454
- if (!err)
2455
- brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
2456
- (saveclk | SBSDIO_FORCE_HT), &err);
2488
+ if (!err) {
2489
+ bpreq = saveclk;
2490
+ bpreq |= brcmf_chip_is_ulp(bus->ci) ?
2491
+ SBSDIO_HT_AVAIL_REQ : SBSDIO_FORCE_HT;
2492
+ brcmf_sdiod_writeb(sdiodev,
2493
+ SBSDIO_FUNC1_CHIPCLKCSR,
2494
+ bpreq, &err);
2495
+ }
24572496 if (err)
24582497 brcmf_err("Failed to force clock for F2: err %d\n",
24592498 err);
....@@ -2646,7 +2685,7 @@
26462685 brcmf_sdio_clrintr(bus);
26472686
26482687 if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
2649
- data_ok(bus)) {
2688
+ txctl_ok(bus)) {
26502689 sdio_claim_host(bus->sdiodev->func1);
26512690 if (bus->ctrl_frame_stat) {
26522691 err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
....@@ -2654,6 +2693,9 @@
26542693 bus->ctrl_frame_err = err;
26552694 wmb();
26562695 bus->ctrl_frame_stat = false;
2696
+ if (err)
2697
+ brcmf_err("sdio ctrlframe tx failed err=%d\n",
2698
+ err);
26572699 }
26582700 sdio_release_host(bus->sdiodev->func1);
26592701 brcmf_sdio_wait_event_wakeup(bus);
....@@ -2756,7 +2798,13 @@
27562798 skb_push(pkt, bus->tx_hdrlen);
27572799 /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
27582800
2759
- prec = prio2prec((pkt->priority & PRIOMASK));
2801
+ /* In WLAN, priority is always set by the AP using WMM parameters
2802
+ * and this need not always follow the standard 802.1d priority.
2803
+ * Based on AP WMM config, map from 802.1d priority to corresponding
2804
+ * precedence level.
2805
+ */
2806
+ prec = brcmf_map_prio_to_prec(bus_if->drvr->config,
2807
+ (pkt->priority & PRIOMASK));
27602808
27612809 /* Check for existing queue, current flow-control,
27622810 pending event, or pending clock */
....@@ -2990,21 +3038,35 @@
29903038 if (error < 0)
29913039 return error;
29923040
2993
- seq_printf(seq,
2994
- "dongle trap info: type 0x%x @ epc 0x%08x\n"
2995
- " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
2996
- " lr 0x%08x pc 0x%08x offset 0x%x\n"
2997
- " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
2998
- " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
2999
- le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
3000
- le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
3001
- le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
3002
- le32_to_cpu(tr.pc), sh->trap_addr,
3003
- le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
3004
- le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
3005
- le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
3006
- le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
3007
-
3041
+ if (seq)
3042
+ seq_printf(seq,
3043
+ "dongle trap info: type 0x%x @ epc 0x%08x\n"
3044
+ " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
3045
+ " lr 0x%08x pc 0x%08x offset 0x%x\n"
3046
+ " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
3047
+ " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
3048
+ le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
3049
+ le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
3050
+ le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
3051
+ le32_to_cpu(tr.pc), sh->trap_addr,
3052
+ le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
3053
+ le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
3054
+ le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
3055
+ le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
3056
+ else
3057
+ pr_debug("dongle trap info: type 0x%x @ epc 0x%08x\n"
3058
+ " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
3059
+ " lr 0x%08x pc 0x%08x offset 0x%x\n"
3060
+ " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
3061
+ " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
3062
+ le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
3063
+ le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
3064
+ le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
3065
+ le32_to_cpu(tr.pc), sh->trap_addr,
3066
+ le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
3067
+ le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
3068
+ le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
3069
+ le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
30083070 return 0;
30093071 }
30103072
....@@ -3058,8 +3120,10 @@
30583120 else if (sh.flags & SDPCM_SHARED_ASSERT)
30593121 brcmf_err("assertion in dongle\n");
30603122
3061
- if (sh.flags & SDPCM_SHARED_TRAP)
3123
+ if (sh.flags & SDPCM_SHARED_TRAP) {
30623124 brcmf_err("firmware trap in dongle\n");
3125
+ brcmf_sdio_trap_info(NULL, bus, &sh);
3126
+ }
30633127
30643128 return 0;
30653129 }
....@@ -3337,6 +3401,7 @@
33373401 /* Take arm out of reset */
33383402 if (!brcmf_chip_set_active(bus->ci, rstvec)) {
33393403 brcmf_err("error getting out of ARM core reset\n");
3404
+ bcmerror = -EIO;
33403405 goto err;
33413406 }
33423407
....@@ -3346,20 +3411,45 @@
33463411 return bcmerror;
33473412 }
33483413
3414
+static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
3415
+{
3416
+ if (bus->ci->chip == CY_CC_43012_CHIP_ID)
3417
+ return true;
3418
+ else
3419
+ return false;
3420
+}
3421
+
33493422 static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
33503423 {
33513424 int err = 0;
33523425 u8 val;
3426
+ u8 wakeupctrl;
3427
+ u8 cardcap;
3428
+ u8 chipclkcsr;
33533429
33543430 brcmf_dbg(TRACE, "Enter\n");
3431
+
3432
+ if (brcmf_chip_is_ulp(bus->ci)) {
3433
+ wakeupctrl = SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
3434
+ chipclkcsr = SBSDIO_HT_AVAIL_REQ;
3435
+ } else {
3436
+ wakeupctrl = SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
3437
+ chipclkcsr = SBSDIO_FORCE_HT;
3438
+ }
3439
+
3440
+ if (brcmf_sdio_aos_no_decode(bus)) {
3441
+ cardcap = SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC;
3442
+ } else {
3443
+ cardcap = (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
3444
+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT);
3445
+ }
33553446
33563447 val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
33573448 if (err) {
33583449 brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
33593450 return;
33603451 }
3361
-
3362
- val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
3452
+ val |= 1 << wakeupctrl;
33633453 brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
33643454 if (err) {
33653455 brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
....@@ -3368,8 +3458,7 @@
33683458
33693459 /* Add CMD14 Support */
33703460 brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
3371
- (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
3372
- SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
3461
+ cardcap,
33733462 &err);
33743463 if (err) {
33753464 brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
....@@ -3377,7 +3466,7 @@
33773466 }
33783467
33793468 brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
3380
- SBSDIO_FORCE_HT, &err);
3469
+ chipclkcsr, &err);
33813470 if (err) {
33823471 brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
33833472 return;
....@@ -3428,7 +3517,6 @@
34283517 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
34293518 struct brcmf_sdio *bus = sdiodev->bus;
34303519 struct brcmf_core *core = bus->sdio_core;
3431
- uint pad_size;
34323520 u32 value;
34333521 int err;
34343522
....@@ -3469,7 +3557,6 @@
34693557 if (sdiodev->sg_support) {
34703558 bus->txglom = false;
34713559 value = 1;
3472
- pad_size = bus->sdiodev->func2->cur_blksize << 1;
34733560 err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
34743561 &value, sizeof(u32));
34753562 if (err < 0) {
....@@ -3539,7 +3626,7 @@
35393626 }
35403627 }
35413628
3542
-void brcmf_sdio_isr(struct brcmf_sdio *bus)
3629
+void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr)
35433630 {
35443631 brcmf_dbg(TRACE, "Enter\n");
35453632
....@@ -3550,7 +3637,7 @@
35503637
35513638 /* Count the interrupt call */
35523639 bus->sdcnt.intrcount++;
3553
- if (in_interrupt())
3640
+ if (in_isr)
35543641 atomic_set(&bus->ipend, 1);
35553642 else
35563643 if (brcmf_sdio_intr_rstatus(bus)) {
....@@ -4047,6 +4134,35 @@
40474134 return 0;
40484135 }
40494136
4137
+static int brcmf_sdio_bus_reset(struct device *dev)
4138
+{
4139
+ int ret = 0;
4140
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
4141
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
4142
+
4143
+ brcmf_dbg(SDIO, "Enter\n");
4144
+
4145
+ /* start by unregistering irqs */
4146
+ brcmf_sdiod_intr_unregister(sdiodev);
4147
+
4148
+ brcmf_sdiod_remove(sdiodev);
4149
+
4150
+ /* reset the adapter */
4151
+ sdio_claim_host(sdiodev->func1);
4152
+ mmc_hw_reset(sdiodev->func1->card->host);
4153
+ sdio_release_host(sdiodev->func1);
4154
+
4155
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
4156
+
4157
+ ret = brcmf_sdiod_probe(sdiodev);
4158
+ if (ret) {
4159
+ brcmf_err("Failed to probe after sdio device reset: ret %d\n",
4160
+ ret);
4161
+ }
4162
+
4163
+ return ret;
4164
+}
4165
+
40504166 static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
40514167 .stop = brcmf_sdio_bus_stop,
40524168 .preinit = brcmf_sdio_bus_preinit,
....@@ -4058,7 +4174,8 @@
40584174 .get_ramsize = brcmf_sdio_bus_get_ramsize,
40594175 .get_memdump = brcmf_sdio_bus_get_memdump,
40604176 .get_fwname = brcmf_sdio_get_fwname,
4061
- .debugfs_create = brcmf_sdio_debugfs_create
4177
+ .debugfs_create = brcmf_sdio_debugfs_create,
4178
+ .reset = brcmf_sdio_bus_reset
40624179 };
40634180
40644181 #define BRCMF_SDIO_FW_CODE 0
....@@ -4074,7 +4191,7 @@
40744191 const struct firmware *code;
40754192 void *nvram;
40764193 u32 nvram_len;
4077
- u8 saveclk;
4194
+ u8 saveclk, bpreq;
40784195 u8 devctl;
40794196
40804197 brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
....@@ -4108,8 +4225,11 @@
41084225 /* Force clocks on backplane to be sure F2 interrupt propagates */
41094226 saveclk = brcmf_sdiod_readb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR, &err);
41104227 if (!err) {
4228
+ bpreq = saveclk;
4229
+ bpreq |= brcmf_chip_is_ulp(bus->ci) ?
4230
+ SBSDIO_HT_AVAIL_REQ : SBSDIO_FORCE_HT;
41114231 brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
4112
- (saveclk | SBSDIO_FORCE_HT), &err);
4232
+ bpreq, &err);
41134233 }
41144234 if (err) {
41154235 brcmf_err("Failed to force clock for F2: err %d\n", err);
....@@ -4132,7 +4252,7 @@
41324252 bus->hostintmask, NULL);
41334253
41344254 switch (sdiod->func1->device) {
4135
- case SDIO_DEVICE_ID_CYPRESS_4373:
4255
+ case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
41364256 brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
41374257 CY_4373_F2_WATERMARK);
41384258 brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
....@@ -4143,8 +4263,62 @@
41434263 brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
41444264 &err);
41454265 brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4146
- CY_4373_F2_WATERMARK |
4147
- SBSDIO_MESBUSYCTRL_ENAB, &err);
4266
+ CY_4373_F1_MESBUSYCTRL, &err);
4267
+ break;
4268
+ case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012:
4269
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4270
+ CY_43012_F2_WATERMARK);
4271
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4272
+ CY_43012_F2_WATERMARK, &err);
4273
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4274
+ &err);
4275
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4276
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4277
+ &err);
4278
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4279
+ CY_43012_MESBUSYCTRL, &err);
4280
+ break;
4281
+ case SDIO_DEVICE_ID_BROADCOM_4329:
4282
+ case SDIO_DEVICE_ID_BROADCOM_4339:
4283
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4284
+ CY_4339_F2_WATERMARK);
4285
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4286
+ CY_4339_F2_WATERMARK, &err);
4287
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4288
+ &err);
4289
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4290
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4291
+ &err);
4292
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4293
+ CY_4339_MESBUSYCTRL, &err);
4294
+ break;
4295
+ case SDIO_DEVICE_ID_BROADCOM_43455:
4296
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4297
+ CY_43455_F2_WATERMARK);
4298
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4299
+ CY_43455_F2_WATERMARK, &err);
4300
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4301
+ &err);
4302
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4303
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4304
+ &err);
4305
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4306
+ CY_43455_MESBUSYCTRL, &err);
4307
+ break;
4308
+ case SDIO_DEVICE_ID_BROADCOM_4359:
4309
+ case SDIO_DEVICE_ID_BROADCOM_4354:
4310
+ case SDIO_DEVICE_ID_BROADCOM_4356:
4311
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4312
+ CY_435X_F2_WATERMARK);
4313
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4314
+ CY_435X_F2_WATERMARK, &err);
4315
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4316
+ &err);
4317
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4318
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4319
+ &err);
4320
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4321
+ CY_435X_F1_MESBUSYCTRL, &err);
41484322 break;
41494323 default:
41504324 brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
....@@ -4154,7 +4328,7 @@
41544328 } else {
41554329 /* Disable F2 again */
41564330 sdio_disable_func(sdiod->func2);
4157
- goto release;
4331
+ goto checkdied;
41584332 }
41594333
41604334 if (brcmf_chip_sr_capable(bus->ci)) {
....@@ -4166,6 +4340,12 @@
41664340 }
41674341
41684342 if (err == 0) {
4343
+ /* Assign bus interface call back */
4344
+ sdiod->bus_if->dev = sdiod->dev;
4345
+ sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
4346
+ sdiod->bus_if->chip = bus->ci->chip;
4347
+ sdiod->bus_if->chiprev = bus->ci->chiprev;
4348
+
41694349 /* Allow full data communication using DPC from now on. */
41704350 brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
41714351
....@@ -4175,27 +4355,35 @@
41754355 }
41764356
41774357 /* If we didn't come up, turn off backplane clock */
4178
- if (err != 0)
4358
+ if (err != 0) {
41794359 brcmf_sdio_clkctl(bus, CLK_NONE, false);
4360
+ goto checkdied;
4361
+ }
41804362
41814363 sdio_release_host(sdiod->func1);
41824364
4183
- /* Assign bus interface call back */
4184
- sdiod->bus_if->dev = sdiod->dev;
4185
- sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
4186
- sdiod->bus_if->chip = bus->ci->chip;
4187
- sdiod->bus_if->chiprev = bus->ci->chiprev;
4365
+ err = brcmf_alloc(sdiod->dev, sdiod->settings);
4366
+ if (err) {
4367
+ brcmf_err("brcmf_alloc failed\n");
4368
+ goto claim;
4369
+ }
41884370
41894371 /* Attach to the common layer, reserve hdr space */
4190
- err = brcmf_attach(sdiod->dev, sdiod->settings);
4372
+ err = brcmf_attach(sdiod->dev);
41914373 if (err != 0) {
41924374 brcmf_err("brcmf_attach failed\n");
4193
- goto fail;
4375
+ goto free;
41944376 }
41954377
41964378 /* ready */
41974379 return;
41984380
4381
+free:
4382
+ brcmf_free(sdiod->dev);
4383
+claim:
4384
+ sdio_claim_host(sdiod->func1);
4385
+checkdied:
4386
+ brcmf_sdio_checkdied(bus);
41994387 release:
42004388 sdio_release_host(sdiod->func1);
42014389 fail:
....@@ -4222,6 +4410,7 @@
42224410
42234411 fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
42244412 fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
4413
+ fwreq->board_type = bus->sdiodev->settings->board_type;
42254414
42264415 return fwreq;
42274416 }
....@@ -4352,6 +4541,7 @@
43524541 brcmf_sdiod_intr_unregister(bus->sdiodev);
43534542
43544543 brcmf_detach(bus->sdiodev->dev);
4544
+ brcmf_free(bus->sdiodev->dev);
43554545
43564546 cancel_work_sync(&bus->datawork);
43574547 if (bus->brcmf_wq)