|
@@ -47,6 +47,12 @@
|
|
|
|
|
|
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
|
|
|
|
|
|
+#define SDIO_VENDOR_ID_BROADCOM 0x02d0
|
|
|
+
|
|
|
+#define DMA_ALIGN_MASK 0x03
|
|
|
+
|
|
|
+#define SDIO_FUNC1_BLOCKSIZE 64
|
|
|
+#define SDIO_FUNC2_BLOCKSIZE 512
|
|
|
|
|
|
static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
|
|
|
{
|
|
@@ -83,6 +89,25 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+static bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
|
|
|
+{
|
|
|
+ bool is_err = false;
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+ is_err = atomic_read(&sdiodev->suspend);
|
|
|
+#endif
|
|
|
+ return is_err;
|
|
|
+}
|
|
|
+
|
|
|
+static void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
|
|
|
+ wait_queue_head_t *wq)
|
|
|
+{
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+ int retry = 0;
|
|
|
+ while (atomic_read(&sdiodev->suspend) && retry++ != 30)
|
|
|
+ wait_event_timeout(*wq, false, HZ/100);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
|
|
|
{
|
|
|
int ret = 0;
|
|
@@ -169,6 +194,144 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
|
|
|
+ uint regaddr, u8 *byte)
|
|
|
+{
|
|
|
+ struct sdio_func *sdfunc = sdiodev->func[0];
|
|
|
+ int err_ret;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Can only directly write to some F0 registers.
|
|
|
+ * Handle F2 enable/disable and Abort command
|
|
|
+ * as a special case.
|
|
|
+ */
|
|
|
+ if (regaddr == SDIO_CCCR_IOEx) {
|
|
|
+ sdfunc = sdiodev->func[2];
|
|
|
+ if (sdfunc) {
|
|
|
+ if (*byte & SDIO_FUNC_ENABLE_2) {
|
|
|
+ /* Enable Function 2 */
|
|
|
+ err_ret = sdio_enable_func(sdfunc);
|
|
|
+ if (err_ret)
|
|
|
+ brcmf_err("enable F2 failed:%d\n",
|
|
|
+ err_ret);
|
|
|
+ } else {
|
|
|
+ /* Disable Function 2 */
|
|
|
+ err_ret = sdio_disable_func(sdfunc);
|
|
|
+ if (err_ret)
|
|
|
+ brcmf_err("Disable F2 failed:%d\n",
|
|
|
+ err_ret);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ err_ret = -ENOENT;
|
|
|
+ }
|
|
|
+ } else if ((regaddr == SDIO_CCCR_ABORT) ||
|
|
|
+ (regaddr == SDIO_CCCR_IENx)) {
|
|
|
+ sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!sdfunc)
|
|
|
+ return -ENOMEM;
|
|
|
+ sdfunc->num = 0;
|
|
|
+ sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
|
|
|
+ kfree(sdfunc);
|
|
|
+ } else if (regaddr < 0xF0) {
|
|
|
+ brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr);
|
|
|
+ err_ret = -EPERM;
|
|
|
+ } else {
|
|
|
+ sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err_ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw,
|
|
|
+ uint func, uint regaddr, u8 *byte)
|
|
|
+{
|
|
|
+ int err_ret;
|
|
|
+
|
|
|
+ brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
|
|
|
+
|
|
|
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
|
|
|
+ if (brcmf_pm_resume_error(sdiodev))
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ if (rw && func == 0) {
|
|
|
+ /* handle F0 separately */
|
|
|
+ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
|
|
|
+ } else {
|
|
|
+ if (rw) /* CMD52 Write */
|
|
|
+ sdio_writeb(sdiodev->func[func], *byte, regaddr,
|
|
|
+ &err_ret);
|
|
|
+ else if (func == 0) {
|
|
|
+ *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
|
|
|
+ &err_ret);
|
|
|
+ } else {
|
|
|
+ *byte = sdio_readb(sdiodev->func[func], regaddr,
|
|
|
+ &err_ret);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (err_ret) {
|
|
|
+ /*
|
|
|
+ * SleepCSR register access can fail when
|
|
|
+ * waking up the device so reduce this noise
|
|
|
+ * in the logs.
|
|
|
+ */
|
|
|
+ if (regaddr != SBSDIO_FUNC1_SLEEPCSR)
|
|
|
+ brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
|
|
|
+ rw ? "write" : "read", func, regaddr, *byte,
|
|
|
+ err_ret);
|
|
|
+ else
|
|
|
+ brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
|
|
|
+ rw ? "write" : "read", func, regaddr, *byte,
|
|
|
+ err_ret);
|
|
|
+ }
|
|
|
+ return err_ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw,
|
|
|
+ uint func, uint addr, u32 *word,
|
|
|
+ uint nbytes)
|
|
|
+{
|
|
|
+ int err_ret = -EIO;
|
|
|
+
|
|
|
+ if (func == 0) {
|
|
|
+ brcmf_err("Only CMD52 allowed to F0\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
|
|
|
+ rw, func, addr, nbytes);
|
|
|
+
|
|
|
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
|
|
|
+ if (brcmf_pm_resume_error(sdiodev))
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ if (rw) { /* CMD52 Write */
|
|
|
+ if (nbytes == 4)
|
|
|
+ sdio_writel(sdiodev->func[func], *word, addr,
|
|
|
+ &err_ret);
|
|
|
+ else if (nbytes == 2)
|
|
|
+ sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
|
|
|
+ addr, &err_ret);
|
|
|
+ else
|
|
|
+ brcmf_err("Invalid nbytes: %d\n", nbytes);
|
|
|
+ } else { /* CMD52 Read */
|
|
|
+ if (nbytes == 4)
|
|
|
+ *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
|
|
|
+ else if (nbytes == 2)
|
|
|
+ *word = sdio_readw(sdiodev->func[func], addr,
|
|
|
+ &err_ret) & 0xFFFF;
|
|
|
+ else
|
|
|
+ brcmf_err("Invalid nbytes: %d\n", nbytes);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (err_ret)
|
|
|
+ brcmf_err("Failed to %s word, Err: 0x%08x\n",
|
|
|
+ rw ? "write" : "read", err_ret);
|
|
|
+
|
|
|
+ return err_ret;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
|
|
|
{
|
|
@@ -757,237 +920,6 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
|
|
-{
|
|
|
- u32 regs = 0;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- ret = brcmf_sdioh_attach(sdiodev);
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
- regs = SI_ENUM_BASE;
|
|
|
-
|
|
|
- /* try to attach to the target device */
|
|
|
- sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
|
|
|
- if (!sdiodev->bus) {
|
|
|
- brcmf_err("device attach failed\n");
|
|
|
- ret = -ENODEV;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
-out:
|
|
|
- if (ret)
|
|
|
- brcmf_sdio_remove(sdiodev);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
|
|
|
-{
|
|
|
- sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
|
|
-
|
|
|
- if (sdiodev->bus) {
|
|
|
- brcmf_sdbrcm_disconnect(sdiodev->bus);
|
|
|
- sdiodev->bus = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- brcmf_sdioh_detach(sdiodev);
|
|
|
-
|
|
|
- sdiodev->sbwad = 0;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
|
|
|
-{
|
|
|
- if (enable)
|
|
|
- brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
|
|
|
- else
|
|
|
- brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
|
|
|
-}
|
|
|
-
|
|
|
-#define SDIO_VENDOR_ID_BROADCOM 0x02d0
|
|
|
-
|
|
|
-#define DMA_ALIGN_MASK 0x03
|
|
|
-
|
|
|
-#define SDIO_FUNC1_BLOCKSIZE 64
|
|
|
-#define SDIO_FUNC2_BLOCKSIZE 512
|
|
|
-
|
|
|
-/* devices we support, null terminated */
|
|
|
-static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
|
|
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
|
|
|
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
|
|
|
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
|
|
|
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
|
|
|
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
|
|
|
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
|
|
|
- SDIO_DEVICE_ID_BROADCOM_4335_4339)},
|
|
|
- { /* end: all zeroes */ },
|
|
|
-};
|
|
|
-MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
|
|
-
|
|
|
-static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
|
|
|
-
|
|
|
-
|
|
|
-bool
|
|
|
-brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
|
|
|
-{
|
|
|
- bool is_err = false;
|
|
|
-#ifdef CONFIG_PM_SLEEP
|
|
|
- is_err = atomic_read(&sdiodev->suspend);
|
|
|
-#endif
|
|
|
- return is_err;
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
|
|
|
-{
|
|
|
-#ifdef CONFIG_PM_SLEEP
|
|
|
- int retry = 0;
|
|
|
- while (atomic_read(&sdiodev->suspend) && retry++ != 30)
|
|
|
- wait_event_timeout(*wq, false, HZ/100);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
|
|
|
- uint regaddr, u8 *byte)
|
|
|
-{
|
|
|
- struct sdio_func *sdfunc = sdiodev->func[0];
|
|
|
- int err_ret;
|
|
|
-
|
|
|
- /*
|
|
|
- * Can only directly write to some F0 registers.
|
|
|
- * Handle F2 enable/disable and Abort command
|
|
|
- * as a special case.
|
|
|
- */
|
|
|
- if (regaddr == SDIO_CCCR_IOEx) {
|
|
|
- sdfunc = sdiodev->func[2];
|
|
|
- if (sdfunc) {
|
|
|
- if (*byte & SDIO_FUNC_ENABLE_2) {
|
|
|
- /* Enable Function 2 */
|
|
|
- err_ret = sdio_enable_func(sdfunc);
|
|
|
- if (err_ret)
|
|
|
- brcmf_err("enable F2 failed:%d\n",
|
|
|
- err_ret);
|
|
|
- } else {
|
|
|
- /* Disable Function 2 */
|
|
|
- err_ret = sdio_disable_func(sdfunc);
|
|
|
- if (err_ret)
|
|
|
- brcmf_err("Disable F2 failed:%d\n",
|
|
|
- err_ret);
|
|
|
- }
|
|
|
- } else {
|
|
|
- err_ret = -ENOENT;
|
|
|
- }
|
|
|
- } else if ((regaddr == SDIO_CCCR_ABORT) ||
|
|
|
- (regaddr == SDIO_CCCR_IENx)) {
|
|
|
- sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
|
|
|
- GFP_KERNEL);
|
|
|
- if (!sdfunc)
|
|
|
- return -ENOMEM;
|
|
|
- sdfunc->num = 0;
|
|
|
- sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
|
|
|
- kfree(sdfunc);
|
|
|
- } else if (regaddr < 0xF0) {
|
|
|
- brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr);
|
|
|
- err_ret = -EPERM;
|
|
|
- } else {
|
|
|
- sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
|
|
|
- }
|
|
|
-
|
|
|
- return err_ret;
|
|
|
-}
|
|
|
-
|
|
|
-int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
|
|
|
- uint regaddr, u8 *byte)
|
|
|
-{
|
|
|
- int err_ret;
|
|
|
-
|
|
|
- brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
|
|
|
-
|
|
|
- brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
|
|
|
- if (brcmf_pm_resume_error(sdiodev))
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- if (rw && func == 0) {
|
|
|
- /* handle F0 separately */
|
|
|
- err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
|
|
|
- } else {
|
|
|
- if (rw) /* CMD52 Write */
|
|
|
- sdio_writeb(sdiodev->func[func], *byte, regaddr,
|
|
|
- &err_ret);
|
|
|
- else if (func == 0) {
|
|
|
- *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
|
|
|
- &err_ret);
|
|
|
- } else {
|
|
|
- *byte = sdio_readb(sdiodev->func[func], regaddr,
|
|
|
- &err_ret);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (err_ret) {
|
|
|
- /*
|
|
|
- * SleepCSR register access can fail when
|
|
|
- * waking up the device so reduce this noise
|
|
|
- * in the logs.
|
|
|
- */
|
|
|
- if (regaddr != SBSDIO_FUNC1_SLEEPCSR)
|
|
|
- brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
|
|
|
- rw ? "write" : "read", func, regaddr, *byte,
|
|
|
- err_ret);
|
|
|
- else
|
|
|
- brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
|
|
|
- rw ? "write" : "read", func, regaddr, *byte,
|
|
|
- err_ret);
|
|
|
- }
|
|
|
- return err_ret;
|
|
|
-}
|
|
|
-
|
|
|
-int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
|
|
|
- uint rw, uint func, uint addr, u32 *word,
|
|
|
- uint nbytes)
|
|
|
-{
|
|
|
- int err_ret = -EIO;
|
|
|
-
|
|
|
- if (func == 0) {
|
|
|
- brcmf_err("Only CMD52 allowed to F0\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
|
|
|
- rw, func, addr, nbytes);
|
|
|
-
|
|
|
- brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
|
|
|
- if (brcmf_pm_resume_error(sdiodev))
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- if (rw) { /* CMD52 Write */
|
|
|
- if (nbytes == 4)
|
|
|
- sdio_writel(sdiodev->func[func], *word, addr,
|
|
|
- &err_ret);
|
|
|
- else if (nbytes == 2)
|
|
|
- sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
|
|
|
- addr, &err_ret);
|
|
|
- else
|
|
|
- brcmf_err("Invalid nbytes: %d\n", nbytes);
|
|
|
- } else { /* CMD52 Read */
|
|
|
- if (nbytes == 4)
|
|
|
- *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
|
|
|
- else if (nbytes == 2)
|
|
|
- *word = sdio_readw(sdiodev->func[func], addr,
|
|
|
- &err_ret) & 0xFFFF;
|
|
|
- else
|
|
|
- brcmf_err("Invalid nbytes: %d\n", nbytes);
|
|
|
- }
|
|
|
-
|
|
|
- if (err_ret)
|
|
|
- brcmf_err("Failed to %s word, Err: 0x%08x\n",
|
|
|
- rw ? "write" : "read", err_ret);
|
|
|
-
|
|
|
- return err_ret;
|
|
|
-}
|
|
|
-
|
|
|
static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
|
|
|
{
|
|
|
/* read 24 bits and return valid 17 bit addr */
|
|
@@ -1042,10 +974,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Public entry points & extern's
|
|
|
- */
|
|
|
-int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
|
|
|
+static int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
|
|
|
{
|
|
|
int err_ret = 0;
|
|
|
struct mmc_host *host;
|
|
@@ -1092,7 +1021,7 @@ out:
|
|
|
return err_ret;
|
|
|
}
|
|
|
|
|
|
-void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
|
|
+static void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
|
|
{
|
|
|
brcmf_dbg(SDIO, "\n");
|
|
|
|
|
@@ -1108,6 +1037,64 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
|
|
|
|
|
|
}
|
|
|
|
|
|
+static int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
|
|
|
+{
|
|
|
+ sdiodev->bus_if->state = BRCMF_BUS_DOWN;
|
|
|
+
|
|
|
+ if (sdiodev->bus) {
|
|
|
+ brcmf_sdbrcm_disconnect(sdiodev->bus);
|
|
|
+ sdiodev->bus = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ brcmf_sdioh_detach(sdiodev);
|
|
|
+
|
|
|
+ sdiodev->sbwad = 0;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
|
|
+{
|
|
|
+ u32 regs = 0;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ ret = brcmf_sdioh_attach(sdiodev);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ regs = SI_ENUM_BASE;
|
|
|
+
|
|
|
+ /* try to attach to the target device */
|
|
|
+ sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
|
|
|
+ if (!sdiodev->bus) {
|
|
|
+ brcmf_err("device attach failed\n");
|
|
|
+ ret = -ENODEV;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
+ if (ret)
|
|
|
+ brcmf_sdio_remove(sdiodev);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/* devices we support, null terminated */
|
|
|
+static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
|
|
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
|
|
|
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
|
|
|
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
|
|
|
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
|
|
|
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
|
|
|
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
|
|
|
+ SDIO_DEVICE_ID_BROADCOM_4335_4339)},
|
|
|
+ { /* end: all zeroes */ },
|
|
|
+};
|
|
|
+MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
|
|
+
|
|
|
+static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
|
|
|
+
|
|
|
+
|
|
|
static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|
|
const struct sdio_device_id *id)
|
|
|
{
|
|
@@ -1201,6 +1188,14 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
+static void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
|
|
|
+{
|
|
|
+ if (enable)
|
|
|
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
|
|
|
+ else
|
|
|
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
|
|
|
+}
|
|
|
+
|
|
|
static int brcmf_sdio_suspend(struct device *dev)
|
|
|
{
|
|
|
mmc_pm_flag_t sdio_flags;
|