u32 sbwad; /* Save backplane window address */
};
-/**
- * SDIO Host Controller info
- */
-struct sdio_hc {
- struct sdio_hc *next;
- struct device *dev; /* platform device handle */
- void *regs; /* SDIO Host Controller address */
- struct brcmf_sdio_card *card;
- void *ch;
- unsigned int oob_irq;
- unsigned long oob_flags; /* OOB Host specifiction
- as edge and etc */
- bool oob_irq_registered;
-};
-
const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
-static struct sdio_hc *sdhcinfo;
-
/* driver info, initialized when brcmf_sdio_register is called */
static struct brcmf_sdioh_driver drvinfo = { NULL, NULL };
module_param(sd_f2_blocksize, int, 0);
struct brcmf_sdio_card*
-brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq)
+brcmf_sdcard_attach(void *cfghdl, u32 *regsva)
{
struct brcmf_sdio_card *card;
return NULL;
}
- card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
+ card->sdioh = brcmf_sdioh_attach(cfghdl);
if (!card->sdioh) {
brcmf_sdcard_detach(card);
return NULL;
return card->sbwad;
}
-int brcmf_sdio_probe(struct device *dev)
+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
{
- struct sdio_hc *sdhc = NULL;
u32 regs = 0;
struct brcmf_sdio_card *card = NULL;
- int irq = 0;
u32 vendevid;
- unsigned long irq_flags = 0;
-
- /* allocate SDIO Host Controller state info */
- sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC);
- if (!sdhc) {
- SDLX_MSG(("%s: out of memory\n", __func__));
- goto err;
- }
- sdhc->dev = (void *)dev;
- card = brcmf_sdcard_attach((void *)0, ®s, irq);
+ card = brcmf_sdcard_attach((void *)0, ®s);
if (!card) {
SDLX_MSG(("%s: attach failed\n", __func__));
goto err;
}
+ sdiodev->card = card;
- sdhc->card = card;
- sdhc->oob_irq = irq;
- sdhc->oob_flags = irq_flags;
- sdhc->oob_irq_registered = false; /* to make sure.. */
-
- /* chain SDIO Host Controller info together */
- sdhc->next = sdhcinfo;
- sdhcinfo = sdhc;
/* Read the vendor/device ID from the CIS */
vendevid = brcmf_sdcard_query_device(card);
/* try to attach to the target device */
- sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
+ sdiodev->bus = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
0, 0, 0, 0, regs, card);
- if (!sdhc->ch) {
+ if (!sdiodev->bus) {
SDLX_MSG(("%s: device attach failed\n", __func__));
goto err;
}
/* error handling */
err:
- if (sdhc) {
- if (sdhc->card)
- brcmf_sdcard_detach(sdhc->card);
- kfree(sdhc);
- }
+ if (sdiodev->card)
+ brcmf_sdcard_detach(sdiodev->card);
return -ENODEV;
}
EXPORT_SYMBOL(brcmf_sdio_probe);
-int brcmf_sdio_remove(struct device *dev)
+int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
{
- struct sdio_hc *sdhc, *prev;
-
- sdhc = sdhcinfo;
- drvinfo.detach(sdhc->ch);
- brcmf_sdcard_detach(sdhc->card);
- /* find the SDIO Host Controller state for this pdev
- and take it out from the list */
- for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
- if (sdhc->dev == (void *)dev) {
- if (prev)
- prev->next = sdhc->next;
- else
- sdhcinfo = NULL;
- break;
- }
- prev = sdhc;
- }
- if (!sdhc) {
- SDLX_MSG(("%s: failed\n", __func__));
- return 0;
- }
-
- /* release SDIO Host Controller info */
- kfree(sdhc);
+ drvinfo.detach(sdiodev->bus);
+ brcmf_sdcard_detach(sdiodev->card);
return 0;
}
EXPORT_SYMBOL(brcmf_sdio_remove);
brcmf_sdio_function_cleanup();
}
-void brcmf_sdio_wdtmr_enable(bool enable)
+void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
{
if (enable)
- brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms);
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, brcmf_watchdog_ms);
else
- brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0);
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
}
struct brcmf_sdmmc_instance *gInstance;
static atomic_t brcmf_mmc_suspend;
-struct device sdmmc_dev;
-
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
/*
* Public entry points & extern's
*/
-struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
+struct sdioh_info *brcmf_sdioh_attach(void *bar0)
{
struct sdioh_info *sd;
int err_ret;
{
int ret = 0;
static struct sdio_func sdio_func_0;
+ struct brcmf_sdio_dev *sdiodev;
BRCMF_TRACE(("sdio_probe: %s Enter\n", __func__));
BRCMF_TRACE(("sdio_probe: func->class=%x\n", func->class));
BRCMF_TRACE(("sdio_vendor: 0x%04x\n", func->vendor));
sdio_func_0.num = 0;
sdio_func_0.card = func->card;
gInstance->func[0] = &sdio_func_0;
+
+ if (dev_get_drvdata(&func->card->dev)) {
+ BRCMF_ERROR(("%s: card private drvdata occupied.\n",
+ __func__));
+ return -ENXIO;
+ }
+ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+ if (!sdiodev)
+ return -ENOMEM;
+ sdiodev->func1 = func;
+ dev_set_drvdata(&func->card->dev, sdiodev);
}
gInstance->func[func->num] = func;
if (func->num == 2) {
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ if ((!sdiodev) || (sdiodev->func1->card != func->card))
+ return -ENODEV;
+ sdiodev->func2 = func;
+
brcmf_cfg80211_sdio_func(func);
BRCMF_TRACE(("F2 found, calling brcmf_sdio_probe...\n"));
- ret = brcmf_sdio_probe(&sdmmc_dev);
+ ret = brcmf_sdio_probe(sdiodev);
}
return ret;
static void brcmf_ops_sdio_remove(struct sdio_func *func)
{
+ struct brcmf_sdio_dev *sdiodev;
BRCMF_TRACE(("%s Enter\n", __func__));
BRCMF_INFO(("func->class=%x\n", func->class));
BRCMF_INFO(("sdio_vendor: 0x%04x\n", func->vendor));
BRCMF_INFO(("Function#: 0x%04x\n", func->num));
if (func->num == 2) {
+ sdiodev = dev_get_drvdata(&func->card->dev);
BRCMF_TRACE(("F2 found, calling brcmf_sdio_remove...\n"));
- brcmf_sdio_remove(&sdmmc_dev);
+ brcmf_sdio_remove(sdiodev);
+ dev_set_drvdata(&func->card->dev, NULL);
+ kfree(sdiodev);
}
}
static int brcmf_sdio_suspend(struct device *dev)
{
mmc_pm_flag_t sdio_flags;
+ struct brcmf_sdio_dev *sdiodev;
+ struct sdio_func *func = dev_to_sdio_func(dev);
int ret = 0;
BRCMF_TRACE(("%s\n", __func__));
return ret;
}
- brcmf_sdio_wdtmr_enable(false);
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ brcmf_sdio_wdtmr_enable(sdiodev, false);
return ret;
}
static int brcmf_sdio_resume(struct device *dev)
{
- brcmf_sdio_wdtmr_enable(true);
+ struct brcmf_sdio_dev *sdiodev;
+ struct sdio_func *func = dev_to_sdio_func(dev);
+
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ brcmf_sdio_wdtmr_enable(sdiodev, true);
atomic_set(&brcmf_mmc_suspend, false);
return 0;
}
if (!gInstance)
return -ENOMEM;
- memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
error = sdio_register_driver(&brcmf_sdmmc_driver);
return error;
u32 host_claimed;
};
+struct brcmf_sdio_dev {
+ struct sdio_func *func1;
+ struct sdio_func *func2;
+ struct brcmf_sdio_card *card;
+ void *bus;
+};
+
/* Attach and build an interface to the underlying SD host driver.
* - Allocates resources (structs, arrays, mem, OS handles, etc) needed by
* brcmf_sdcard.
* most recent one) to enable single-instance implementations to pass NULL.
*/
extern struct brcmf_sdio_card*
-brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq);
+brcmf_sdcard_attach(void *cfghdl, u32 *regsva);
/* Detach - freeup resources allocated in attach */
extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card);
extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver);
extern void brcmf_sdio_unregister(void);
extern void brcmf_sdio_function_cleanup(void);
-extern int brcmf_sdio_probe(struct device *dev);
-extern int brcmf_sdio_remove(struct device *dev);
+extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
/* Function to return current window addr */
extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card);
* The handler shall be provided by all subsequent calls. No local cache
* cfghdl points to the starting address of pci device mapped memory
*/
-extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq);
+extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl);
extern int brcmf_sdioh_detach(struct sdioh_info *si);
extern int
extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc);
/* Watchdog timer interface for pm ops */
-extern void brcmf_sdio_wdtmr_enable(bool enable);
+extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev,
+ bool enable);
extern uint sd_f2_blocksize;