forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
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 }
....@@ -3346,20 +3410,45 @@
33463410 return bcmerror;
33473411 }
33483412
3413
+static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
3414
+{
3415
+ if (bus->ci->chip == CY_CC_43012_CHIP_ID)
3416
+ return true;
3417
+ else
3418
+ return false;
3419
+}
3420
+
33493421 static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
33503422 {
33513423 int err = 0;
33523424 u8 val;
3425
+ u8 wakeupctrl;
3426
+ u8 cardcap;
3427
+ u8 chipclkcsr;
33533428
33543429 brcmf_dbg(TRACE, "Enter\n");
3430
+
3431
+ if (brcmf_chip_is_ulp(bus->ci)) {
3432
+ wakeupctrl = SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
3433
+ chipclkcsr = SBSDIO_HT_AVAIL_REQ;
3434
+ } else {
3435
+ wakeupctrl = SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
3436
+ chipclkcsr = SBSDIO_FORCE_HT;
3437
+ }
3438
+
3439
+ if (brcmf_sdio_aos_no_decode(bus)) {
3440
+ cardcap = SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC;
3441
+ } else {
3442
+ cardcap = (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
3443
+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT);
3444
+ }
33553445
33563446 val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
33573447 if (err) {
33583448 brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
33593449 return;
33603450 }
3361
-
3362
- val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
3451
+ val |= 1 << wakeupctrl;
33633452 brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
33643453 if (err) {
33653454 brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
....@@ -3368,8 +3457,7 @@
33683457
33693458 /* Add CMD14 Support */
33703459 brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
3371
- (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
3372
- SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
3460
+ cardcap,
33733461 &err);
33743462 if (err) {
33753463 brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
....@@ -3377,7 +3465,7 @@
33773465 }
33783466
33793467 brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
3380
- SBSDIO_FORCE_HT, &err);
3468
+ chipclkcsr, &err);
33813469 if (err) {
33823470 brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
33833471 return;
....@@ -3428,7 +3516,6 @@
34283516 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
34293517 struct brcmf_sdio *bus = sdiodev->bus;
34303518 struct brcmf_core *core = bus->sdio_core;
3431
- uint pad_size;
34323519 u32 value;
34333520 int err;
34343521
....@@ -3469,7 +3556,6 @@
34693556 if (sdiodev->sg_support) {
34703557 bus->txglom = false;
34713558 value = 1;
3472
- pad_size = bus->sdiodev->func2->cur_blksize << 1;
34733559 err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
34743560 &value, sizeof(u32));
34753561 if (err < 0) {
....@@ -3539,7 +3625,7 @@
35393625 }
35403626 }
35413627
3542
-void brcmf_sdio_isr(struct brcmf_sdio *bus)
3628
+void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr)
35433629 {
35443630 brcmf_dbg(TRACE, "Enter\n");
35453631
....@@ -3550,7 +3636,7 @@
35503636
35513637 /* Count the interrupt call */
35523638 bus->sdcnt.intrcount++;
3553
- if (in_interrupt())
3639
+ if (in_isr)
35543640 atomic_set(&bus->ipend, 1);
35553641 else
35563642 if (brcmf_sdio_intr_rstatus(bus)) {
....@@ -4047,6 +4133,35 @@
40474133 return 0;
40484134 }
40494135
4136
+static int brcmf_sdio_bus_reset(struct device *dev)
4137
+{
4138
+ int ret = 0;
4139
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
4140
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
4141
+
4142
+ brcmf_dbg(SDIO, "Enter\n");
4143
+
4144
+ /* start by unregistering irqs */
4145
+ brcmf_sdiod_intr_unregister(sdiodev);
4146
+
4147
+ brcmf_sdiod_remove(sdiodev);
4148
+
4149
+ /* reset the adapter */
4150
+ sdio_claim_host(sdiodev->func1);
4151
+ mmc_hw_reset(sdiodev->func1->card->host);
4152
+ sdio_release_host(sdiodev->func1);
4153
+
4154
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
4155
+
4156
+ ret = brcmf_sdiod_probe(sdiodev);
4157
+ if (ret) {
4158
+ brcmf_err("Failed to probe after sdio device reset: ret %d\n",
4159
+ ret);
4160
+ }
4161
+
4162
+ return ret;
4163
+}
4164
+
40504165 static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
40514166 .stop = brcmf_sdio_bus_stop,
40524167 .preinit = brcmf_sdio_bus_preinit,
....@@ -4058,7 +4173,8 @@
40584173 .get_ramsize = brcmf_sdio_bus_get_ramsize,
40594174 .get_memdump = brcmf_sdio_bus_get_memdump,
40604175 .get_fwname = brcmf_sdio_get_fwname,
4061
- .debugfs_create = brcmf_sdio_debugfs_create
4176
+ .debugfs_create = brcmf_sdio_debugfs_create,
4177
+ .reset = brcmf_sdio_bus_reset
40624178 };
40634179
40644180 #define BRCMF_SDIO_FW_CODE 0
....@@ -4074,7 +4190,7 @@
40744190 const struct firmware *code;
40754191 void *nvram;
40764192 u32 nvram_len;
4077
- u8 saveclk;
4193
+ u8 saveclk, bpreq;
40784194 u8 devctl;
40794195
40804196 brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
....@@ -4108,8 +4224,11 @@
41084224 /* Force clocks on backplane to be sure F2 interrupt propagates */
41094225 saveclk = brcmf_sdiod_readb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR, &err);
41104226 if (!err) {
4227
+ bpreq = saveclk;
4228
+ bpreq |= brcmf_chip_is_ulp(bus->ci) ?
4229
+ SBSDIO_HT_AVAIL_REQ : SBSDIO_FORCE_HT;
41114230 brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
4112
- (saveclk | SBSDIO_FORCE_HT), &err);
4231
+ bpreq, &err);
41134232 }
41144233 if (err) {
41154234 brcmf_err("Failed to force clock for F2: err %d\n", err);
....@@ -4132,7 +4251,7 @@
41324251 bus->hostintmask, NULL);
41334252
41344253 switch (sdiod->func1->device) {
4135
- case SDIO_DEVICE_ID_CYPRESS_4373:
4254
+ case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
41364255 brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
41374256 CY_4373_F2_WATERMARK);
41384257 brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
....@@ -4143,8 +4262,62 @@
41434262 brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
41444263 &err);
41454264 brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4146
- CY_4373_F2_WATERMARK |
4147
- SBSDIO_MESBUSYCTRL_ENAB, &err);
4265
+ CY_4373_F1_MESBUSYCTRL, &err);
4266
+ break;
4267
+ case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012:
4268
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4269
+ CY_43012_F2_WATERMARK);
4270
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4271
+ CY_43012_F2_WATERMARK, &err);
4272
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4273
+ &err);
4274
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4275
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4276
+ &err);
4277
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4278
+ CY_43012_MESBUSYCTRL, &err);
4279
+ break;
4280
+ case SDIO_DEVICE_ID_BROADCOM_4329:
4281
+ case SDIO_DEVICE_ID_BROADCOM_4339:
4282
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4283
+ CY_4339_F2_WATERMARK);
4284
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4285
+ CY_4339_F2_WATERMARK, &err);
4286
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4287
+ &err);
4288
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4289
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4290
+ &err);
4291
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4292
+ CY_4339_MESBUSYCTRL, &err);
4293
+ break;
4294
+ case SDIO_DEVICE_ID_BROADCOM_43455:
4295
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4296
+ CY_43455_F2_WATERMARK);
4297
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4298
+ CY_43455_F2_WATERMARK, &err);
4299
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4300
+ &err);
4301
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4302
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4303
+ &err);
4304
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4305
+ CY_43455_MESBUSYCTRL, &err);
4306
+ break;
4307
+ case SDIO_DEVICE_ID_BROADCOM_4359:
4308
+ case SDIO_DEVICE_ID_BROADCOM_4354:
4309
+ case SDIO_DEVICE_ID_BROADCOM_4356:
4310
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
4311
+ CY_435X_F2_WATERMARK);
4312
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
4313
+ CY_435X_F2_WATERMARK, &err);
4314
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
4315
+ &err);
4316
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
4317
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
4318
+ &err);
4319
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
4320
+ CY_435X_F1_MESBUSYCTRL, &err);
41484321 break;
41494322 default:
41504323 brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
....@@ -4154,7 +4327,7 @@
41544327 } else {
41554328 /* Disable F2 again */
41564329 sdio_disable_func(sdiod->func2);
4157
- goto release;
4330
+ goto checkdied;
41584331 }
41594332
41604333 if (brcmf_chip_sr_capable(bus->ci)) {
....@@ -4166,6 +4339,12 @@
41664339 }
41674340
41684341 if (err == 0) {
4342
+ /* Assign bus interface call back */
4343
+ sdiod->bus_if->dev = sdiod->dev;
4344
+ sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
4345
+ sdiod->bus_if->chip = bus->ci->chip;
4346
+ sdiod->bus_if->chiprev = bus->ci->chiprev;
4347
+
41694348 /* Allow full data communication using DPC from now on. */
41704349 brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
41714350
....@@ -4175,27 +4354,35 @@
41754354 }
41764355
41774356 /* If we didn't come up, turn off backplane clock */
4178
- if (err != 0)
4357
+ if (err != 0) {
41794358 brcmf_sdio_clkctl(bus, CLK_NONE, false);
4359
+ goto checkdied;
4360
+ }
41804361
41814362 sdio_release_host(sdiod->func1);
41824363
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;
4364
+ err = brcmf_alloc(sdiod->dev, sdiod->settings);
4365
+ if (err) {
4366
+ brcmf_err("brcmf_alloc failed\n");
4367
+ goto claim;
4368
+ }
41884369
41894370 /* Attach to the common layer, reserve hdr space */
4190
- err = brcmf_attach(sdiod->dev, sdiod->settings);
4371
+ err = brcmf_attach(sdiod->dev);
41914372 if (err != 0) {
41924373 brcmf_err("brcmf_attach failed\n");
4193
- goto fail;
4374
+ goto free;
41944375 }
41954376
41964377 /* ready */
41974378 return;
41984379
4380
+free:
4381
+ brcmf_free(sdiod->dev);
4382
+claim:
4383
+ sdio_claim_host(sdiod->func1);
4384
+checkdied:
4385
+ brcmf_sdio_checkdied(bus);
41994386 release:
42004387 sdio_release_host(sdiod->func1);
42014388 fail:
....@@ -4222,6 +4409,7 @@
42224409
42234410 fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
42244411 fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
4412
+ fwreq->board_type = bus->sdiodev->settings->board_type;
42254413
42264414 return fwreq;
42274415 }
....@@ -4352,6 +4540,7 @@
43524540 brcmf_sdiod_intr_unregister(bus->sdiodev);
43534541
43544542 brcmf_detach(bus->sdiodev->dev);
4543
+ brcmf_free(bus->sdiodev->dev);
43554544
43564545 cancel_work_sync(&bus->datawork);
43574546 if (bus->brcmf_wq)