staticint cw1200_request_irq(struct hwbus_priv *self)
{ int ret;
u8 cccr;
cccr = sdio_f0_readb(self->func, SDIO_CCCR_IENx, &ret); if (WARN_ON(ret)) goto err;
/* Master interrupt enable ... */
cccr |= BIT(0);
/* ... for our function */
cccr |= BIT(self->func->num);
sdio_f0_writeb(self->func, cccr, SDIO_CCCR_IENx, &ret); if (WARN_ON(ret)) goto err;
ret = enable_irq_wake(self->pdata->irq); if (WARN_ON(ret)) goto err;
/* Request the IRQ */
ret = request_threaded_irq(self->pdata->irq, cw1200_gpio_hardirq,
cw1200_gpio_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "cw1200_wlan_irq", self); if (WARN_ON(ret)) goto err;
return 0;
err: return ret;
}
staticint cw1200_sdio_irq_subscribe(struct hwbus_priv *self)
{ int ret = 0;
pr_debug("SW IRQ subscribe\n");
sdio_claim_host(self->func); if (self->pdata->irq)
ret = cw1200_request_irq(self); else
ret = sdio_claim_irq(self->func, cw1200_sdio_irq_handler);
sdio_release_host(self->func); return ret;
}
staticint cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self)
{ int ret = 0;
pr_debug("SW IRQ unsubscribe\n");
if (self->pdata->irq) {
disable_irq_wake(self->pdata->irq);
free_irq(self->pdata->irq, self);
} else {
sdio_claim_host(self->func);
ret = sdio_release_irq(self->func);
sdio_release_host(self->func);
} return ret;
}
/* Like the rest of the driver, this only supports one device per system */ staticstruct gpio_desc *cw1200_reset; staticstruct gpio_desc *cw1200_powerup;
staticint cw1200_sdio_off(conststruct cw1200_platform_data_sdio *pdata)
{ if (cw1200_reset) {
gpiod_set_value(cw1200_reset, 0);
msleep(30); /* Min is 2 * CLK32K cycles */
}
if (pdata->power_ctrl)
pdata->power_ctrl(pdata, false); if (pdata->clk_ctrl)
pdata->clk_ctrl(pdata, false);
return 0;
}
staticint cw1200_sdio_on(conststruct cw1200_platform_data_sdio *pdata)
{ /* Ensure I/Os are pulled low (reset is active low) */
cw1200_reset = devm_gpiod_get_optional(NULL, "reset", GPIOD_OUT_HIGH); if (IS_ERR(cw1200_reset)) {
pr_err("could not get CW1200 SDIO reset GPIO\n"); return PTR_ERR(cw1200_reset);
}
gpiod_set_consumer_name(cw1200_reset, "cw1200_wlan_reset");
cw1200_powerup = devm_gpiod_get_optional(NULL, "powerup", GPIOD_OUT_LOW); if (IS_ERR(cw1200_powerup)) {
pr_err("could not get CW1200 SDIO powerup GPIO\n"); return PTR_ERR(cw1200_powerup);
}
gpiod_set_consumer_name(cw1200_powerup, "cw1200_wlan_powerup");
if (cw1200_reset || cw1200_powerup)
msleep(10); /* Settle time? */
/* Enable 3v3 and 1v8 to hardware */ if (pdata->power_ctrl) { if (pdata->power_ctrl(pdata, true)) {
pr_err("power_ctrl() failed!\n"); return -1;
}
}
/* Enable CLK32K */ if (pdata->clk_ctrl) { if (pdata->clk_ctrl(pdata, true)) {
pr_err("clk_ctrl() failed!\n"); return -1;
}
msleep(10); /* Delay until clock is stable for 2 cycles */
}
/* Enable POWERUP signal */ if (cw1200_powerup) {
gpiod_set_value(cw1200_powerup, 1);
msleep(250); /* or more..? */
} /* Deassert RSTn signal, note active low */ if (cw1200_reset) {
gpiod_set_value(cw1200_reset, 0);
msleep(50); /* Or more..? */
} return 0;
}
/* Probe Function to be called by SDIO stack when device is discovered */ staticint cw1200_sdio_probe(struct sdio_func *func, conststruct sdio_device_id *id)
{ struct hwbus_priv *self; int status;
pr_info("cw1200_wlan_sdio: Probe called\n");
/* We are only able to handle the wlan function */ if (func->num != 0x01) return -ENODEV;
/* Disconnect Function to be called by SDIO stack when * device is disconnected
*/ staticvoid cw1200_sdio_disconnect(struct sdio_func *func)
{ struct hwbus_priv *self = sdio_get_drvdata(func);
if (self) {
cw1200_sdio_irq_unsubscribe(self); if (self->core) {
cw1200_core_release(self->core);
self->core = NULL;
}
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
sdio_set_drvdata(func, NULL);
kfree(self);
}
}
if (!cw1200_can_suspend(self->core)) return -EAGAIN;
/* Notify SDIO that CW1200 will remain powered during suspend */
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret)
pr_err("Error setting SDIO pm flags: %i\n", ret);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.