Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- a/drivers/net/wireless/ti/wlcore/sdio.c
- +++ b/drivers/net/wireless/ti/wlcore/sdio.c
- @@ -30,7 +30,7 @@
- #include <linux/mmc/sdio_ids.h>
- #include <linux/mmc/card.h>
- #include <linux/mmc/host.h>
- -#include <linux/gpio.h>
- +#include <linux/of_irq.h>
- #include <linux/wl12xx.h>
- #include <linux/pm_runtime.h>
- #include <linux/printk.h>
- @@ -214,6 +214,43 @@
- .set_block_size = wl1271_sdio_set_block_size,
- };
- +static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
- +{
- + struct wl12xx_platform_data *pdata;
- + struct device_node *np = dev->of_node;
- +
- + if (!np) {
- + np = of_find_matching_node(NULL, dev->driver->of_match_table);
- + if (!np) {
- + dev_notice(dev, "device tree node not available\n");
- + pdata = ERR_PTR(-ENODEV);
- + goto out;
- + }
- + }
- +
- + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
- + if (!pdata) {
- + dev_err(dev, "can't allocate platform data\n");
- + pdata = ERR_PTR(-ENODEV);
- + goto out;
- + }
- +
- + pdata->irq = irq_of_parse_and_map(np, 0);
- + if (pdata->irq < 0) {
- + dev_err(dev, "can't get interrupt gpio from the device tree\n");
- + goto out_free;
- + }
- + pdata->board_ref_clock = WL12XX_REFCLOCK_38; /* 38.4 MHz */
- + goto out;
- +
- +out_free:
- + kfree(pdata);
- + pdata = ERR_PTR(-ENODEV);
- +
- +out:
- + return pdata;
- +}
- +
- static int wl1271_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
- {
- @@ -248,11 +285,23 @@
- /* Use block mode for transferring over one block size of data */
- func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
- + /* The pdata allocated here is freed when the device is freed,
- + * so we don't need an additional out label to free it in case
- + * of error further on.
- + */
- +
- + /* Try to get legacy platform data from the board file */
- pdev_data->pdata = wl12xx_get_platform_data();
- if (IS_ERR(pdev_data->pdata)) {
- - ret = PTR_ERR(pdev_data->pdata);
- - dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
- - goto out_free_glue;
- + dev_info(&func->dev,
- + "legacy platform data not found, trying device tree\n");
- +
- + pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev);
- + if (IS_ERR(pdev_data->pdata)) {
- + ret = PTR_ERR(pdev_data->pdata);
- + dev_err(&func->dev, "can't get platform data\n");
- + goto out_free_glue;
- + }
- }
- /* if sdio can keep power while host is suspended, enable wow */
- @@ -386,16 +435,25 @@
- };
- #endif
- +static const struct of_device_id wlcore_sdio_of_match_table[] = {
- + { .compatible = "ti,wilink6" },
- + { .compatible = "ti,wilink7" },
- + { .compatible = "ti,wilink8" },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table);
- +
- static struct sdio_driver wl1271_sdio_driver = {
- .name = "wl1271_sdio",
- .id_table = wl1271_devices,
- .probe = wl1271_probe,
- .remove = wl1271_remove,
- + .drv = {
- #ifdef CONFIG_PM
- - .drv = {
- .pm = &wl1271_sdio_pm_ops,
- +#endif
- + .of_match_table = of_match_ptr(wlcore_sdio_of_match_table),
- },
- -#endif
- };
- static int __init wl1271_init(void)
- --- a/drivers/mmc/host/sdhci-esdhc-imx.c
- +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
- @@ -916,6 +916,20 @@
- return 1 << 28;
- }
- +static void sdhci_platform_set_power
- + (struct sdhci_host *host, int on)
- +{
- + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- + struct pltfm_imx_data *imx_data = pltfm_host ? pltfm_host->priv : 0;
- + struct esdhc_platform_data *boarddata = &imx_data->boarddata;
- +
- + if (imx_data && gpio_is_valid(boarddata->power_gpio)) {
- + dev_dbg(mmc_dev(host->mmc),"%s: imx_data %p, power-gpio %d, on %d\n",
- + __func__, imx_data, imx_data ? boarddata->power_gpio : -2, on);
- + gpio_direction_output(boarddata->power_gpio, on);
- + }
- +}
- +
- static struct sdhci_ops sdhci_esdhc_ops = {
- .read_l = esdhc_readl_le,
- .read_w = esdhc_readw_le,
- @@ -966,12 +980,28 @@
- if (gpio_is_valid(boarddata->wp_gpio))
- boarddata->wp_type = ESDHC_WP_GPIO;
- + boarddata->power_gpio = of_get_named_gpio(np, "power-gpio", 0);
- + dev_info(mmc_dev(host->mmc),
- + "%s: power-gpio %d\n", __func__, boarddata->power_gpio);
- + if (gpio_is_valid(boarddata->power_gpio)) {
- + int rc = gpio_request(boarddata->power_gpio, "sdhci_power");
- + if (rc) {
- + dev_err(mmc_dev(host->mmc),
- + "failed to allocate power gpio\n");
- + boarddata->power_gpio = -ENODEV;
- + }
- + gpio_direction_output(boarddata->power_gpio, 0);
- + }
- +
- of_property_read_u32(np, "bus-width", &boarddata->max_bus_width);
- if (of_find_property(np, "no-1-8-v", NULL))
- boarddata->support_vsel = false;
- else
- boarddata->support_vsel = true;
- +
- + if (of_find_property(np, "vqmmc-1-8-v", NULL))
- + boarddata->vqmmc_18v = true;
- if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
- boarddata->delay_line = 0;
- @@ -1108,6 +1138,9 @@
- imx_data->boarddata = *((struct esdhc_platform_data *)
- host->mmc->parent->platform_data);
- }
- +
- + if (gpio_is_valid(boarddata->power_gpio))
- + sdhci_esdhc_ops. platform_set_power = sdhci_platform_set_power;
- /* write_protect */
- if (boarddata->wp_type == ESDHC_WP_GPIO) {
- @@ -1173,6 +1206,8 @@
- } else {
- host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
- }
- + if (boarddata->vqmmc_18v)
- + host->quirks2 |= SDHCI_QUIRK2_VQMMC_1_8_V;
- if (host->mmc->pm_caps & MMC_PM_KEEP_POWER &&
- host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ)
- @@ -1205,6 +1240,14 @@
- {
- struct sdhci_host *host = platform_get_drvdata(pdev);
- int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
- + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- + struct pltfm_imx_data *imx_data = pltfm_host ? pltfm_host->priv : 0;
- + struct esdhc_platform_data *boarddata = &imx_data->boarddata;
- +
- + if (imx_data && gpio_is_valid(boarddata->power_gpio)) {
- + gpio_direction_output(boarddata->power_gpio, 0);
- + gpio_free(boarddata->power_gpio);
- + }
- sdhci_remove_host(host, dead);
- --- a/drivers/mmc/host/sdhci.c
- +++ b/drivers/mmc/host/sdhci.c
- @@ -1452,7 +1452,10 @@
- vdd_bit = sdhci_set_power(host, -1);
- else
- vdd_bit = sdhci_set_power(host, ios->vdd);
- -
- + if (host->ops->platform_set_power)
- + host->ops->platform_set_power
- + (host,
- + MMC_POWER_OFF != ios->power_mode);
- if (host->vmmc && vdd_bit != -1) {
- spin_unlock_irqrestore(&host->lock, flags);
- mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
- @@ -1750,6 +1753,9 @@
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- + if (host->quirks2 & SDHCI_QUIRK2_VQMMC_1_8_V)
- + ios->signal_voltage = MMC_SIGNAL_VOLTAGE_180;
- +
- switch (ios->signal_voltage) {
- case MMC_SIGNAL_VOLTAGE_330:
- /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
- @@ -1777,7 +1783,7 @@
- return -EAGAIN;
- case MMC_SIGNAL_VOLTAGE_180:
- - if (host->vqmmc) {
- + if (host->vqmmc && !(host->quirks2 & SDHCI_QUIRK2_VQMMC_1_8_V)) {
- ret = regulator_set_voltage(host->vqmmc,
- 1700000, 1950000);
- if (ret) {
- @@ -2201,8 +2207,9 @@
- spin_lock_irqsave(&host->lock, flags);
- if (host->mrq) {
- - pr_err("%s: Timeout waiting for hardware "
- - "interrupt.\n", mmc_hostname(host->mmc));
- + pr_err("%s: Timeout waiting for hardware interrupt. retries left=%d opcode=%x\n",
- + mmc_hostname(host->mmc), host->cmd ? host->cmd->retries : 0,
- + host->cmd ? host->cmd->opcode : 0);
- sdhci_dumpregs(host);
- if (host->data) {
- --- a/drivers/mmc/host/sdhci.h
- +++ b/drivers/mmc/host/sdhci.h
- @@ -296,6 +296,7 @@
- void (*platform_resume)(struct sdhci_host *host);
- void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
- void (*platform_init)(struct sdhci_host *host);
- + void (*platform_set_power)(struct sdhci_host *host, int on);
- };
- #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
- --- a/include/linux/mmc/host.h
- +++ b/include/linux/mmc/host.h
- @@ -328,6 +328,7 @@
- struct task_struct *claimer; /* task that has host claimed */
- int claim_cnt; /* "claim" nesting count */
- + struct workqueue_struct *workqueue;
- struct delayed_work detect;
- int detect_change; /* card detect flag */
- struct mmc_slot slot;
- --- a/include/linux/mmc/sdhci.h
- +++ b/include/linux/mmc/sdhci.h
- @@ -97,6 +97,7 @@
- #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3)
- #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4)
- #define SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER (1<<5)
- +#define SDHCI_QUIRK2_VQMMC_1_8_V (1<<6)
- int irq; /* Device IRQ */
- void __iomem *ioaddr; /* Mapped address */
- --- a/include/linux/platform_data/mmc-esdhc-imx.h
- +++ b/include/linux/platform_data/mmc-esdhc-imx.h
- @@ -40,10 +40,12 @@
- struct esdhc_platform_data {
- unsigned int wp_gpio;
- unsigned int cd_gpio;
- + unsigned int power_gpio;
- enum wp_types wp_type;
- enum cd_types cd_type;
- int max_bus_width;
- bool support_vsel;
- + bool vqmmc_18v;
- unsigned int delay_line;
- };
- #endif /* __ASM_ARCH_IMX_ESDHC_H */
- --- a/drivers/mmc/core/core.c
- +++ b/drivers/mmc/core/core.c
- @@ -51,7 +51,6 @@
- */
- #define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */
- -static struct workqueue_struct *workqueue;
- static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
- /*
- @@ -78,23 +77,6 @@
- MODULE_PARM_DESC(
- removable,
- "MMC/SD cards are removable and may be removed during suspend");
- -
- -/*
- - * Internal function. Schedule delayed work in the MMC work queue.
- - */
- -static int mmc_schedule_delayed_work(struct delayed_work *work,
- - unsigned long delay)
- -{
- - return queue_delayed_work(workqueue, work, delay);
- -}
- -
- -/*
- - * Internal function. Flush all scheduled work from the MMC work queue.
- - */
- -static void mmc_flush_scheduled_work(void)
- -{
- - flush_workqueue(workqueue);
- -}
- #ifdef CONFIG_FAIL_MMC_REQUEST
- @@ -1656,7 +1638,7 @@
- spin_unlock_irqrestore(&host->lock, flags);
- #endif
- host->detect_change = 1;
- - mmc_schedule_delayed_work(&host->detect, delay);
- + queue_delayed_work(host->workqueue, &host->detect, delay);
- }
- EXPORT_SYMBOL(mmc_detect_change);
- @@ -2409,7 +2391,7 @@
- out:
- if (host->caps & MMC_CAP_NEEDS_POLL)
- - mmc_schedule_delayed_work(&host->detect, HZ);
- + queue_delayed_work(host->workqueue, &host->detect, HZ);
- }
- void mmc_start_host(struct mmc_host *host)
- @@ -2434,7 +2416,7 @@
- host->rescan_disable = 1;
- cancel_delayed_work_sync(&host->detect);
- - mmc_flush_scheduled_work();
- + flush_workqueue(host->workqueue);
- /* clear pm flags now and let card drivers set them as needed */
- host->pm_flags = 0;
- @@ -2629,7 +2611,7 @@
- int err = 0;
- cancel_delayed_work(&host->detect);
- - mmc_flush_scheduled_work();
- + flush_workqueue(host->workqueue);
- mmc_bus_get(host);
- if (host->bus_ops && !host->bus_dead) {
- @@ -2793,13 +2775,9 @@
- {
- int ret;
- - workqueue = alloc_ordered_workqueue("kmmcd", 0);
- - if (!workqueue)
- - return -ENOMEM;
- -
- ret = mmc_register_bus();
- if (ret)
- - goto destroy_workqueue;
- + return ret;
- ret = mmc_register_host_class();
- if (ret)
- @@ -2815,9 +2793,6 @@
- mmc_unregister_host_class();
- unregister_bus:
- mmc_unregister_bus();
- -destroy_workqueue:
- - destroy_workqueue(workqueue);
- -
- return ret;
- }
- @@ -2826,7 +2801,6 @@
- sdio_unregister_bus();
- mmc_unregister_host_class();
- mmc_unregister_bus();
- - destroy_workqueue(workqueue);
- }
- subsys_initcall(mmc_init);
- --- a/drivers/mmc/core/host.c
- +++ b/drivers/mmc/core/host.c
- @@ -36,6 +36,7 @@
- {
- struct mmc_host *host = cls_dev_to_mmc_host(dev);
- mutex_destroy(&host->slot.lock);
- + destroy_workqueue(host->workqueue);
- kfree(host);
- }
- @@ -446,6 +447,9 @@
- goto free;
- dev_set_name(&host->class_dev, "mmc%d", host->index);
- + host->workqueue = alloc_ordered_workqueue("kmmcd%d", 0, host->index);
- + if (!host->workqueue)
- + goto free;
- host->parent = dev;
- host->class_dev.parent = dev;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement