From af321b13cffc080451f5e802e041decf60666d26 Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Tue, 4 Dec 2012 17:06:18 +0530 Subject: mmc: sdio: fix resume failure due to lack of CMD52 reset If SDIO keep power flag (MMC_PM_KEEP_POWER) is not set, card would be reinitialized during resume but as we are not resetting (CMD52 reset) the SDIO card during this reinitialization, card may fail to respond back to subsequent commands (CMD5 etc...). This change resets the card before the reinitialization of card during resume. Signed-off-by: Subhash Jadavani Acked-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/sdio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 2273ce6b6c1a..34ad4c877c1f 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -937,10 +937,12 @@ static int mmc_sdio_resume(struct mmc_host *host) mmc_claim_host(host); /* No need to reinitialize powered-resumed nonremovable cards */ - if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) + if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { + sdio_reset(host); + mmc_go_idle(host); err = mmc_sdio_init_card(host, host->ocr, host->card, mmc_card_keep_power(host)); - else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { + } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { /* We may have switched to 1-bit mode during suspend */ err = sdio_enable_4bit_bus(host->card); if (err > 0) { -- cgit v1.2.3 From 56475a1d54fbb5b2b166b4e1c153293368437898 Mon Sep 17 00:00:00 2001 From: Sujit Reddy Thumma Date: Tue, 4 Dec 2012 17:06:19 +0530 Subject: mmc: sdio: Fix SDIO 3.0 UHS-I initialization sequence According to UHS-I initialization sequence for SDIO 3.0 cards, the host must set bit[24] (S18R) of OCR register during OCR handshake to know whether the SDIO card is capable of doing 1.8V I/O. Signed-off-by: Sujit Reddy Thumma Signed-off-by: Subhash Jadavani Reviewed-by: Johan Rudholm Reviewed-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/sdio.c | 22 +++++++++++----------- include/linux/mmc/host.h | 8 ++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 34ad4c877c1f..9565d38d91a4 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -157,10 +157,7 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) if (ret) goto out; - if (card->host->caps & - (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | - MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | - MMC_CAP_UHS_DDR50)) { + if (mmc_host_uhs(card->host)) { if (data & SDIO_UHS_DDR50) card->sw_caps.sd3_bus_mode |= SD_MODE_UHS_DDR50; @@ -478,8 +475,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) * If the host doesn't support any of the UHS-I modes, fallback on * default speed. */ - if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | - MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) + if (!mmc_host_uhs(card->host)) return 0; bus_speed = SDIO_SPEED_SDR12; @@ -645,11 +641,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, * systems that claim 1.8v signalling in fact do not support * it. */ - if ((ocr & R4_18V_PRESENT) && - (host->caps & - (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | - MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | - MMC_CAP_UHS_DDR50))) { + if ((ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) { err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, true); if (err) { @@ -1022,6 +1014,10 @@ static int mmc_sdio_power_restore(struct mmc_host *host) goto out; } + if (mmc_host_uhs(host)) + /* to query card if 1.8V signalling is supported */ + host->ocr |= R4_18V_PRESENT; + ret = mmc_sdio_init_card(host, host->ocr, host->card, mmc_card_keep_power(host)); if (!ret && host->sdio_irqs) @@ -1087,6 +1083,10 @@ int mmc_attach_sdio(struct mmc_host *host) /* * Detect and init the card. */ + if (mmc_host_uhs(host)) + /* to query card if 1.8V signalling is supported */ + host->ocr |= R4_18V_PRESENT; + err = mmc_sdio_init_card(host, host->ocr, NULL, 0); if (err) { if (err == -EAGAIN) { diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 61a10c17aabd..c89a1bb87fa5 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -434,6 +434,14 @@ static inline int mmc_boot_partition_access(struct mmc_host *host) return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC); } +static inline int mmc_host_uhs(struct mmc_host *host) +{ + return host->caps & + (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | + MMC_CAP_UHS_DDR50); +} + #ifdef CONFIG_MMC_CLKGATE void mmc_host_clk_hold(struct mmc_host *host); void mmc_host_clk_release(struct mmc_host *host); -- cgit v1.2.3 From 033631b715491522c239185adcbfe8b20659868f Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Tue, 4 Dec 2012 17:06:20 +0530 Subject: mmc: sdio: print correct UHS mode during card detection When SDIO3.0 card is detected, incorrect bus speed mode is printed as part of card detection print in kernel logs. This change fixes it so that user won't be confused by looking at incorrect card detection message in logs. Signed-off-by: Subhash Jadavani Tested-by: Jackey Shen Acked-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/sdio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 9565d38d91a4..3a64933466b8 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -485,23 +485,27 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) bus_speed = SDIO_SPEED_SDR104; timing = MMC_TIMING_UHS_SDR104; card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; + card->sd_bus_speed = UHS_SDR104_BUS_SPEED; } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { bus_speed = SDIO_SPEED_DDR50; timing = MMC_TIMING_UHS_DDR50; card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; + card->sd_bus_speed = UHS_DDR50_BUS_SPEED; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50)) { bus_speed = SDIO_SPEED_SDR50; timing = MMC_TIMING_UHS_SDR50; card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; + card->sd_bus_speed = UHS_SDR50_BUS_SPEED; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { bus_speed = SDIO_SPEED_SDR25; timing = MMC_TIMING_UHS_SDR25; card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; + card->sd_bus_speed = UHS_SDR25_BUS_SPEED; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & @@ -509,6 +513,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) bus_speed = SDIO_SPEED_SDR12; timing = MMC_TIMING_UHS_SDR12; card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; + card->sd_bus_speed = UHS_SDR12_BUS_SPEED; } err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); -- cgit v1.2.3 From 96272c84393330341f3778ace53c8ab4cbd8ddfd Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 11 Dec 2012 15:23:42 +0800 Subject: mmc: sdhci: query card presence from cd-gpio before asking SDHCI Call mmc_gpio_get_cd() to query card presence from cd-gpio before asking SDHCI. The rationale behind this change is that flag SDHCI_QUIRK_BROKEN_CARD_DETECTION is designed for SDHCI controller to tell that SDHCI_PRESENT_STATE is broken, and it should be used for this case only. So when cd-gpio is being used, the controller should set the flag to tell that SDHCI_PRESENT_STATE is not available. However, the existing code will skip checking cd-gpio as long as flag SDHCI_QUIRK_BROKEN_CARD_DETECTION is set. Change the querying order between cd-gpio and SDHCI to support the rationale above. Signed-off-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6f0bfc0c8c9c..1b97fe2d70ab 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1258,7 +1258,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct sdhci_host *host; - bool present; + int present; unsigned long flags; u32 tuning_opcode; @@ -1287,18 +1287,21 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; - /* If polling, assume that the card is always present. */ - if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) - present = true; - else - present = sdhci_readl(host, SDHCI_PRESENT_STATE) & - SDHCI_CARD_PRESENT; - - /* If we're using a cd-gpio, testing the presence bit might fail. */ - if (!present) { - int ret = mmc_gpio_get_cd(host->mmc); - if (ret > 0) - present = true; + /* + * Firstly check card presence from cd-gpio. The return could + * be one of the following possibilities: + * negative: cd-gpio is not available + * zero: cd-gpio is used, and card is removed + * one: cd-gpio is used, and card is present + */ + present = mmc_gpio_get_cd(host->mmc); + if (present < 0) { + /* If polling, assume that the card is always present. */ + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) + present = 1; + else + present = sdhci_readl(host, SDHCI_PRESENT_STATE) & + SDHCI_CARD_PRESENT; } if (!present || host->flags & SDHCI_DEVICE_DEAD) { -- cgit v1.2.3 From c8bdfea7c3e60c99ce7cc3459d8acfa0ce8854e3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 11 Dec 2012 22:32:18 +0800 Subject: mmc: slot-gpio: use devm_* managed functions to ease users Use devm_* managed functions, so that slot-gpio users do not have to call mmc_gpio_free_ro/cd to free up resources requested in mmc_gpio_request_ro/cd. Signed-off-by: Shawn Guo Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/core/slot-gpio.c | 57 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 16a1c0b6f264..324235105519 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -92,6 +92,20 @@ int mmc_gpio_get_cd(struct mmc_host *host) } EXPORT_SYMBOL(mmc_gpio_get_cd); +/** + * mmc_gpio_request_ro - request a gpio for write-protection + * @host: mmc host + * @gpio: gpio number requested + * + * As devm_* managed functions are used in mmc_gpio_request_ro(), client + * drivers do not need to explicitly call mmc_gpio_free_ro() for freeing up, + * if the requesting and freeing are only needed at probing and unbinding time + * for once. However, if client drivers do something special like runtime + * switching for write-protection, they are responsible for calling + * mmc_gpio_request_ro() and mmc_gpio_free_ro() as a pair on their own. + * + * Returns zero on success, else an error. + */ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) { struct mmc_gpio *ctx; @@ -106,7 +120,8 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) ctx = host->slot.handler_priv; - ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); + ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, + ctx->ro_label); if (ret < 0) return ret; @@ -116,6 +131,20 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) } EXPORT_SYMBOL(mmc_gpio_request_ro); +/** + * mmc_gpio_request_cd - request a gpio for card-detection + * @host: mmc host + * @gpio: gpio number requested + * + * As devm_* managed functions are used in mmc_gpio_request_cd(), client + * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up, + * if the requesting and freeing are only needed at probing and unbinding time + * for once. However, if client drivers do something special like runtime + * switching for card-detection, they are responsible for calling + * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own. + * + * Returns zero on success, else an error. + */ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) { struct mmc_gpio *ctx; @@ -128,7 +157,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) ctx = host->slot.handler_priv; - ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); + ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, + ctx->cd_label); if (ret < 0) /* * don't bother freeing memory. It might still get used by other @@ -146,7 +176,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) irq = -EINVAL; if (irq >= 0) { - ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, + ret = devm_request_threaded_irq(&host->class_dev, irq, + NULL, mmc_gpio_cd_irqt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ctx->cd_label, host); if (ret < 0) @@ -164,6 +195,13 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) } EXPORT_SYMBOL(mmc_gpio_request_cd); +/** + * mmc_gpio_free_ro - free the write-protection gpio + * @host: mmc host + * + * It's provided only for cases that client drivers need to manually free + * up the write-protection gpio requested by mmc_gpio_request_ro(). + */ void mmc_gpio_free_ro(struct mmc_host *host) { struct mmc_gpio *ctx = host->slot.handler_priv; @@ -175,10 +213,17 @@ void mmc_gpio_free_ro(struct mmc_host *host) gpio = ctx->ro_gpio; ctx->ro_gpio = -EINVAL; - gpio_free(gpio); + devm_gpio_free(&host->class_dev, gpio); } EXPORT_SYMBOL(mmc_gpio_free_ro); +/** + * mmc_gpio_free_cd - free the card-detection gpio + * @host: mmc host + * + * It's provided only for cases that client drivers need to manually free + * up the card-detection gpio requested by mmc_gpio_request_cd(). + */ void mmc_gpio_free_cd(struct mmc_host *host) { struct mmc_gpio *ctx = host->slot.handler_priv; @@ -188,13 +233,13 @@ void mmc_gpio_free_cd(struct mmc_host *host) return; if (host->slot.cd_irq >= 0) { - free_irq(host->slot.cd_irq, host); + devm_free_irq(&host->class_dev, host->slot.cd_irq, host); host->slot.cd_irq = -EINVAL; } gpio = ctx->cd_gpio; ctx->cd_gpio = -EINVAL; - gpio_free(gpio); + devm_gpio_free(&host->class_dev, gpio); } EXPORT_SYMBOL(mmc_gpio_free_cd); -- cgit v1.2.3 From 60fe3ec12122be39e673580c8870f4b92e546bf9 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 11 Dec 2012 22:32:19 +0800 Subject: mmc: remove unncessary mmc_gpio_free_cd() call from slot-gpio users Since slot-gpio uses devm_* managed functions in mmc_gpio_request_cd() now, we can remove those mmc_gpio_free_cd() call from host drivers' .probe() error path and .remove(). Signed-off-by: Shawn Guo Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pxav3.c | 5 ----- drivers/mmc/host/sh_mmcif.c | 6 ------ drivers/mmc/host/tmio_mmc_pio.c | 8 -------- 3 files changed, 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index fad0966427fd..b7ee7761bc26 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -316,7 +316,6 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) err_add_host: clk_disable_unprepare(clk); clk_put(clk); - mmc_gpio_free_cd(host->mmc); err_cd_req: err_clk_get: sdhci_pltfm_free(pdev); @@ -329,16 +328,12 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pxa *pxa = pltfm_host->priv; - struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; sdhci_remove_host(host, 1); clk_disable_unprepare(pltfm_host->clk); clk_put(pltfm_host->clk); - if (gpio_is_valid(pdata->ext_cd_gpio)) - mmc_gpio_free_cd(host->mmc); - sdhci_pltfm_free(pdev); kfree(pxa); diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 9a4c151067dd..741aeb95c7a4 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1404,8 +1404,6 @@ static int sh_mmcif_probe(struct platform_device *pdev) return ret; emmcaddh: - if (pd && pd->use_cd_gpio) - mmc_gpio_free_cd(mmc); erqcd: free_irq(irq[1], host); ereqirq1: @@ -1427,7 +1425,6 @@ ealloch: static int sh_mmcif_remove(struct platform_device *pdev) { struct sh_mmcif_host *host = platform_get_drvdata(pdev); - struct sh_mmcif_plat_data *pd = pdev->dev.platform_data; int irq[2]; host->dying = true; @@ -1436,9 +1433,6 @@ static int sh_mmcif_remove(struct platform_device *pdev) dev_pm_qos_hide_latency_limit(&pdev->dev); - if (pd && pd->use_cd_gpio) - mmc_gpio_free_cd(host->mmc); - mmc_remove_host(host->mmc); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 50bf495a988b..0f992e9ffc73 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -1060,16 +1060,8 @@ EXPORT_SYMBOL(tmio_mmc_host_probe); void tmio_mmc_host_remove(struct tmio_mmc_host *host) { struct platform_device *pdev = host->pdev; - struct tmio_mmc_data *pdata = host->pdata; struct mmc_host *mmc = host->mmc; - if (pdata->flags & TMIO_MMC_USE_GPIO_CD) - /* - * This means we can miss a card-eject, but this is anyway - * possible, because of delayed processing of hotplug events. - */ - mmc_gpio_free_cd(mmc); - if (!host->native_hotplug) pm_runtime_get_sync(&pdev->dev); -- cgit v1.2.3 From f6e644389d26ef12d40dc5f56c5d465006502d03 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 11 Dec 2012 22:32:20 +0800 Subject: mmc: sdhci-esdhc-imx: use slot-gpio helpers for CD and WP Use slot-gpio helpers to save some code in the driver. Signed-off-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 56 +++++++++++--------------------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index e07df812ff1e..dd7fcc137644 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -147,17 +148,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) struct pltfm_imx_data *imx_data = pltfm_host->priv; struct esdhc_platform_data *boarddata = &imx_data->boarddata; - /* fake CARD_PRESENT flag */ u32 val = readl(host->ioaddr + reg); - if (unlikely((reg == SDHCI_PRESENT_STATE) - && gpio_is_valid(boarddata->cd_gpio))) { - if (gpio_get_value(boarddata->cd_gpio)) - /* no card, if a valid gpio says so... */ + if (unlikely(reg == SDHCI_PRESENT_STATE)) { + /* + * After SDHCI core gets improved to never query + * SDHCI_CARD_PRESENT state in GPIO case, we can + * remove this check. + */ + if (boarddata->cd_type == ESDHC_CD_GPIO) val &= ~SDHCI_CARD_PRESENT; - else - /* ... in all other cases assume card is present */ - val |= SDHCI_CARD_PRESENT; } if (unlikely(reg == SDHCI_CAPABILITIES)) { @@ -362,8 +362,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) switch (boarddata->wp_type) { case ESDHC_WP_GPIO: - if (gpio_is_valid(boarddata->wp_gpio)) - return gpio_get_value(boarddata->wp_gpio); + return mmc_gpio_get_ro(host->mmc); case ESDHC_WP_CONTROLLER: return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); @@ -394,14 +393,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { .ops = &sdhci_esdhc_ops, }; -static irqreturn_t cd_irq(int irq, void *data) -{ - struct sdhci_host *sdhost = (struct sdhci_host *)data; - - tasklet_schedule(&sdhost->card_tasklet); - return IRQ_HANDLED; -}; - #ifdef CONFIG_OF static int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, @@ -527,37 +518,22 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) /* write_protect */ if (boarddata->wp_type == ESDHC_WP_GPIO) { - err = devm_gpio_request_one(&pdev->dev, boarddata->wp_gpio, - GPIOF_IN, "ESDHC_WP"); + err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); if (err) { - dev_warn(mmc_dev(host->mmc), - "no write-protect pin available!\n"); - boarddata->wp_gpio = -EINVAL; + dev_err(mmc_dev(host->mmc), + "failed to request write-protect gpio!\n"); + goto disable_clk; } - } else { - boarddata->wp_gpio = -EINVAL; + host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; } /* card_detect */ - if (boarddata->cd_type != ESDHC_CD_GPIO) - boarddata->cd_gpio = -EINVAL; - switch (boarddata->cd_type) { case ESDHC_CD_GPIO: - err = devm_gpio_request_one(&pdev->dev, boarddata->cd_gpio, - GPIOF_IN, "ESDHC_CD"); + err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio); if (err) { dev_err(mmc_dev(host->mmc), - "no card-detect pin available!\n"); - goto disable_clk; - } - - err = devm_request_irq(&pdev->dev, - gpio_to_irq(boarddata->cd_gpio), cd_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - mmc_hostname(host->mmc), host); - if (err) { - dev_err(mmc_dev(host->mmc), "request irq error\n"); + "failed to request card-detect gpio!\n"); goto disable_clk; } /* fall through */ -- cgit v1.2.3 From cd0511503532320e68396c90617d5f91ed7cae1c Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:05 +0100 Subject: mmc: sh_mmcif: force to fail CMD52 immediately mmc_rescan() sends CMD52 (SD_IO_RW_DIRECT) to reset SDIO card during card detection. CMD52 should be ignored by SD/eMMC cards, but we can also abort it in the driver immediately, since MMCIF doesn't support SDIO cards anyway. Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 741aeb95c7a4..8b4e98e2b130 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -911,6 +911,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR) break; case MMC_APP_CMD: + case SD_IO_RW_DIRECT: host->state = STATE_IDLE; mrq->cmd->error = -ETIMEDOUT; mmc_request_done(mmc, mrq); -- cgit v1.2.3 From 85033ef29f5ca3c362dcf79356c9ba8759b6d8ac Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:06 +0100 Subject: mmc: sh_mmcif: ensure run-time suspend call is processed before suspend With this post-v2.6.35 change applied: commit a0a1a5fd4fb15ec61117c759fe9f5c16c53d9e9c Author: Tejun Heo Date: Tue Jun 29 10:07:12 2010 +0200 workqueue: reimplement workqueue freeze using max_active freeze_workqueues_begin() was introduced and workqueue now gets frozen before device drivers suspend operations. We have to ensure that run-time PM suspend operation completes before system-wide suspend is started. Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 8b4e98e2b130..2ff3e4774b67 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -982,7 +982,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } if (host->power) { - pm_runtime_put(&host->pd->dev); + pm_runtime_put_sync(&host->pd->dev); clk_disable(host->hclk); host->power = false; if (ios->power_mode == MMC_POWER_OFF) -- cgit v1.2.3 From 0e8752f3a5c60e1b753bb320643145b3dfd4359c Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Mon, 14 Jan 2013 14:12:36 -0500 Subject: mmc: sh_mmcif: add support for bundled MMCIF IRQs On newer SoCs like R-Mobile U2, MMCIF interrupts are bundled. Signed-off-by: Shinya Kuribayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 2ff3e4774b67..c7984bad8efc 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1307,10 +1307,11 @@ static int sh_mmcif_probe(struct platform_device *pdev) struct sh_mmcif_plat_data *pd = pdev->dev.platform_data; struct resource *res; void __iomem *reg; + const char *name; irq[0] = platform_get_irq(pdev, 0); irq[1] = platform_get_irq(pdev, 1); - if (irq[0] < 0 || irq[1] < 0) { + if (irq[0] < 0) { dev_err(&pdev->dev, "Get irq error\n"); return -ENXIO; } @@ -1375,15 +1376,19 @@ static int sh_mmcif_probe(struct platform_device *pdev) sh_mmcif_sync_reset(host); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); - ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host); + name = irq[1] < 0 ? dev_name(&pdev->dev) : "sh_mmc:error"; + ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host); if (ret) { - dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); + dev_err(&pdev->dev, "request_irq error (%s)\n", name); goto ereqirq0; } - ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); - if (ret) { - dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); - goto ereqirq1; + if (irq[1] >= 0) { + ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, + 0, "sh_mmc:int", host); + if (ret) { + dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); + goto ereqirq1; + } } if (pd && pd->use_cd_gpio) { @@ -1406,7 +1411,8 @@ static int sh_mmcif_probe(struct platform_device *pdev) emmcaddh: erqcd: - free_irq(irq[1], host); + if (irq[1] >= 0) + free_irq(irq[1], host); ereqirq1: free_irq(irq[0], host); ereqirq0: @@ -1451,7 +1457,8 @@ static int sh_mmcif_remove(struct platform_device *pdev) irq[1] = platform_get_irq(pdev, 1); free_irq(irq[0], host); - free_irq(irq[1], host); + if (irq[1] >= 0) + free_irq(irq[1], host); platform_set_drvdata(pdev, NULL); -- cgit v1.2.3 From 613c25e7b5d4129d64327f83c00ad1463b606b01 Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:08 +0100 Subject: mmc: sh_mmcif: Add support for eMMC Dual Data Rate Some MMCIF implementations support the Dual Data Rate. With this patch, platforms can set the MMC_CAP_UHS_DDR50 capability flag in MMCIF platform data. This will let the MMC core to actually use the DDR mode. Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index c7984bad8efc..6d4328dce320 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -88,6 +88,7 @@ #define CMD_SET_TBIT (1 << 7) /* 1: tran mission bit "Low" */ #define CMD_SET_OPDM (1 << 6) /* 1: open/drain */ #define CMD_SET_CCSH (1 << 5) +#define CMD_SET_DARS (1 << 2) /* Dual Data Rate */ #define CMD_SET_DATW_1 ((0 << 1) | (0 << 0)) /* 1bit */ #define CMD_SET_DATW_4 ((0 << 1) | (1 << 0)) /* 4bit */ #define CMD_SET_DATW_8 ((1 << 1) | (0 << 0)) /* 8bit */ @@ -216,6 +217,7 @@ struct sh_mmcif_host { struct clk *hclk; unsigned int clk; int bus_width; + unsigned char timing; bool sd_error; bool dying; long timeout; @@ -781,6 +783,17 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, dev_err(&host->pd->dev, "Unsupported bus width.\n"); break; } + switch (host->timing) { + case MMC_TIMING_UHS_DDR50: + /* + * MMC core will only set this timing, if the host + * advertises the MMC_CAP_UHS_DDR50 capability. MMCIF + * implementations with this capability, e.g. sh73a0, + * will have to set it in their platform data. + */ + tmp |= CMD_SET_DARS; + break; + } } /* DWEN */ if (opc == MMC_WRITE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) @@ -1002,6 +1015,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) sh_mmcif_clock_control(host, ios->clock); } + host->timing = ios->timing; host->bus_width = ios->bus_width; host->state = STATE_IDLE; } -- cgit v1.2.3 From 93c3a791e7ce306f33b8e39d96ae9527c23e925a Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:09 +0100 Subject: mmc: sh_mmcif: Use msecs_to_jiffies() for host->timeout Timeout period should be properly normalized using msecs_to_jiffies(). Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 6d4328dce320..6d3644430877 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1348,7 +1348,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) host = mmc_priv(mmc); host->mmc = mmc; host->addr = reg; - host->timeout = 1000; + host->timeout = msecs_to_jiffies(1000); host->pd = pdev; -- cgit v1.2.3 From e4fa90c60d30758daadc0aebc1807b54fedc497c Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:10 +0100 Subject: mmc: sh_mmcif: Avoid unnecessary mmc_delay() at mmc_card_sleepawake() SH/R-Mobile MMCIF host controller can wait while the card signals busy. Set MMC_CAP_WAIT_WHILE_BUSY to inform an upper layer (core/mmc_ops.c) not to insert unnecessary mmc_delay(). Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 6d3644430877..663b92b364bb 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -758,6 +758,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, } switch (opc) { /* RBSY */ + case MMC_SLEEP_AWAKE: case MMC_SWITCH: case MMC_STOP_TRANSMISSION: case MMC_SET_WRITE_PROT: @@ -851,6 +852,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, switch (opc) { /* response busy check */ + case MMC_SLEEP_AWAKE: case MMC_SWITCH: case MMC_STOP_TRANSMISSION: case MMC_SET_WRITE_PROT: @@ -1357,7 +1359,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) mmc->ops = &sh_mmcif_ops; sh_mmcif_init_ocr(host); - mmc->caps = MMC_CAP_MMC_HIGHSPEED; + mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_WAIT_WHILE_BUSY; if (pd && pd->caps) mmc->caps |= pd->caps; mmc->max_segs = 32; -- cgit v1.2.3 From a78b4ca276d7df627ebac50ae3d012c060fe04f8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:38:11 +0100 Subject: mmc: sh-mmcif: fix missing and consolidate IO completion timeouts Read block and write block operations are currently missing completion timeouts. Add missing timeouts and consolidate them at one location. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 663b92b364bb..f4b10c8f6384 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -564,7 +564,6 @@ static void sh_mmcif_single_read(struct sh_mmcif_host *host, BLOCK_SIZE_MASK) + 3; host->wait_for = MMCIF_WAIT_FOR_READ; - schedule_delayed_work(&host->timeout_work, host->timeout); /* buf read enable */ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); @@ -606,7 +605,7 @@ static void sh_mmcif_multi_read(struct sh_mmcif_host *host, host->sg_idx = 0; host->sg_blkidx = 0; host->pio_ptr = sg_virt(data->sg); - schedule_delayed_work(&host->timeout_work, host->timeout); + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); } @@ -629,7 +628,6 @@ static bool sh_mmcif_mread_block(struct sh_mmcif_host *host) if (!sh_mmcif_next_block(host, p)) return false; - schedule_delayed_work(&host->timeout_work, host->timeout); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); return true; @@ -642,7 +640,6 @@ static void sh_mmcif_single_write(struct sh_mmcif_host *host, BLOCK_SIZE_MASK) + 3; host->wait_for = MMCIF_WAIT_FOR_WRITE; - schedule_delayed_work(&host->timeout_work, host->timeout); /* buf write enable */ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); @@ -684,7 +681,7 @@ static void sh_mmcif_multi_write(struct sh_mmcif_host *host, host->sg_idx = 0; host->sg_blkidx = 0; host->pio_ptr = sg_virt(data->sg); - schedule_delayed_work(&host->timeout_work, host->timeout); + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); } @@ -707,7 +704,6 @@ static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host) if (!sh_mmcif_next_block(host, p)) return false; - schedule_delayed_work(&host->timeout_work, host->timeout); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); return true; @@ -900,7 +896,6 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, } host->wait_for = MMCIF_WAIT_FOR_STOP; - schedule_delayed_work(&host->timeout_work, host->timeout); } static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) @@ -1121,6 +1116,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) { struct sh_mmcif_host *host = dev_id; struct mmc_request *mrq = host->mrq; + bool wait = false; cancel_delayed_work_sync(&host->timeout_work); @@ -1133,29 +1129,24 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) /* We're too late, the timeout has already kicked in */ return IRQ_HANDLED; case MMCIF_WAIT_FOR_CMD: - if (sh_mmcif_end_cmd(host)) - /* Wait for data */ - return IRQ_HANDLED; + /* Wait for data? */ + wait = sh_mmcif_end_cmd(host); break; case MMCIF_WAIT_FOR_MREAD: - if (sh_mmcif_mread_block(host)) - /* Wait for more data */ - return IRQ_HANDLED; + /* Wait for more data? */ + wait = sh_mmcif_mread_block(host); break; case MMCIF_WAIT_FOR_READ: - if (sh_mmcif_read_block(host)) - /* Wait for data end */ - return IRQ_HANDLED; + /* Wait for data end? */ + wait = sh_mmcif_read_block(host); break; case MMCIF_WAIT_FOR_MWRITE: - if (sh_mmcif_mwrite_block(host)) - /* Wait data to write */ - return IRQ_HANDLED; + /* Wait data to write? */ + wait = sh_mmcif_mwrite_block(host); break; case MMCIF_WAIT_FOR_WRITE: - if (sh_mmcif_write_block(host)) - /* Wait for data end */ - return IRQ_HANDLED; + /* Wait for data end? */ + wait = sh_mmcif_write_block(host); break; case MMCIF_WAIT_FOR_STOP: if (host->sd_error) { @@ -1174,6 +1165,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) BUG(); } + if (wait) { + schedule_delayed_work(&host->timeout_work, host->timeout); + /* Wait for more data */ + return IRQ_HANDLED; + } + if (host->wait_for != MMCIF_WAIT_FOR_STOP) { struct mmc_data *data = mrq->data; if (!mrq->cmd->error && data && !data->error) @@ -1182,8 +1179,10 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { sh_mmcif_stop_cmd(host, mrq); - if (!mrq->stop->error) + if (!mrq->stop->error) { + schedule_delayed_work(&host->timeout_work, host->timeout); return IRQ_HANDLED; + } } } -- cgit v1.2.3 From f291683f09d8b87957fe9a7955ba61f369c09dc4 Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:12 +0100 Subject: mmc: sh-mmcif: Terminate DMA transactions when detecting timeout or error If a DMA transaction fails, terminate all outstanding DMA transfers and unmap buffers. Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi [g.liakhovetski@gmx.de: forward-port, add dma_unmap_sg() in error cases] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index f4b10c8f6384..8aa7b0e6dec2 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -263,15 +263,6 @@ static void mmcif_dma_complete(void *arg) dev_name(&host->pd->dev))) return; - if (data->flags & MMC_DATA_READ) - dma_unmap_sg(host->chan_rx->device->dev, - data->sg, data->sg_len, - DMA_FROM_DEVICE); - else - dma_unmap_sg(host->chan_tx->device->dev, - data->sg, data->sg_len, - DMA_TO_DEVICE); - complete(&host->dma_complete); } @@ -1088,14 +1079,20 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) /* Running in the IRQ thread, can sleep */ time = wait_for_completion_interruptible_timeout(&host->dma_complete, host->timeout); + + if (data->flags & MMC_DATA_READ) + dma_unmap_sg(host->chan_rx->device->dev, + data->sg, data->sg_len, + DMA_FROM_DEVICE); + else + dma_unmap_sg(host->chan_tx->device->dev, + data->sg, data->sg_len, + DMA_TO_DEVICE); + if (host->sd_error) { dev_err(host->mmc->parent, "Error IRQ while waiting for DMA completion!\n"); /* Woken up by an error IRQ: abort DMA */ - if (data->flags & MMC_DATA_READ) - dmaengine_terminate_all(host->chan_rx); - else - dmaengine_terminate_all(host->chan_tx); data->error = sh_mmcif_error_manage(host); } else if (!time) { data->error = -ETIMEDOUT; @@ -1106,8 +1103,14 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) BUF_ACC_DMAREN | BUF_ACC_DMAWEN); host->dma_active = false; - if (data->error) + if (data->error) { data->bytes_xfered = 0; + /* Abort DMA */ + if (data->flags & MMC_DATA_READ) + dmaengine_terminate_all(host->chan_rx); + else + dmaengine_terminate_all(host->chan_tx); + } return false; } -- cgit v1.2.3 From 3050197d55b0f918ae48443b125616024065f977 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:38:13 +0100 Subject: mmc: sh-mmcif: (cosmetic) simplify boolean return blocks Use "return condition" instead of "if (condition) return true; return false" in functions, returning bool. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 8aa7b0e6dec2..de4b6d073599 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -542,10 +542,7 @@ static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p) host->pio_ptr = p; } - if (host->sg_idx == data->sg_len) - return false; - - return true; + return host->sg_idx != data->sg_len; } static void sh_mmcif_single_read(struct sh_mmcif_host *host, @@ -1071,9 +1068,7 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) if (!host->dma_active) { data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode); - if (!data->error) - return true; - return false; + return !data->error; } /* Running in the IRQ thread, can sleep */ -- cgit v1.2.3 From f20bec813edbef479bfc771abd037fc92e1ddf02 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:38:14 +0100 Subject: mmc: sh-mmcif: fix a race, causing an Oops on SMP Oopses have been observed on SMP in the sh-mmcif IRQ thread, when the two IRQ threads run simultaneously on two CPUs. Also take care to guard the timeout work and the DMA completion callback from possible NULL-pointer dereferences and races. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index de4b6d073599..3cfe383dc22b 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -196,6 +197,7 @@ enum mmcif_state { STATE_IDLE, STATE_REQUEST, STATE_IOS, + STATE_TIMEOUT, }; enum mmcif_wait_for { @@ -232,6 +234,7 @@ struct sh_mmcif_host { int sg_blkidx; bool power; bool card_present; + struct mutex thread_lock; /* DMA support */ struct dma_chan *chan_rx; @@ -255,11 +258,11 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host, static void mmcif_dma_complete(void *arg) { struct sh_mmcif_host *host = arg; - struct mmc_data *data = host->mrq->data; + struct mmc_request *mrq = host->mrq; dev_dbg(&host->pd->dev, "Command completed\n"); - if (WARN(!data, "%s: NULL data in DMA completion!\n", + if (WARN(!mrq || !mrq->data, "%s: NULL data in DMA completion!\n", dev_name(&host->pd->dev))) return; @@ -1113,11 +1116,21 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) { struct sh_mmcif_host *host = dev_id; - struct mmc_request *mrq = host->mrq; + struct mmc_request *mrq; bool wait = false; cancel_delayed_work_sync(&host->timeout_work); + mutex_lock(&host->thread_lock); + + mrq = host->mrq; + if (!mrq) { + dev_dbg(&host->pd->dev, "IRQ thread state %u, wait %u: NULL mrq!\n", + host->state, host->wait_for); + mutex_unlock(&host->thread_lock); + return IRQ_HANDLED; + } + /* * All handlers return true, if processing continues, and false, if the * request has to be completed - successfully or not @@ -1125,6 +1138,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) switch (host->wait_for) { case MMCIF_WAIT_FOR_REQUEST: /* We're too late, the timeout has already kicked in */ + mutex_unlock(&host->thread_lock); return IRQ_HANDLED; case MMCIF_WAIT_FOR_CMD: /* Wait for data? */ @@ -1166,6 +1180,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) if (wait) { schedule_delayed_work(&host->timeout_work, host->timeout); /* Wait for more data */ + mutex_unlock(&host->thread_lock); return IRQ_HANDLED; } @@ -1179,6 +1194,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) sh_mmcif_stop_cmd(host, mrq); if (!mrq->stop->error) { schedule_delayed_work(&host->timeout_work, host->timeout); + mutex_unlock(&host->thread_lock); return IRQ_HANDLED; } } @@ -1189,6 +1205,8 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) host->mrq = NULL; mmc_request_done(host->mmc, mrq); + mutex_unlock(&host->thread_lock); + return IRQ_HANDLED; } @@ -1262,11 +1280,24 @@ static void mmcif_timeout_work(struct work_struct *work) struct delayed_work *d = container_of(work, struct delayed_work, work); struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work); struct mmc_request *mrq = host->mrq; + unsigned long flags; if (host->dying) /* Don't run after mmc_remove_host() */ return; + dev_dbg(&host->pd->dev, "Timeout waiting for %u, opcode %u\n", + host->wait_for, mrq->cmd->opcode); + + spin_lock_irqsave(&host->lock, flags); + if (host->state == STATE_IDLE) { + spin_unlock_irqrestore(&host->lock, flags); + return; + } + + host->state = STATE_TIMEOUT; + spin_unlock_irqrestore(&host->lock, flags); + /* * Handle races with cancel_delayed_work(), unless * cancel_delayed_work_sync() is used @@ -1410,6 +1441,8 @@ static int sh_mmcif_probe(struct platform_device *pdev) goto erqcd; } + mutex_init(&host->thread_lock); + clk_disable(host->hclk); ret = mmc_add_host(mmc); if (ret < 0) -- cgit v1.2.3 From 33e69c7b4821818fb758c5437a7bc50d06f37dde Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:38:15 +0100 Subject: mmc: sh-mmcif: reset error code for any opcode If a command execution has produced an error, it has to be reset as a part of the error handling. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 3cfe383dc22b..14fafafc12d3 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1041,7 +1041,6 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) case MMC_SELECT_CARD: case MMC_APP_CMD: cmd->error = -ETIMEDOUT; - host->sd_error = false; break; default: cmd->error = sh_mmcif_error_manage(host); @@ -1049,6 +1048,7 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) cmd->opcode, cmd->error); break; } + host->sd_error = false; return false; } if (!(cmd->flags & MMC_RSP_PRESENT)) { -- cgit v1.2.3 From 1fcfebfe49f0fe3c3311decdcb3ad411d48feb59 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:38:16 +0100 Subject: mmc: sh-mmcif: reset DMA completion immediately before starting DMA DMA completion can be signalled from the DMA callback and from the error handler. If both are called, the completion struct can enter an inconsistent state. To prevent this move completion initialisation immediately before activating DMA. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 14fafafc12d3..1c37854c0f33 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -419,8 +419,6 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host, if (ret < 0) goto ecfgrx; - init_completion(&host->dma_complete); - return; ecfgrx: @@ -1061,6 +1059,12 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) if (!data) return false; + /* + * Completion can be signalled from DMA callback and error, so, have to + * reset here, before setting .dma_active + */ + init_completion(&host->dma_complete); + if (data->flags & MMC_DATA_READ) { if (host->chan_rx) sh_mmcif_start_dma_rx(host); -- cgit v1.2.3 From b31d6370588f7ebfb25fbba58ca40e192c1b616c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:38:17 +0100 Subject: mmc: sh-mmcif: fix I/O errors The INT_BUFWEN IRQ often arrives with other bits set too. If they are not cleared, an additional IRQ can be triggered, sometimes also after the MMC request has already been completed. This leads to block I/O errors. Earlier Teppei Kamijou also observed these additional interrupts and proposed to explicitly wait for them. This patch chooses an alternative approach of clearing all active bits immediately, when processing the main interrupt. Reported-by: Teppei Kamijou Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 1c37854c0f33..e6a6d2363a4d 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1238,7 +1238,9 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN); sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); } else if (state & INT_BUFWEN) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFWEN); + sh_mmcif_writel(host->addr, MMCIF_CE_INT, + ~(INT_BUFWEN | INT_DTRANE | INT_CMD12DRE | + INT_CMD12RBE | INT_CMD12CRE)); sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); } else if (state & INT_CMD12DRE) { sh_mmcif_writel(host->addr, MMCIF_CE_INT, -- cgit v1.2.3 From 30e531a5457117070fe9ac53610a0f0b0b217f81 Mon Sep 17 00:00:00 2001 From: Teppei Kamijou Date: Wed, 12 Dec 2012 15:38:18 +0100 Subject: mmc: sh-mmcif: report all errors Make error reporting in the driver more verbose. This patch is based on an earlier work by Teppei Kamijou, but we try to not add any new error messages to the log in the normal case to avoid confusing the user, and also add a few more dev_dbg() calls. Signed-off-by: Teppei Kamijou Signed-off-by: Shinya Kuribayashi [g.liakhovetski@gmx.de: avoid producing new errors in normal case] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index e6a6d2363a4d..b4180c7bffc4 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -514,13 +514,16 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) } if (state2 & STS2_CRC_ERR) { - dev_dbg(&host->pd->dev, ": CRC error\n"); + dev_err(&host->pd->dev, " CRC error: state %u, wait %u\n", + host->state, host->wait_for); ret = -EIO; } else if (state2 & STS2_TIMEOUT_ERR) { - dev_dbg(&host->pd->dev, ": Timeout\n"); + dev_err(&host->pd->dev, " Timeout: state %u, wait %u\n", + host->state, host->wait_for); ret = -ETIMEDOUT; } else { - dev_dbg(&host->pd->dev, ": End/Index error\n"); + dev_dbg(&host->pd->dev, " End/Index error: state %u, wait %u\n", + host->state, host->wait_for); ret = -EIO; } return ret; @@ -566,6 +569,7 @@ static bool sh_mmcif_read_block(struct sh_mmcif_host *host) if (host->sd_error) { data->error = sh_mmcif_error_manage(host); + dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); return false; } @@ -606,6 +610,7 @@ static bool sh_mmcif_mread_block(struct sh_mmcif_host *host) if (host->sd_error) { data->error = sh_mmcif_error_manage(host); + dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); return false; } @@ -642,6 +647,7 @@ static bool sh_mmcif_write_block(struct sh_mmcif_host *host) if (host->sd_error) { data->error = sh_mmcif_error_manage(host); + dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); return false; } @@ -682,6 +688,7 @@ static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host) if (host->sd_error) { data->error = sh_mmcif_error_manage(host); + dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); return false; } @@ -823,7 +830,7 @@ static int sh_mmcif_data_trans(struct sh_mmcif_host *host, sh_mmcif_single_read(host, mrq); return 0; default: - dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc); + dev_err(&host->pd->dev, "Unsupported CMD%d\n", opc); return -EINVAL; } } @@ -894,6 +901,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) spin_lock_irqsave(&host->lock, flags); if (host->state != STATE_IDLE) { + dev_dbg(&host->pd->dev, "%s() rejected, state %u\n", __func__, host->state); spin_unlock_irqrestore(&host->lock, flags); mrq->cmd->error = -EAGAIN; mmc_request_done(mmc, mrq); @@ -957,6 +965,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_irqsave(&host->lock, flags); if (host->state != STATE_IDLE) { + dev_dbg(&host->pd->dev, "%s() rejected, state %u\n", __func__, host->state); spin_unlock_irqrestore(&host->lock, flags); return; } @@ -1042,10 +1051,10 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) break; default: cmd->error = sh_mmcif_error_manage(host); - dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n", - cmd->opcode, cmd->error); break; } + dev_dbg(&host->pd->dev, "CMD%d error %d\n", + cmd->opcode, cmd->error); host->sd_error = false; return false; } @@ -1097,8 +1106,11 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) /* Woken up by an error IRQ: abort DMA */ data->error = sh_mmcif_error_manage(host); } else if (!time) { + dev_err(host->mmc->parent, "DMA timeout!\n"); data->error = -ETIMEDOUT; } else if (time < 0) { + dev_err(host->mmc->parent, + "wait_for_completion_...() error %ld!\n", time); data->error = time; } sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, @@ -1167,6 +1179,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) case MMCIF_WAIT_FOR_STOP: if (host->sd_error) { mrq->stop->error = sh_mmcif_error_manage(host); + dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->stop->error); break; } sh_mmcif_get_cmd12response(host, mrq->stop); @@ -1174,8 +1187,10 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) break; case MMCIF_WAIT_FOR_READ_END: case MMCIF_WAIT_FOR_WRITE_END: - if (host->sd_error) + if (host->sd_error) { mrq->data->error = sh_mmcif_error_manage(host); + dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->data->error); + } break; default: BUG(); @@ -1292,7 +1307,7 @@ static void mmcif_timeout_work(struct work_struct *work) /* Don't run after mmc_remove_host() */ return; - dev_dbg(&host->pd->dev, "Timeout waiting for %u, opcode %u\n", + dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n", host->wait_for, mrq->cmd->opcode); spin_lock_irqsave(&host->lock, flags); -- cgit v1.2.3 From aa11d6d892c9cf0170865fadbce04d558d359d1a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 12 Dec 2012 15:45:14 +0100 Subject: mmc: sh-mmcif: simplify IRQ processing The classical way to process IRQs is read out the status, ack all triggered IRQs, possibly mask them, then process them. Follow this simple procesure instead of the current complex custom algorithm. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 65 +++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 46 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index b4180c7bffc4..0189efcb9e12 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -129,6 +129,10 @@ INT_CCSTO | INT_CRCSTO | INT_WDATTO | \ INT_RDATTO | INT_RBSYTO | INT_RSPTO) +#define INT_ALL (INT_RBSYE | INT_CRSPE | INT_BUFREN | \ + INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \ + INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE) + /* CE_INT_MASK */ #define MASK_ALL 0x00000000 #define MASK_MCCSDE (1 << 29) @@ -160,6 +164,11 @@ MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \ MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO) +#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \ + MASK_MBUFREN | MASK_MBUFWEN | \ + MASK_MCMD12DRE | MASK_MBUFRE | MASK_MDTRANE | \ + MASK_MCMD12RBE | MASK_MCMD12CRE) + /* CE_HOST_STS1 */ #define STS1_CMDSEQ (1 << 31) @@ -1233,58 +1242,22 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) { struct sh_mmcif_host *host = dev_id; u32 state; - int err = 0; state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); + sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); + sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); - if (state & INT_ERR_STS) { - /* error interrupts - process first */ - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); - err = 1; - } else if (state & INT_RBSYE) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, - ~(INT_RBSYE | INT_CRSPE)); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE); - } else if (state & INT_CRSPE) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_CRSPE); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE); - } else if (state & INT_BUFREN) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); - } else if (state & INT_BUFWEN) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, - ~(INT_BUFWEN | INT_DTRANE | INT_CMD12DRE | - INT_CMD12RBE | INT_CMD12CRE)); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); - } else if (state & INT_CMD12DRE) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, - ~(INT_CMD12DRE | INT_CMD12RBE | - INT_CMD12CRE | INT_BUFRE)); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); - } else if (state & INT_BUFRE) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); - } else if (state & INT_DTRANE) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, - ~(INT_CMD12DRE | INT_CMD12RBE | - INT_CMD12CRE | INT_DTRANE)); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); - } else if (state & INT_CMD12RBE) { - sh_mmcif_writel(host->addr, MMCIF_CE_INT, - ~(INT_CMD12RBE | INT_CMD12CRE)); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); - } else { - dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state); - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); - sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); - err = 1; - } - if (err) { + if (state & ~MASK_CLEAN) + dev_dbg(&host->pd->dev, "IRQ state = 0x%08x incompletely cleared\n", + state); + + if (state & INT_ERR_STS || state & ~INT_ALL) { host->sd_error = true; - dev_dbg(&host->pd->dev, "int err state = %08x\n", state); + dev_dbg(&host->pd->dev, "int err state = 0x%08x\n", state); } if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { + if (!host->mrq) + dev_dbg(&host->pd->dev, "NULL IRQ state = 0x%08x\n", state); if (!host->dma_active) return IRQ_WAKE_THREAD; else if (host->sd_error) -- cgit v1.2.3 From 5b4c924b1a18f0d04732ee03b408ace39089fdcf Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 26 Dec 2012 10:40:17 +0900 Subject: mmc: queue: exclude asynchronous transfer for special request Unlike normal r/w request, special requests(discard, flush) is finished with a one-time issue_fn. Request change to mqrq_prev makes unnecessary call. Signed-off-by: Seungwon Jeon Reviewed-by: Konstantin Dorfman Signed-off-by: Chris Ball --- drivers/mmc/card/queue.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index fadf52eb5d70..d630d9861e7b 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -24,6 +24,8 @@ #define MMC_QUEUE_SUSPENDED (1 << 0) +#define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH) + /* * Prepare a MMC request. This just filters out odd stuff. */ @@ -58,6 +60,7 @@ static int mmc_queue_thread(void *d) do { struct request *req = NULL; struct mmc_queue_req *tmp; + unsigned int cmd_flags = 0; spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); @@ -67,12 +70,19 @@ static int mmc_queue_thread(void *d) if (req || mq->mqrq_prev->req) { set_current_state(TASK_RUNNING); + cmd_flags = req ? req->cmd_flags : 0; mq->issue_fn(mq, req); /* * Current request becomes previous request * and vice versa. + * In case of special requests, current request + * has been finished. Do not assign it to previous + * request. */ + if (cmd_flags & MMC_REQ_SPECIAL_MASK) + mq->mqrq_cur->req = NULL; + mq->mqrq_prev->brq.mrq.data = NULL; mq->mqrq_prev->req = NULL; tmp = mq->mqrq_prev; -- cgit v1.2.3 From 6035d9730d5825e6e3c225b721a5847a521d6556 Mon Sep 17 00:00:00 2001 From: Konstantin Dorfman Date: Mon, 14 Jan 2013 14:28:17 -0500 Subject: mmc: fix async request mechanism for sequential read scenarios When current request is running on the bus and if next request fetched by mmcqd is NULL, mmc context (mmcqd thread) gets blocked until the current request completes. This means that if new request comes in while the mmcqd thread is blocked, this new request can not be prepared in parallel to current ongoing request. This may result in delaying the new request execution and increase it's latency. This change allows to wake up the MMC thread on new request arrival. Now once the MMC thread is woken up, a new request can be fetched and prepared in parallel to the current running request which means this new request can be started immediately after the current running request completes. With this change read throughput is improved by 16%. Signed-off-by: Konstantin Dorfman Reviewed-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 30 +++++++----- drivers/mmc/card/queue.c | 22 ++++++++- drivers/mmc/card/queue.h | 3 ++ drivers/mmc/core/bus.c | 1 + drivers/mmc/core/core.c | 121 +++++++++++++++++++++++++++++++++++++++++++++-- drivers/mmc/core/core.h | 1 + include/linux/mmc/card.h | 12 +++++ include/linux/mmc/core.h | 3 +- include/linux/mmc/host.h | 17 +++++++ 9 files changed, 191 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 21056b9ef0a0..f79b4688e471 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -113,17 +113,6 @@ struct mmc_blk_data { static DEFINE_MUTEX(open_lock); -enum mmc_blk_status { - MMC_BLK_SUCCESS = 0, - MMC_BLK_PARTIAL, - MMC_BLK_CMD_ERR, - MMC_BLK_RETRY, - MMC_BLK_ABORT, - MMC_BLK_DATA_ERR, - MMC_BLK_ECC_ERR, - MMC_BLK_NOMEDIUM, -}; - module_param(perdev_minors, int, 0444); MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); @@ -1364,8 +1353,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) } else areq = NULL; areq = mmc_start_req(card->host, areq, (int *) &status); - if (!areq) + if (!areq) { + if (status == MMC_BLK_NEW_REQUEST) + mq->flags |= MMC_QUEUE_NEW_REQUEST; return 0; + } mq_rq = container_of(areq, struct mmc_queue_req, mmc_active); brq = &mq_rq->brq; @@ -1438,6 +1430,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) break; case MMC_BLK_NOMEDIUM: goto cmd_abort; + default: + pr_err("%s: Unhandled return value (%d)", + req->rq_disk->disk_name, status); + goto cmd_abort; } if (ret) { @@ -1472,6 +1468,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) int ret; struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; + struct mmc_host *host = card->host; + unsigned long flags; if (req && !mq->mqrq_prev->req) /* claim host only for the first request */ @@ -1486,6 +1484,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) goto out; } + mq->flags &= ~MMC_QUEUE_NEW_REQUEST; if (req && req->cmd_flags & REQ_DISCARD) { /* complete ongoing async transfer before issuing discard */ if (card->host->areq) @@ -1501,11 +1500,16 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) mmc_blk_issue_rw_rq(mq, NULL); ret = mmc_blk_issue_flush(mq, req); } else { + if (!req && host->areq) { + spin_lock_irqsave(&host->context_info.lock, flags); + host->context_info.is_waiting_last_req = true; + spin_unlock_irqrestore(&host->context_info.lock, flags); + } ret = mmc_blk_issue_rw_rq(mq, req); } out: - if (!req) + if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) /* release host only when there are no more requests */ mmc_release_host(card->host); return ret; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index d630d9861e7b..5e0971016ac5 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -22,7 +22,6 @@ #define MMC_QUEUE_BOUNCESZ 65536 -#define MMC_QUEUE_SUSPENDED (1 << 0) #define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH) @@ -72,6 +71,10 @@ static int mmc_queue_thread(void *d) set_current_state(TASK_RUNNING); cmd_flags = req ? req->cmd_flags : 0; mq->issue_fn(mq, req); + if (mq->flags & MMC_QUEUE_NEW_REQUEST) { + mq->flags &= ~MMC_QUEUE_NEW_REQUEST; + continue; /* fetch again */ + } /* * Current request becomes previous request @@ -113,6 +116,8 @@ static void mmc_request_fn(struct request_queue *q) { struct mmc_queue *mq = q->queuedata; struct request *req; + unsigned long flags; + struct mmc_context_info *cntx; if (!mq) { while ((req = blk_fetch_request(q)) != NULL) { @@ -122,7 +127,20 @@ static void mmc_request_fn(struct request_queue *q) return; } - if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) + cntx = &mq->card->host->context_info; + if (!mq->mqrq_cur->req && mq->mqrq_prev->req) { + /* + * New MMC request arrived when MMC thread may be + * blocked on the previous request to be complete + * with no current request fetched + */ + spin_lock_irqsave(&cntx->lock, flags); + if (cntx->is_waiting_last_req) { + cntx->is_new_req = true; + wake_up_interruptible(&cntx->wait); + } + spin_unlock_irqrestore(&cntx->lock, flags); + } else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) wake_up_process(mq->thread); } diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index d2a1eb4b9f9f..e20c27b2b8b4 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -27,6 +27,9 @@ struct mmc_queue { struct task_struct *thread; struct semaphore thread_sem; unsigned int flags; +#define MMC_QUEUE_SUSPENDED (1 << 0) +#define MMC_QUEUE_NEW_REQUEST (1 << 1) + int (*issue_fn)(struct mmc_queue *, struct request *); void *data; struct request_queue *queue; diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 420cb6753c1e..e219c97a02a4 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -321,6 +321,7 @@ int mmc_add_card(struct mmc_card *card) #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif + mmc_init_context_info(card->host); ret = device_add(&card->dev); if (ret) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index aaed7687cf09..8b3a1222e665 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -319,11 +319,44 @@ out: } EXPORT_SYMBOL(mmc_start_bkops); +/* + * mmc_wait_data_done() - done callback for data request + * @mrq: done data request + * + * Wakes up mmc context, passed as a callback to host controller driver + */ +static void mmc_wait_data_done(struct mmc_request *mrq) +{ + mrq->host->context_info.is_done_rcv = true; + wake_up_interruptible(&mrq->host->context_info.wait); +} + static void mmc_wait_done(struct mmc_request *mrq) { complete(&mrq->completion); } +/* + *__mmc_start_data_req() - starts data request + * @host: MMC host to start the request + * @mrq: data request to start + * + * Sets the done callback to be called when request is completed by the card. + * Starts data mmc request execution + */ +static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) +{ + mrq->done = mmc_wait_data_done; + mrq->host = host; + if (mmc_card_removed(host->card)) { + mrq->cmd->error = -ENOMEDIUM; + return -ENOMEDIUM; + } + mmc_start_request(host, mrq); + + return 0; +} + static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) { init_completion(&mrq->completion); @@ -337,6 +370,62 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) return 0; } +/* + * mmc_wait_for_data_req_done() - wait for request completed + * @host: MMC host to prepare the command. + * @mrq: MMC request to wait for + * + * Blocks MMC context till host controller will ack end of data request + * execution or new request notification arrives from the block layer. + * Handles command retries. + * + * Returns enum mmc_blk_status after checking errors. + */ +static int mmc_wait_for_data_req_done(struct mmc_host *host, + struct mmc_request *mrq, + struct mmc_async_req *next_req) +{ + struct mmc_command *cmd; + struct mmc_context_info *context_info = &host->context_info; + int err; + unsigned long flags; + + while (1) { + wait_event_interruptible(context_info->wait, + (context_info->is_done_rcv || + context_info->is_new_req)); + spin_lock_irqsave(&context_info->lock, flags); + context_info->is_waiting_last_req = false; + spin_unlock_irqrestore(&context_info->lock, flags); + if (context_info->is_done_rcv) { + context_info->is_done_rcv = false; + context_info->is_new_req = false; + cmd = mrq->cmd; + if (!cmd->error || !cmd->retries || + mmc_card_removed(host->card)) { + err = host->areq->err_check(host->card, + host->areq); + break; /* return err */ + } else { + pr_info("%s: req failed (CMD%u): %d, retrying...\n", + mmc_hostname(host), + cmd->opcode, cmd->error); + cmd->retries--; + cmd->error = 0; + host->ops->request(host, mrq); + continue; /* wait for done/new event again */ + } + } else if (context_info->is_new_req) { + context_info->is_new_req = false; + if (!next_req) { + err = MMC_BLK_NEW_REQUEST; + break; /* return err */ + } + } + } + return err; +} + static void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) { @@ -426,8 +515,17 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, mmc_pre_req(host, areq->mrq, !host->areq); if (host->areq) { - mmc_wait_for_req_done(host, host->areq->mrq); - err = host->areq->err_check(host->card, host->areq); + err = mmc_wait_for_data_req_done(host, host->areq->mrq, + areq); + if (err == MMC_BLK_NEW_REQUEST) { + if (error) + *error = err; + /* + * The previous request was not completed, + * nothing to return + */ + return NULL; + } /* * Check BKOPS urgency for each R1 response */ @@ -439,7 +537,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, } if (!err && areq) - start_err = __mmc_start_req(host, areq->mrq); + start_err = __mmc_start_data_req(host, areq->mrq); if (host->areq) mmc_post_req(host, host->areq->mrq, 0); @@ -2581,6 +2679,23 @@ int mmc_pm_notify(struct notifier_block *notify_block, } #endif +/** + * mmc_init_context_info() - init synchronization context + * @host: mmc host + * + * Init struct context_info needed to implement asynchronous + * request mechanism, used by mmc core, host driver and mmc requests + * supplier. + */ +void mmc_init_context_info(struct mmc_host *host) +{ + spin_lock_init(&host->context_info.lock); + host->context_info.is_new_req = false; + host->context_info.is_done_rcv = false; + host->context_info.is_waiting_last_req = false; + init_waitqueue_head(&host->context_info.wait); +} + static int __init mmc_init(void) { int ret; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 3bdafbca354f..0272b3284b5e 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -76,5 +76,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host); void mmc_add_card_debugfs(struct mmc_card *card); void mmc_remove_card_debugfs(struct mmc_card *card); +void mmc_init_context_info(struct mmc_host *host); #endif diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 5c69315d60cc..be2500a49925 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -187,6 +187,18 @@ struct sdio_func_tuple; #define SDIO_MAX_FUNCS 7 +enum mmc_blk_status { + MMC_BLK_SUCCESS = 0, + MMC_BLK_PARTIAL, + MMC_BLK_CMD_ERR, + MMC_BLK_RETRY, + MMC_BLK_ABORT, + MMC_BLK_DATA_ERR, + MMC_BLK_ECC_ERR, + MMC_BLK_NOMEDIUM, + MMC_BLK_NEW_REQUEST, +}; + /* The number of MMC physical partitions. These consist of: * boot partitions (2), general purpose partitions (4) in MMC v4.4. */ diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 5bf7c2274fcb..495d1336149c 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -120,6 +120,7 @@ struct mmc_data { s32 host_cookie; /* host private data */ }; +struct mmc_host; struct mmc_request { struct mmc_command *sbc; /* SET_BLOCK_COUNT for multiblock */ struct mmc_command *cmd; @@ -128,9 +129,9 @@ struct mmc_request { struct completion completion; void (*done)(struct mmc_request *);/* completion function */ + struct mmc_host *host; }; -struct mmc_host; struct mmc_card; struct mmc_async_req; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c89a1bb87fa5..523d570f58ad 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -170,6 +170,22 @@ struct mmc_slot { void *handler_priv; }; +/** + * mmc_context_info - synchronization details for mmc context + * @is_done_rcv wake up reason was done request + * @is_new_req wake up reason was new request + * @is_waiting_last_req mmc context waiting for single running request + * @wait wait queue + * @lock lock to protect data fields + */ +struct mmc_context_info { + bool is_done_rcv; + bool is_new_req; + bool is_waiting_last_req; + wait_queue_head_t wait; + spinlock_t lock; +}; + struct regulator; struct mmc_supply { @@ -331,6 +347,7 @@ struct mmc_host { struct dentry *debugfs_root; struct mmc_async_req *areq; /* active async req */ + struct mmc_context_info context_info; /* async synchronization info */ #ifdef CONFIG_FAIL_MMC_REQUEST struct fault_attr fail_mmc_request; -- cgit v1.2.3 From aae66f3849433299ec1850f1ec4cfdf25929587c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 2 Jan 2013 22:34:49 -0700 Subject: mmc: add BCM2835 driver Add a very simple driver for the BCM2835 SoC, which is used in the Raspberry Pi board. Signed-off-by: Stephen Warren Signed-off-by: Chris Ball --- .../devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt | 18 ++ drivers/mmc/host/Kconfig | 11 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-bcm2835.c | 227 +++++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt create mode 100644 drivers/mmc/host/sdhci-bcm2835.c diff --git a/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt new file mode 100644 index 000000000000..59476fbdbfa1 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt @@ -0,0 +1,18 @@ +Broadcom BCM2835 SDHCI controller + +This file documents differences between the core properties described +by mmc.txt and the properties that represent the BCM2835 controller. + +Required properties: +- compatible : Should be "brcm,bcm2835-sdhci". +- clocks : The clock feeding the SDHCI controller. + +Example: + +sdhci: sdhci { + compatible = "brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <2 30>; + clocks = <&clk_mmc>; + bus-width = <4>; +}; diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 8d13c6594520..66a54aa68e25 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -241,6 +241,17 @@ config MMC_SDHCI_S3C_DMA YMMV. +config MMC_SDHCI_BCM2835 + tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" + depends on ARCH_BCM2835 + depends on MMC_SDHCI_PLTFM + select MMC_SDHCI_IO_ACCESSORS + help + This selects the BCM2835 SD/MMC controller. If you have a BCM2835 + platform with SD or MMC devices, say Y or M here. + + If unsure, say N. + config MMC_OMAP tristate "TI OMAP Multimedia Card Interface support" depends on ARCH_OMAP diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index e4e218c930bd..d5ea072207ec 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o +obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o ifeq ($(CONFIG_CB710_DEBUG),y) CFLAGS-cb710-mmc += -DDEBUG diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c new file mode 100644 index 000000000000..453825fcc5cf --- /dev/null +++ b/drivers/mmc/host/sdhci-bcm2835.c @@ -0,0 +1,227 @@ +/* + * BCM2835 SDHCI + * Copyright (C) 2012 Stephen Warren + * Based on U-Boot's MMC driver for the BCM2835 by Oleksandr Tymoshenko & me + * Portions of the code there were obviously based on the Linux kernel at: + * git://github.com/raspberrypi/linux.git rpi-3.6.y + * commit f5b930b "Main bcm2708 linux port" signed-off-by Dom Cobley. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "sdhci-pltfm.h" + +/* + * 400KHz is max freq for card ID etc. Use that as min card clock. We need to + * know the min to enable static calculation of max BCM2835_SDHCI_WRITE_DELAY. + */ +#define MIN_FREQ 400000 + +/* + * The Arasan has a bugette whereby it may lose the content of successive + * writes to registers that are within two SD-card clock cycles of each other + * (a clock domain crossing problem). It seems, however, that the data + * register does not have this problem, which is just as well - otherwise we'd + * have to nobble the DMA engine too. + * + * This should probably be dynamically calculated based on the actual card + * frequency. However, this is the longest we'll have to wait, and doesn't + * seem to slow access down too much, so the added complexity doesn't seem + * worth it for now. + * + * 1/MIN_FREQ is (max) time per tick of eMMC clock. + * 2/MIN_FREQ is time for two ticks. + * Multiply by 1000000 to get uS per two ticks. + * *1000000 for uSecs. + * +1 for hack rounding. + */ +#define BCM2835_SDHCI_WRITE_DELAY (((2 * 1000000) / MIN_FREQ) + 1) + +struct bcm2835_sdhci { + struct clk *clk; + u32 shadow; +}; + +static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg) +{ + writel(val, host->ioaddr + reg); + + udelay(BCM2835_SDHCI_WRITE_DELAY); +} + +static inline u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg) +{ + u32 val = readl(host->ioaddr + reg); + + if (reg == SDHCI_CAPABILITIES) + val |= SDHCI_CAN_VDD_330; + + return val; +} + +static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv; + u32 oldval = (reg == SDHCI_COMMAND) ? bcm2835_host->shadow : + bcm2835_sdhci_readl(host, reg & ~3); + u32 word_num = (reg >> 1) & 1; + u32 word_shift = word_num * 16; + u32 mask = 0xffff << word_shift; + u32 newval = (oldval & ~mask) | (val << word_shift); + + if (reg == SDHCI_TRANSFER_MODE) + bcm2835_host->shadow = newval; + else + bcm2835_sdhci_writel(host, newval, reg & ~3); +} + +static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg) +{ + u32 val = bcm2835_sdhci_readl(host, (reg & ~3)); + u32 word_num = (reg >> 1) & 1; + u32 word_shift = word_num * 16; + u32 word = (val >> word_shift) & 0xffff; + + return word; +} + +static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) +{ + u32 oldval = bcm2835_sdhci_readl(host, reg & ~3); + u32 byte_num = reg & 3; + u32 byte_shift = byte_num * 8; + u32 mask = 0xff << byte_shift; + u32 newval = (oldval & ~mask) | (val << byte_shift); + + bcm2835_sdhci_writel(host, newval, reg & ~3); +} + +static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg) +{ + u32 val = bcm2835_sdhci_readl(host, (reg & ~3)); + u32 byte_num = reg & 3; + u32 byte_shift = byte_num * 8; + u32 byte = (val >> byte_shift) & 0xff; + + return byte; +} + +static unsigned int bcm2835_sdhci_get_max_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv; + + return clk_get_rate(bcm2835_host->clk); +} + +unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host) +{ + return MIN_FREQ; +} + +unsigned int bcm2835_sdhci_get_timeout_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv; + + return clk_get_rate(bcm2835_host->clk); +} + +static struct sdhci_ops bcm2835_sdhci_ops = { + .write_l = bcm2835_sdhci_writel, + .write_w = bcm2835_sdhci_writew, + .write_b = bcm2835_sdhci_writeb, + .read_l = bcm2835_sdhci_readl, + .read_w = bcm2835_sdhci_readw, + .read_b = bcm2835_sdhci_readb, + .get_max_clock = bcm2835_sdhci_get_max_clock, + .get_min_clock = bcm2835_sdhci_get_min_clock, + .get_timeout_clock = bcm2835_sdhci_get_timeout_clock, +}; + +static struct sdhci_pltfm_data bcm2835_sdhci_pdata = { + .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION, + .ops = &bcm2835_sdhci_ops, +}; + +static int bcm2835_sdhci_probe(struct platform_device *pdev) +{ + struct sdhci_host *host; + struct bcm2835_sdhci *bcm2835_host; + struct sdhci_pltfm_host *pltfm_host; + int ret; + + host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata); + if (IS_ERR(host)) + return PTR_ERR(host); + + bcm2835_host = devm_kzalloc(&pdev->dev, sizeof(*bcm2835_host), + GFP_KERNEL); + if (!bcm2835_host) { + dev_err(mmc_dev(host->mmc), + "failed to allocate bcm2835_sdhci\n"); + return -ENOMEM; + } + + pltfm_host = sdhci_priv(host); + pltfm_host->priv = bcm2835_host; + + bcm2835_host->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(bcm2835_host->clk)) { + ret = PTR_ERR(bcm2835_host->clk); + goto err; + } + + return sdhci_add_host(host); + +err: + sdhci_pltfm_free(pdev); + return ret; +} + +static int bcm2835_sdhci_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); + + sdhci_remove_host(host, dead); + sdhci_pltfm_free(pdev); + + return 0; +} + +static const struct of_device_id bcm2835_sdhci_of_match[] = { + { .compatible = "brcm,bcm2835-sdhci" }, + { } +}; +MODULE_DEVICE_TABLE(of, bcm2835_sdhci_of_match); + +static struct platform_driver bcm2835_sdhci_driver = { + .driver = { + .name = "sdhci-bcm2835", + .owner = THIS_MODULE, + .of_match_table = bcm2835_sdhci_of_match, + .pm = SDHCI_PLTFM_PMOPS, + }, + .probe = bcm2835_sdhci_probe, + .remove = bcm2835_sdhci_remove, +}; +module_platform_driver(bcm2835_sdhci_driver); + +MODULE_DESCRIPTION("BCM2835 SDHCI driver"); +MODULE_AUTHOR("Stephen Warren"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From f6f926885faa07aa9f54617b4e59fa33074500f5 Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Sat, 5 Jan 2013 17:18:28 +0800 Subject: mmc: sdhci: disable interrupt before free_irq Current code missed disabling interrupts before free irq which is shared. Notice below comments for function free_irq (kernel/irq/manage.c): On a shared IRQ the caller must ensure the interrupt is disabled on the card it drives before calling this function. Original code has below issue during suspend/resume when multiple SD hosts share the same IRQ: 1. Assume there are two hosts (host1 for emmc while host2 for sd) share the same mmc irq. 2. When system suspend, host2 will be suspended before host1. So the sequence is below: step1: irq handler for host2 removed -> step2: irq handler for host1 removed and irq disabled -> ... system suspended ... ... system resumed ... step3: irq enabled and the irq handler for host1 restored -> step4: irq handler for host2 restored 3. So there is the buggy time slot that the irq is enabled but the irq handler for host2 is removed. Then host2 interrupt can be triggered but can't be handled at that moment. Signed-off-by: Jialing Fu Signed-off-by: Kevin Liu Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1b97fe2d70ab..1165376592b9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2487,6 +2487,7 @@ int sdhci_suspend_host(struct sdhci_host *host) return ret; } + sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); free_irq(host->irq, host); return ret; @@ -3142,6 +3143,7 @@ int sdhci_add_host(struct sdhci_host *host) #ifdef SDHCI_USE_LEDS_CLASS reset: sdhci_reset(host, SDHCI_RESET_ALL); + sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); free_irq(host->irq, host); #endif untasklet: @@ -3184,6 +3186,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) if (!dead) sdhci_reset(host, SDHCI_RESET_ALL); + sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); free_irq(host->irq, host); del_timer_sync(&host->timer); -- cgit v1.2.3 From 8678b8181dacb1804325f70e63a176873ce9784f Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Sat, 5 Jan 2013 17:21:33 +0800 Subject: mmc: sdhci: add IRQ wake up support Don't disable SD Host IRQ during suspend if it is wake up source. Enable wakeup event during suspend. Signed-off-by: Jialing Fu Signed-off-by: Kevin Liu Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 60 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1165376592b9..b93076764ddd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2458,6 +2458,32 @@ out: \*****************************************************************************/ #ifdef CONFIG_PM +void sdhci_enable_irq_wakeups(struct sdhci_host *host) +{ + u8 val; + u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE + | SDHCI_WAKE_ON_INT; + + val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); + val |= mask ; + /* Avoid fake wake up */ + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) + val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE); + sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); +} +EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); + +void sdhci_disable_irq_wakeups(struct sdhci_host *host) +{ + u8 val; + u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE + | SDHCI_WAKE_ON_INT; + + val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); + val &= ~mask; + sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); +} +EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups); int sdhci_suspend_host(struct sdhci_host *host) { @@ -2487,9 +2513,13 @@ int sdhci_suspend_host(struct sdhci_host *host) return ret; } - sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); - free_irq(host->irq, host); - + if (!device_may_wakeup(mmc_dev(host->mmc))) { + sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); + free_irq(host->irq, host); + } else { + sdhci_enable_irq_wakeups(host); + enable_irq_wake(host->irq); + } return ret; } @@ -2504,10 +2534,15 @@ int sdhci_resume_host(struct sdhci_host *host) host->ops->enable_dma(host); } - ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, - mmc_hostname(host->mmc), host); - if (ret) - return ret; + if (!device_may_wakeup(mmc_dev(host->mmc))) { + ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, + mmc_hostname(host->mmc), host); + if (ret) + return ret; + } else { + sdhci_disable_irq_wakeups(host); + disable_irq_wake(host->irq); + } if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { @@ -2535,17 +2570,6 @@ int sdhci_resume_host(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_resume_host); - -void sdhci_enable_irq_wakeups(struct sdhci_host *host) -{ - u8 val; - val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); - val |= SDHCI_WAKE_ON_INT; - sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); -} - -EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); - #endif /* CONFIG_PM */ #ifdef CONFIG_PM_RUNTIME -- cgit v1.2.3 From 9ddc4f27cf9ebb413c713fb4419c4f5e80c6a5f3 Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Mon, 14 Jan 2013 14:38:53 -0500 Subject: mmc: sdhci-pxav3: add IRQ wake up support [cjb: The MMP3 architecture requires a registered interrupt to retire wfi when waking from suspend.] Signed-off-by: Jialing Fu Signed-off-by: Kevin Liu Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pxav3.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index b7ee7761bc26..3d20c10fc571 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -311,6 +311,13 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); + if (pdata->pm_caps & MMC_PM_KEEP_POWER) { + device_init_wakeup(&pdev->dev, 1); + host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ; + } else { + device_init_wakeup(&pdev->dev, 0); + } + return 0; err_add_host: -- cgit v1.2.3 From 22c07f36269befbf092d833d2c7cf0e27a3e9d1f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 7 Jan 2013 16:31:08 +0200 Subject: mmc: sdhci: introduce sdhci_update_clock helper to re-enable clock There are three places where same piece of code is used. Let's split it to a separate function. Signed-off-by: Andy Shevchenko Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index b93076764ddd..336ab06aeb2f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1189,6 +1189,15 @@ out: host->clock = clock; } +static inline void sdhci_update_clock(struct sdhci_host *host) +{ + unsigned int clock; + + clock = host->clock; + host->clock = 0; + sdhci_set_clock(host, clock); +} + static int sdhci_set_power(struct sdhci_host *host, unsigned short power) { u8 pwr = 0; @@ -1418,7 +1427,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) if (host->version >= SDHCI_SPEC_300) { u16 clk, ctrl_2; - unsigned int clock; /* In case of UHS-I modes, set High Speed Enable */ if ((ios->timing == MMC_TIMING_MMC_HS200) || @@ -1458,9 +1466,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); /* Re-enable SD Clock */ - clock = host->clock; - host->clock = 0; - sdhci_set_clock(host, clock); + sdhci_update_clock(host); } @@ -1491,9 +1497,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) } /* Re-enable SD Clock */ - clock = host->clock; - host->clock = 0; - sdhci_set_clock(host, clock); + sdhci_update_clock(host); } else sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); @@ -2083,14 +2087,9 @@ static void sdhci_tasklet_finish(unsigned long param) (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { /* Some controllers need this kick or reset won't work here */ - if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { - unsigned int clock; - + if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) /* This is to force an update */ - clock = host->clock; - host->clock = 0; - sdhci_set_clock(host, clock); - } + sdhci_update_clock(host); /* Spec says we should do both at the same time, but Ricoh controllers do not like that. */ -- cgit v1.2.3 From 290d934172fd751c26f357a93836d54273f835b1 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 15 Jan 2013 23:19:54 +0800 Subject: mmc: sdhci-esdhc-imx: remove ESDHC_CD_GPIO handling from IO accessory With commit 9444e07 (mmc: remove unncessary mmc_gpio_free_cd() call from slot-gpio users) in place, the ESDHC_CD_GPIO handling in IO accessories becomes unnecessary. Remove it. Signed-off-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index dd7fcc137644..ae68bc965ab5 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -150,16 +150,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) u32 val = readl(host->ioaddr + reg); - if (unlikely(reg == SDHCI_PRESENT_STATE)) { - /* - * After SDHCI core gets improved to never query - * SDHCI_CARD_PRESENT state in GPIO case, we can - * remove this check. - */ - if (boarddata->cd_type == ESDHC_CD_GPIO) - val &= ~SDHCI_CARD_PRESENT; - } - if (unlikely(reg == SDHCI_CAPABILITIES)) { /* In FSL esdhc IC module, only bit20 is used to indicate the * ADMA2 capability of esdhc, but this bit is messed up on @@ -192,13 +182,6 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) u32 data; if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { - if (boarddata->cd_type == ESDHC_CD_GPIO) - /* - * These interrupts won't work with a custom - * card_detect gpio (only applied to mx25/35) - */ - val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); - if (val & SDHCI_INT_CARD_INT) { /* * Clear and then set D3CD bit to avoid missing the -- cgit v1.2.3 From 9d8b28e5d09746a0fea5aeec63b78586795e82de Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 16 Jan 2013 14:13:57 +0100 Subject: mmc: mvsdio: use slot-gpio infrastructure for write protect gpio The MMC core subsystem provides in drivers/mmc/core/slot-gpio.c a nice set of helper functions to simplify the management of the write protect GPIO in MMC host drivers. This patch migrates the mvsdio driver to using those helpers, which will make the ->probe() code simpler, and therefore ease the process of adding a Device Tree binding for this driver. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn Tested-by: Stefan Peter Tested-by: Florian Fainelli Signed-off-by: Jason Cooper Signed-off-by: Chris Ball --- drivers/mmc/host/mvsdio.c | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index f8dd36102949..c6dc8fd696ab 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,6 @@ struct mvsd_host { struct device *dev; struct clk *clk; int gpio_card_detect; - int gpio_write_protect; }; #define mvsd_write(offs, val) writel(val, iobase + (offs)) @@ -564,20 +564,6 @@ static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_unlock_irqrestore(&host->lock, flags); } -static int mvsd_get_ro(struct mmc_host *mmc) -{ - struct mvsd_host *host = mmc_priv(mmc); - - if (host->gpio_write_protect) - return gpio_get_value(host->gpio_write_protect); - - /* - * Board doesn't support read only detection; let the mmc core - * decide what to do. - */ - return -ENOSYS; -} - static void mvsd_power_up(struct mvsd_host *host) { void __iomem *iobase = host->base; @@ -674,7 +660,7 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) static const struct mmc_host_ops mvsd_ops = { .request = mvsd_request, - .get_ro = mvsd_get_ro, + .get_ro = mmc_gpio_get_ro, .set_ios = mvsd_set_ios, .enable_sdio_irq = mvsd_enable_sdio_irq, }; @@ -793,15 +779,7 @@ static int __init mvsd_probe(struct platform_device *pdev) if (!host->gpio_card_detect) mmc->caps |= MMC_CAP_NEEDS_POLL; - if (mvsd_data->gpio_write_protect) { - ret = devm_gpio_request_one(&pdev->dev, - mvsd_data->gpio_write_protect, - GPIOF_IN, DRIVER_NAME " wp"); - if (ret == 0) { - host->gpio_write_protect = - mvsd_data->gpio_write_protect; - } - } + mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); platform_set_drvdata(pdev, mmc); @@ -820,6 +798,7 @@ static int __init mvsd_probe(struct platform_device *pdev) out: if (mmc) { + mmc_gpio_free_ro(mmc); if (!IS_ERR(host->clk)) clk_disable_unprepare(host->clk); mmc_free_host(mmc); @@ -834,6 +813,7 @@ static int __exit mvsd_remove(struct platform_device *pdev) struct mvsd_host *host = mmc_priv(mmc); + mmc_gpio_free_ro(mmc); mmc_remove_host(mmc); del_timer_sync(&host->timer); mvsd_power_down(host); -- cgit v1.2.3 From aa3738e9565ffb67e296483087ff1d2f116fa81a Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 16 Jan 2013 14:13:58 +0100 Subject: mmc: mvsdio: use slot-gpio for card detect gpio The MMC core subsystem provides in drivers/mmc/core/slot-gpio.c a nice set of helper functions to simplify the management of the card detect GPIO in MMC host drivers. This patch migrates the mvsdio driver to using those helpers, which will make the ->probe() code simpler, and therefore ease the process of adding a Device Tree binding for this driver. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn Tested-by: Stefan Peter Tested-by: Florian Fainelli Signed-off-by: Jason Cooper Signed-off-by: Chris Ball --- drivers/mmc/host/mvsdio.c | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index c6dc8fd696ab..704b7a3fe873 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -52,7 +52,6 @@ struct mvsd_host { struct mmc_host *mmc; struct device *dev; struct clk *clk; - int gpio_card_detect; }; #define mvsd_write(offs, val) writel(val, iobase + (offs)) @@ -538,13 +537,6 @@ static void mvsd_timeout_timer(unsigned long data) mmc_request_done(host->mmc, mrq); } -static irqreturn_t mvsd_card_detect_irq(int irq, void *dev) -{ - struct mvsd_host *host = dev; - mmc_detect_change(host->mmc, msecs_to_jiffies(100)); - return IRQ_HANDLED; -} - static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct mvsd_host *host = mmc_priv(mmc); @@ -757,26 +749,11 @@ static int __init mvsd_probe(struct platform_device *pdev) if (!IS_ERR(host->clk)) clk_prepare_enable(host->clk); - if (mvsd_data->gpio_card_detect) { - ret = devm_gpio_request_one(&pdev->dev, - mvsd_data->gpio_card_detect, - GPIOF_IN, DRIVER_NAME " cd"); - if (ret == 0) { - irq = gpio_to_irq(mvsd_data->gpio_card_detect); - ret = devm_request_irq(&pdev->dev, irq, - mvsd_card_detect_irq, - IRQ_TYPE_EDGE_RISING | - IRQ_TYPE_EDGE_FALLING, - DRIVER_NAME " cd", host); - if (ret == 0) - host->gpio_card_detect = - mvsd_data->gpio_card_detect; - else - devm_gpio_free(&pdev->dev, - mvsd_data->gpio_card_detect); - } - } - if (!host->gpio_card_detect) + if (gpio_is_valid(mvsd_data->gpio_card_detect)) { + ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect); + if (ret) + goto out; + } else mmc->caps |= MMC_CAP_NEEDS_POLL; mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); @@ -789,15 +766,16 @@ static int __init mvsd_probe(struct platform_device *pdev) pr_notice("%s: %s driver initialized, ", mmc_hostname(mmc), DRIVER_NAME); - if (host->gpio_card_detect) + if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) printk("using GPIO %d for card detection\n", - host->gpio_card_detect); + mvsd_data->gpio_card_detect); else printk("lacking card detect (fall back to polling)\n"); return 0; out: if (mmc) { + mmc_gpio_free_cd(mmc); mmc_gpio_free_ro(mmc); if (!IS_ERR(host->clk)) clk_disable_unprepare(host->clk); @@ -813,6 +791,7 @@ static int __exit mvsd_remove(struct platform_device *pdev) struct mvsd_host *host = mmc_priv(mmc); + mmc_gpio_free_cd(mmc); mmc_gpio_free_ro(mmc); mmc_remove_host(mmc); del_timer_sync(&host->timer); -- cgit v1.2.3 From 182ce2162bcc2a1f7bb7137d621a6ea97ccdd635 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 16 Jan 2013 14:13:59 +0100 Subject: mmc: mvsdio: implement a Device Tree binding This patch adds a simple Device Tree binding for the mvsdio driver, as well as the necessary documentation for it. Compatibility with non-DT platforms is preserved, by keeping the platform_data based initialization. We introduce a small difference between non-DT and DT platforms: DT platforms are required to provide a clocks = <...> property, which the driver uses to get the frequency of the clock that goes to the SDIO IP. The behaviour on non-DT platforms is kept unchanged: a clock reference is not mandatory, but the clock frequency must be passed in the "clock" field of the mvsdio_platform_data structure. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn Tested-by: Stefan Peter Tested-by: Florian Fainelli Signed-off-by: Jason Cooper Signed-off-by: Chris Ball --- .../devicetree/bindings/mmc/orion-sdio.txt | 17 ++++++ drivers/mmc/host/mvsdio.c | 64 +++++++++++++++++----- 2 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/orion-sdio.txt diff --git a/Documentation/devicetree/bindings/mmc/orion-sdio.txt b/Documentation/devicetree/bindings/mmc/orion-sdio.txt new file mode 100644 index 000000000000..84f0ebd67a13 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/orion-sdio.txt @@ -0,0 +1,17 @@ +* Marvell orion-sdio controller + +This file documents differences between the core properties in mmc.txt +and the properties used by the orion-sdio driver. + +- compatible: Should be "marvell,orion-sdio" +- clocks: reference to the clock of the SDIO interface + +Example: + + mvsdio@d00d4000 { + compatible = "marvell,orion-sdio"; + reg = <0xd00d4000 0x200>; + interrupts = <54>; + clocks = <&gateclk 17>; + status = "disabled"; + }; diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 704b7a3fe873..78d3abf837c2 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -681,17 +683,17 @@ mv_conf_mbus_windows(struct mvsd_host *host, static int __init mvsd_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct mmc_host *mmc = NULL; struct mvsd_host *host = NULL; - const struct mvsdio_platform_data *mvsd_data; const struct mbus_dram_target_info *dram; struct resource *r; int ret, irq; + int gpio_card_detect, gpio_write_protect; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - mvsd_data = pdev->dev.platform_data; - if (!r || irq < 0 || !mvsd_data) + if (!r || irq < 0) return -ENXIO; mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); @@ -703,8 +705,39 @@ static int __init mvsd_probe(struct platform_device *pdev) host = mmc_priv(mmc); host->mmc = mmc; host->dev = &pdev->dev; - host->base_clock = mvsd_data->clock / 2; - host->clk = ERR_PTR(-EINVAL); + + /* + * Some non-DT platforms do not pass a clock, and the clock + * frequency is passed through platform_data. On DT platforms, + * a clock must always be passed, even if there is no gatable + * clock associated to the SDIO interface (it can simply be a + * fixed rate clock). + */ + host->clk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(host->clk)) + clk_prepare_enable(host->clk); + + if (np) { + if (IS_ERR(host->clk)) { + dev_err(&pdev->dev, "DT platforms must have a clock associated\n"); + ret = -EINVAL; + goto out; + } + + host->base_clock = clk_get_rate(host->clk) / 2; + gpio_card_detect = of_get_named_gpio(np, "cd-gpios", 0); + gpio_write_protect = of_get_named_gpio(np, "wp-gpios", 0); + } else { + const struct mvsdio_platform_data *mvsd_data; + mvsd_data = pdev->dev.platform_data; + if (!mvsd_data) { + ret = -ENXIO; + goto out; + } + host->base_clock = mvsd_data->clock / 2; + gpio_card_detect = mvsd_data->gpio_card_detect; + gpio_write_protect = mvsd_data->gpio_write_protect; + } mmc->ops = &mvsd_ops; @@ -743,20 +776,14 @@ static int __init mvsd_probe(struct platform_device *pdev) goto out; } - /* Not all platforms can gate the clock, so it is not - an error if the clock does not exists. */ - host->clk = devm_clk_get(&pdev->dev, NULL); - if (!IS_ERR(host->clk)) - clk_prepare_enable(host->clk); - - if (gpio_is_valid(mvsd_data->gpio_card_detect)) { - ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect); + if (gpio_is_valid(gpio_card_detect)) { + ret = mmc_gpio_request_cd(mmc, gpio_card_detect); if (ret) goto out; } else mmc->caps |= MMC_CAP_NEEDS_POLL; - mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); + mmc_gpio_request_ro(mmc, gpio_write_protect); setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); platform_set_drvdata(pdev, mmc); @@ -768,7 +795,7 @@ static int __init mvsd_probe(struct platform_device *pdev) mmc_hostname(mmc), DRIVER_NAME); if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) printk("using GPIO %d for card detection\n", - mvsd_data->gpio_card_detect); + gpio_card_detect); else printk("lacking card detect (fall back to polling)\n"); return 0; @@ -832,12 +859,19 @@ static int mvsd_resume(struct platform_device *dev) #define mvsd_resume NULL #endif +static const struct of_device_id mvsdio_dt_ids[] = { + { .compatible = "marvell,orion-sdio" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mvsdio_dt_ids); + static struct platform_driver mvsd_driver = { .remove = __exit_p(mvsd_remove), .suspend = mvsd_suspend, .resume = mvsd_resume, .driver = { .name = DRIVER_NAME, + .of_match_table = mvsdio_dt_ids, }, }; -- cgit v1.2.3 From d2938758caae523768f60208dbc8a487be3f0bd5 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Mon, 28 Jan 2013 06:26:53 -0500 Subject: mmc: mvsdio: add pinctrl integration On many Marvell SoCs, the pins used for the SDIO interface are part of the MPP pins, that are muxable pins. In order to get the muxing of those pins correct, this commit integrates the mvsdio driver with the pinctrl infrastructure by calling devm_pinctrl_get_select_default() during ->probe(). Note that we permit this function to fail because not all Marvell platforms have yet been fully converted to using the pinctrl infrastructure. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn Tested-by: Stefan Peter Tested-by: Florian Fainelli Signed-off-by: Jason Cooper Signed-off-by: Chris Ball --- drivers/mmc/host/mvsdio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 78d3abf837c2..145cdaf000d1 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -690,6 +691,7 @@ static int __init mvsd_probe(struct platform_device *pdev) struct resource *r; int ret, irq; int gpio_card_detect, gpio_write_protect; + struct pinctrl *pinctrl; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); @@ -706,6 +708,10 @@ static int __init mvsd_probe(struct platform_device *pdev) host->mmc = mmc; host->dev = &pdev->dev; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_warn(&pdev->dev, "no pins associated\n"); + /* * Some non-DT platforms do not pass a clock, and the clock * frequency is passed through platform_data. On DT platforms, -- cgit v1.2.3 From f18bfba41ea0c2f3af82df2a6fc519af87004355 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 12 Dec 2012 10:06:26 +0100 Subject: arm: mvebu: Update defconfig with Marvell RTC support The RTC class driver is already part of the mvebu_defconfig but the Marvell internal RTC not yet. Now that its support is added for mvebu let's update the config file. Signed-off-by: Gregory CLEMENT Tested-by: Florian Fainelli Acked-by: Arnd Bergmann Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index cbd91bce1ca9..9d3922bf7372 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -41,6 +41,7 @@ CONFIG_GPIO_SYSFS=y # CONFIG_USB_SUPPORT is not set CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_S35390A=y +CONFIG_RTC_DRV_MV=y CONFIG_DMADEVICES=y CONFIG_MV_XOR=y # CONFIG_IOMMU_SUPPORT is not set -- cgit v1.2.3 From 71e2a396234d5b044c50145ec9d05648a618c0d1 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:17 +0100 Subject: arm: mvebu: enable SDIO support in mvebu_defconfig Now that the mvsdio driver has gained Device Tree support and the necessary Device Tree informations has been added for Armada 370 and Armada XP platforms, we enable the MMC subsystem and the mvsdio driver in mvebu_defconfig. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 9d3922bf7372..f69a7159f787 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -39,6 +39,8 @@ CONFIG_SERIAL_8250_DW=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y # CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_MVSDIO=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_S35390A=y CONFIG_RTC_DRV_MV=y -- cgit v1.2.3 From 0c8cb1d4ae7d1a96be6a0bef18e7f44d88a18fdf Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:18 +0100 Subject: arm: mvebu: enable mwifiex driver in mvebu_defconfig The Globalscale Mirabox platform, based on the Armada 370 from Marvell, has a SD8787 Wireless chip connected on the SDIO interface. Now that the mvsdio has a Device Tree binding, and the necessary Device Tree informations have been added at the SoC and board level, let's enable the mwifiex driver for the Wireless part of the SD8787 chip. For now, the driver gets probed correctly, detects a device and shows the network interfaces. However, scanning Wifi networks doesn't work for now, with a 'CMD_RESP: cmd 0x6 error, result=0x1' message. This will have to be investigated separately. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index f69a7159f787..6243175e845a 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -24,6 +24,7 @@ CONFIG_ARM_APPENDED_DTB=y CONFIG_VFP=y CONFIG_NET=y CONFIG_INET=y +CONFIG_CFG80211=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_SD=y CONFIG_ATA=y @@ -31,6 +32,8 @@ CONFIG_SATA_MV=y CONFIG_NETDEVICES=y CONFIG_MVNETA=y CONFIG_MARVELL_PHY=y +CONFIG_MWIFIEX=y +CONFIG_MWIFIEX_SDIO=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_I2C=y -- cgit v1.2.3 From c9b7a72d988d3474f3127cd39084d18bcc2df3df Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:19 +0100 Subject: arm: mvebu: enable btmrvl driver in mvebu_defconfig The Globalscale Mirabox platform, based on the Armada 370 from Marvell, has a SD8787 Wireless/Bluetooth chip connected on the SDIO interface. Now that the mvsdio has a Device Tree binding, and the necessary Device Tree informations have been added at the SoC and board level, let's enable the btmrvl driver for the Bluetooth part of the SD8787 chip. For now, the driver gets probed correctly, detects the device but apparently fails to push the firmware to the device: Bluetooth: vendor=0x2df, device=0x911a, class=255, fn=2 Bluetooth: FW failed to be active in time! Bluetooth: Downloading firmware failed! Bluetooth: vendor=0x2df, device=0x911b, class=255, fn=3 Bluetooth: FW failed to be active in time! Bluetooth: Downloading firmware failed! This will have to be investigated separately. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 6243175e845a..02adb5dfb773 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -24,6 +24,9 @@ CONFIG_ARM_APPENDED_DTB=y CONFIG_VFP=y CONFIG_NET=y CONFIG_INET=y +CONFIG_BT=y +CONFIG_BT_MRVL=y +CONFIG_BT_MRVL_SDIO=y CONFIG_CFG80211=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_SD=y -- cgit v1.2.3 From 572aab7a2b8d0001d98f84a03b4a55f8dadf3146 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 7 Jan 2013 17:27:14 +0100 Subject: arm: mvebu: add LEDs support to defconfig file The OpenBlocks AX3-4 platform has several LEDs, so it sounds wise to enable LED support in mvebu_defconfig. We anticipate that more platforms using Marvell EBU SoCs will have LEDs in the future. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 02adb5dfb773..4e6f0ceb9b12 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -47,6 +47,11 @@ CONFIG_GPIO_SYSFS=y # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y CONFIG_MMC_MVSDIO=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_S35390A=y CONFIG_RTC_DRV_MV=y -- cgit v1.2.3 From 25026d0d21faefe59aa316bf9ae29b56755e4e05 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Thu, 10 Jan 2013 22:01:08 +0100 Subject: ARM: Kirkwood: Remove redundent USB clock alias Now that USB is instantiated via DT, and the USB DT node has a clocks property, we no longer need a C coded clock alias. Remove it. Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/mach-kirkwood/board-dt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 95cc04d14b65..2c884feee503 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -55,10 +55,6 @@ static void __init kirkwood_legacy_clk_init(void) orion_clkdev_add("0", "pcie", of_clk_get_from_provider(&clkspec)); - clkspec.args[0] = CGC_BIT_USB0; - orion_clkdev_add(NULL, "orion-ehci.0", - of_clk_get_from_provider(&clkspec)); - clkspec.args[0] = CGC_BIT_PEX1; orion_clkdev_add("1", "pcie", of_clk_get_from_provider(&clkspec)); -- cgit v1.2.3 From 970a43c76ffb85fbb3d215e5c2b91074f5e33768 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Thu, 10 Jan 2013 22:01:09 +0100 Subject: ARM: Kirkwood: Remove redundent SDIO clock alias Now that SDIO is instantiated via DT, and the SDIO DT node has a clocks property, we no longer need a C coded clock alias. Remove it. Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/mach-kirkwood/board-dt.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 2c884feee503..8eac5487773b 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -62,11 +62,6 @@ static void __init kirkwood_legacy_clk_init(void) clkspec.args[0] = CGC_BIT_GE1; orion_clkdev_add(NULL, "mv643xx_eth_port.1", of_clk_get_from_provider(&clkspec)); - - clkspec.args[0] = CGC_BIT_SDIO; - orion_clkdev_add(NULL, "mvsdio", - of_clk_get_from_provider(&clkspec)); - } static void __init kirkwood_of_clk_init(void) -- cgit v1.2.3 From 9f86f2761117f9031c349c1c1e80d9f64820e6f6 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Sun, 13 Jan 2013 09:54:07 -0800 Subject: ARM: dove: update dove_defconfig with a few useful options This refreshes the dove_defconfig, and adds: PRINTK_TIME DEVTMPFS EXT4 They're quite useful, and allows booting a cubox ubuntu rootfs on SD card, since that by default uses ext4. The rest of the churn is due to options and defaults moving around, no functional difference. Signed-off-by: Olof Johansson Cc: Sebastian Hesselbarth Signed-off-by: Jason Cooper --- arch/arm/configs/dove_defconfig | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig index 0b7ee92c5713..3fe8dae8d32d 100644 --- a/arch/arm/configs/dove_defconfig +++ b/arch/arm/configs/dove_defconfig @@ -1,26 +1,24 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_EXPERT=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y CONFIG_ARCH_DOVE=y CONFIG_MACH_DOVE_DB=y CONFIG_MACH_CM_A510=y CONFIG_MACH_DOVE_DT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_AEABI=y +CONFIG_HIGHMEM=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_HIGHMEM=y -CONFIG_USE_OF=y -CONFIG_ATAGS=y CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y -CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y CONFIG_VFP=y CONFIG_NET=y CONFIG_PACKET=y @@ -32,8 +30,9 @@ CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -57,7 +56,6 @@ CONFIG_ATA=y CONFIG_SATA_MV=y CONFIG_NETDEVICES=y CONFIG_MV643XX_ETH=y -# CONFIG_NETDEV_10000 is not set CONFIG_INPUT_POLLDEV=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y @@ -68,10 +66,7 @@ CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_DEVKMEM is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_PCI is not set CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y @@ -81,13 +76,11 @@ CONFIG_SPI=y CONFIG_SPI_ORION=y # CONFIG_HWMON is not set CONFIG_USB=y -CONFIG_USB_DEVICEFS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_STORAGE=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_IO_ACCESSORS=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_DOVE=y CONFIG_NEW_LEDS=y @@ -104,6 +97,7 @@ CONFIG_MV_XOR=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT4_FS=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_UDF_FS=m @@ -112,24 +106,20 @@ CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y -CONFIG_PARTITION_ADVANCED=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_850=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_2=y CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set CONFIG_TIMER_STATS=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m @@ -138,7 +128,6 @@ CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_BLOWFISH=y CONFIG_CRYPTO_TEA=y CONFIG_CRYPTO_TWOFISH=y @@ -147,5 +136,4 @@ CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_MV_CESA=y CONFIG_CRC_CCITT=y -CONFIG_CRC16=y CONFIG_LIBCRC32C=y -- cgit v1.2.3 From 48be9ac930086f7605fb4959936f568e865b2cff Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Feb 2013 18:19:16 +0100 Subject: ARM: Dove: split legacy and DT setup In the beginning of DT for Dove it was reasonable to have it close to non-DT code. With improved DT support, it became more and more difficult to not break non-DT while changing DT code. This patch splits up DT board setup and introduces a DOVE_LEGACY config to allow to remove legacy code for DT-only kernels. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Jason Cooper --- arch/arm/mach-dove/Kconfig | 5 +++ arch/arm/mach-dove/Makefile | 4 +- arch/arm/mach-dove/board-dt.c | 102 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-dove/common.c | 85 ----------------------------------- 4 files changed, 110 insertions(+), 86 deletions(-) create mode 100644 arch/arm/mach-dove/board-dt.c diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig index 603c5fd99e8a..aedd0baa04bf 100644 --- a/arch/arm/mach-dove/Kconfig +++ b/arch/arm/mach-dove/Kconfig @@ -2,8 +2,12 @@ if ARCH_DOVE menu "Marvell Dove Implementations" +config DOVE_LEGACY + bool + config MACH_DOVE_DB bool "Marvell DB-MV88AP510 Development Board" + select DOVE_LEGACY select I2C_BOARDINFO help Say 'Y' here if you want your kernel to support the @@ -11,6 +15,7 @@ config MACH_DOVE_DB config MACH_CM_A510 bool "CompuLab CM-A510 Board" + select DOVE_LEGACY help Say 'Y' here if you want your kernel to support the CompuLab CM-A510 Board. diff --git a/arch/arm/mach-dove/Makefile b/arch/arm/mach-dove/Makefile index 5e683baf96cf..3f0a858fb597 100644 --- a/arch/arm/mach-dove/Makefile +++ b/arch/arm/mach-dove/Makefile @@ -1,4 +1,6 @@ -obj-y += common.o addr-map.o irq.o mpp.o +obj-y += common.o addr-map.o irq.o +obj-$(CONFIG_DOVE_LEGACY) += mpp.o obj-$(CONFIG_PCI) += pcie.o obj-$(CONFIG_MACH_DOVE_DB) += dove-db-setup.o +obj-$(CONFIG_MACH_DOVE_DT) += board-dt.o obj-$(CONFIG_MACH_CM_A510) += cm-a510.o diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c new file mode 100644 index 000000000000..61c2b595494a --- /dev/null +++ b/arch/arm/mach-dove/board-dt.c @@ -0,0 +1,102 @@ +/* + * arch/arm/mach-dove/board-dt.c + * + * Marvell Dove 88AP510 System On Chip FDT Board + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +/* + * There are still devices that doesn't even know about DT, + * get clock gates here and add a clock lookup. + */ +static void __init dove_legacy_clk_init(void) +{ + struct device_node *np = of_find_compatible_node(NULL, NULL, + "marvell,dove-gating-clock"); + struct of_phandle_args clkspec; + + clkspec.np = np; + clkspec.args_count = 1; + + clkspec.args[0] = CLOCK_GATING_BIT_USB0; + orion_clkdev_add(NULL, "orion-ehci.0", + of_clk_get_from_provider(&clkspec)); + + clkspec.args[0] = CLOCK_GATING_BIT_USB1; + orion_clkdev_add(NULL, "orion-ehci.1", + of_clk_get_from_provider(&clkspec)); + + clkspec.args[0] = CLOCK_GATING_BIT_GBE; + orion_clkdev_add(NULL, "mv643xx_eth_port.0", + of_clk_get_from_provider(&clkspec)); + + clkspec.args[0] = CLOCK_GATING_BIT_PCIE0; + orion_clkdev_add("0", "pcie", + of_clk_get_from_provider(&clkspec)); + + clkspec.args[0] = CLOCK_GATING_BIT_PCIE1; + orion_clkdev_add("1", "pcie", + of_clk_get_from_provider(&clkspec)); +} + +static void __init dove_of_clk_init(void) +{ + mvebu_clocks_init(); + dove_legacy_clk_init(); +} + +static struct mv643xx_eth_platform_data dove_dt_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT, +}; + +static void __init dove_dt_init(void) +{ + pr_info("Dove 88AP510 SoC\n"); + +#ifdef CONFIG_CACHE_TAUROS2 + tauros2_init(0); +#endif + dove_setup_cpu_mbus(); + + /* Setup root of clk tree */ + dove_of_clk_init(); + + /* Internal devices not ported to DT yet */ + dove_ge00_init(&dove_dt_ge00_data); + dove_ehci0_init(); + dove_ehci1_init(); + dove_pcie_init(1, 1); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static const char * const dove_dt_board_compat[] = { + "marvell,dove", + NULL +}; + +DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)") + .map_io = dove_map_io, + .init_early = dove_init_early, + .init_irq = orion_dt_init_irq, + .init_time = dove_timer_init, + .init_machine = dove_dt_init, + .restart = dove_restart, + .dt_compat = dove_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index ea84c535a110..c6b3b2bb50e7 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -360,88 +360,3 @@ void dove_restart(char mode, const char *cmd) while (1) ; } - -#if defined(CONFIG_MACH_DOVE_DT) -/* - * There are still devices that doesn't even know about DT, - * get clock gates here and add a clock lookup. - */ -static void __init dove_legacy_clk_init(void) -{ - struct device_node *np = of_find_compatible_node(NULL, NULL, - "marvell,dove-gating-clock"); - struct of_phandle_args clkspec; - - clkspec.np = np; - clkspec.args_count = 1; - - clkspec.args[0] = CLOCK_GATING_BIT_USB0; - orion_clkdev_add(NULL, "orion-ehci.0", - of_clk_get_from_provider(&clkspec)); - - clkspec.args[0] = CLOCK_GATING_BIT_USB1; - orion_clkdev_add(NULL, "orion-ehci.1", - of_clk_get_from_provider(&clkspec)); - - clkspec.args[0] = CLOCK_GATING_BIT_GBE; - orion_clkdev_add(NULL, "mv643xx_eth_port.0", - of_clk_get_from_provider(&clkspec)); - - clkspec.args[0] = CLOCK_GATING_BIT_PCIE0; - orion_clkdev_add("0", "pcie", - of_clk_get_from_provider(&clkspec)); - - clkspec.args[0] = CLOCK_GATING_BIT_PCIE1; - orion_clkdev_add("1", "pcie", - of_clk_get_from_provider(&clkspec)); -} - -static void __init dove_of_clk_init(void) -{ - mvebu_clocks_init(); - dove_legacy_clk_init(); -} - -static struct mv643xx_eth_platform_data dove_dt_ge00_data = { - .phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT, -}; - -static void __init dove_dt_init(void) -{ - pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n", - (dove_tclk + 499999) / 1000000); - -#ifdef CONFIG_CACHE_TAUROS2 - tauros2_init(0); -#endif - dove_setup_cpu_mbus(); - - /* Setup root of clk tree */ - dove_of_clk_init(); - - /* Internal devices not ported to DT yet */ - dove_rtc_init(); - - dove_ge00_init(&dove_dt_ge00_data); - dove_ehci0_init(); - dove_ehci1_init(); - dove_pcie_init(1, 1); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - -static const char * const dove_dt_board_compat[] = { - "marvell,dove", - NULL -}; - -DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)") - .map_io = dove_map_io, - .init_early = dove_init_early, - .init_irq = orion_dt_init_irq, - .init_time = dove_timer_init, - .init_machine = dove_dt_init, - .restart = dove_restart, - .dt_compat = dove_dt_board_compat, -MACHINE_END -#endif -- cgit v1.2.3 From 3202bf0157ccbf8f1f89051d60ba9ca3aa4d424f Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 5 Dec 2012 21:43:23 +0100 Subject: arm: mvebu: Improve the SMP support of the interrupt controller This patch makes the interrupt controller driver more SMP aware for the Armada XP SoCs. It adds the support for the per-CPU irq. It also adds the implementation for the set_affinity hook. Patch initialy wrote by Yehuda Yitschak and reworked by Gregory CLEMENT. Signed-off-by: Yehuda Yitschak Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp.dtsi | 2 +- arch/arm/mach-mvebu/irq-armada-370-xp.c | 72 +++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 2e37ef101c90..390ba9888f36 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -30,7 +30,7 @@ }; mpic: interrupt-controller@d0020000 { - reg = <0xd0020a00 0x1d0>, + reg = <0xd0020a00 0x2d0>, <0xd0021070 0x58>; }; diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c index 8e3fb082c3c6..f99a4a2a250d 100644 --- a/arch/arm/mach-mvebu/irq-armada-370-xp.c +++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c @@ -34,6 +34,7 @@ #define ARMADA_370_XP_INT_CONTROL (0x00) #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) +#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) @@ -41,28 +42,90 @@ #define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) #define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8) +#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) + #define ACTIVE_DOORBELLS (8) +static DEFINE_RAW_SPINLOCK(irq_controller_lock); + static void __iomem *per_cpu_int_base; static void __iomem *main_int_base; static struct irq_domain *armada_370_xp_mpic_domain; +/* + * In SMP mode: + * For shared global interrupts, mask/unmask global enable bit + * For CPU interrtups, mask/unmask the calling CPU's bit + */ static void armada_370_xp_irq_mask(struct irq_data *d) { +#ifdef CONFIG_SMP + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS) + writel(hwirq, main_int_base + + ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); + else + writel(hwirq, per_cpu_int_base + + ARMADA_370_XP_INT_SET_MASK_OFFS); +#else writel(irqd_to_hwirq(d), per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS); +#endif } static void armada_370_xp_irq_unmask(struct irq_data *d) { +#ifdef CONFIG_SMP + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS) + writel(hwirq, main_int_base + + ARMADA_370_XP_INT_SET_ENABLE_OFFS); + else + writel(hwirq, per_cpu_int_base + + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); +#else writel(irqd_to_hwirq(d), per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); +#endif } #ifdef CONFIG_SMP static int armada_xp_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { + unsigned long reg; + unsigned long new_mask = 0; + unsigned long online_mask = 0; + unsigned long count = 0; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + int cpu; + + for_each_cpu(cpu, mask_val) { + new_mask |= 1 << cpu_logical_map(cpu); + count++; + } + + /* + * Forbid mutlicore interrupt affinity + * This is required since the MPIC HW doesn't limit + * several CPUs from acknowledging the same interrupt. + */ + if (count > 1) + return -EINVAL; + + for_each_cpu(cpu, cpu_online_mask) + online_mask |= 1 << cpu_logical_map(cpu); + + raw_spin_lock(&irq_controller_lock); + + reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); + reg = (reg & (~online_mask)) | new_mask; + writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); + + raw_spin_unlock(&irq_controller_lock); + return 0; } #endif @@ -155,6 +218,15 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, #ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init(); + + /* + * Set the default affinity from all CPUs to the boot cpu. + * This is required since the MPIC doesn't limit several CPUs + * from acknowledging the same interrupt. + */ + cpumask_clear(irq_default_affinity); + cpumask_set_cpu(smp_processor_id(), irq_default_affinity); + #endif return 0; -- cgit v1.2.3 From 491221451b9998cf182770f2b5f8b3a8b141dd81 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 9 Jan 2013 20:56:07 +0100 Subject: arm: mvebu: add DTS file for Marvell RD-A370-A1 board This patch adds the DTS file to support the Marvell RD-A370-A1 (Reference Design board) also known as RD-88F6710 board. It is almost entirely similar to the DB-A370 board except that the first Ethernet PHY is SGMII-wired and the second is a switch which is RGMII-wired. Signed-off-by: Florian Fainelli Signed-off-by: Jason Cooper --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/armada-370-rd.dts | 61 +++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 arch/arm/boot/dts/armada-370-rd.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5ebb44fe826a..ed256e29cc2a 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -77,6 +77,7 @@ dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \ msm8960-cdp.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \ armada-370-mirabox.dtb \ + armada-370-rd.dtb \ armada-xp-db.dtb \ armada-xp-openblocks-ax3-4.dtb dtb-$(CONFIG_ARCH_MXC) += imx51-babbage.dtb \ diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts new file mode 100644 index 000000000000..d62dfac61924 --- /dev/null +++ b/arch/arm/boot/dts/armada-370-rd.dts @@ -0,0 +1,61 @@ +/* + * Device Tree file for Marvell Armada 370 Reference Design board + * (RD-88F6710-A1) + * + * Copied from arch/arm/boot/dts/armada-370-db.dts + * + * Copyright (C) 2013 Florian Fainelli + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/dts-v1/; +/include/ "armada-370.dtsi" + +/ { + model = "Marvell Armada 370 Reference Design"; + compatible = "marvell,a370-rd", "marvell,armada370", "marvell,armada-370-xp"; + + chosen { + bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* 512 MB */ + }; + + soc { + serial@d0012000 { + clock-frequency = <200000000>; + status = "okay"; + }; + sata@d00a0000 { + nr-ports = <2>; + status = "okay"; + }; + + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + + ethernet@d0070000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "sgmii"; + }; + ethernet@d0074000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + }; +}; -- cgit v1.2.3 From 9b47a4fb7760fabfbbc33b7d7703454684f36782 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 9 Dec 2012 19:40:04 +0100 Subject: ARM: kirkwood: convert Guruplug Server Plus to use the device tree Add a device tree entry for the Guruplug Server Plus board. This port was based both on the work done on the dreamplug and the dockstar. It builds, boots and works on my Guruplug Server Plus. Signed-off-by: Willy Tarreau Signed-off-by: Jason Cooper --- arch/arm/boot/dts/Makefile | 1 + .../arm/boot/dts/kirkwood-guruplug-server-plus.dts | 94 ++++++++++++++++++++++ arch/arm/mach-kirkwood/Kconfig | 7 ++ arch/arm/mach-kirkwood/Makefile | 1 + arch/arm/mach-kirkwood/board-dt.c | 4 + arch/arm/mach-kirkwood/board-guruplug.c | 39 +++++++++ arch/arm/mach-kirkwood/common.h | 5 ++ 7 files changed, 151 insertions(+) create mode 100644 arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts create mode 100644 arch/arm/mach-kirkwood/board-guruplug.c diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index ed256e29cc2a..ebba972d774b 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \ kirkwood-dockstar.dtb \ kirkwood-dreamplug.dtb \ kirkwood-goflexnet.dtb \ + kirkwood-guruplug-server-plus.dtb \ kirkwood-ib62x0.dtb \ kirkwood-iconnect.dtb \ kirkwood-iomega_ix2_200.dtb \ diff --git a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts new file mode 100644 index 000000000000..9555a86297c2 --- /dev/null +++ b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +/include/ "kirkwood.dtsi" +/include/ "kirkwood-6281.dtsi" + +/ { + model = "Globalscale Technologies Guruplug Server Plus"; + compatible = "globalscale,guruplug-server-plus", "globalscale,guruplug", "marvell,kirkwood-88f6281", "marvell,kirkwood"; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200n8 earlyprintk"; + }; + + ocp@f1000000 { + pinctrl: pinctrl@10000 { + + pinctrl-0 = < &pmx_led_health_r &pmx_led_health_g + &pmx_led_wmode_r &pmx_led_wmode_g >; + pinctrl-names = "default"; + + pmx_led_health_r: pmx-led-health-r { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + pmx_led_health_g: pmx-led-health-g { + marvell,pins = "mpp47"; + marvell,function = "gpio"; + }; + pmx_led_wmode_r: pmx-led-wmode-r { + marvell,pins = "mpp48"; + marvell,function = "gpio"; + }; + pmx_led_wmode_g: pmx-led-wmode-g { + marvell,pins = "mpp49"; + marvell,function = "gpio"; + }; + }; + serial@12000 { + clock-frequency = <200000000>; + status = "ok"; + }; + + nand@3000000 { + status = "okay"; + + partition@0 { + label = "u-boot"; + reg = <0x00000000 0x00100000>; + read-only; + }; + + partition@100000 { + label = "uImage"; + reg = <0x00100000 0x00400000>; + }; + + partition@500000 { + label = "data"; + reg = <0x00500000 0x1fb00000>; + }; + }; + + sata@80000 { + status = "okay"; + nr-ports = <1>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + health-r { + label = "guruplug:red:health"; + gpios = <&gpio1 14 1>; + }; + health-g { + label = "guruplug:green:health"; + gpios = <&gpio1 15 1>; + }; + wmode-r { + label = "guruplug:red:wmode"; + gpios = <&gpio1 16 1>; + }; + wmode-g { + label = "guruplug:green:wmode"; + gpios = <&gpio1 17 1>; + }; + }; +}; diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index f91cdff5a3e4..7b6a64bc5f40 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -58,6 +58,13 @@ config ARCH_KIRKWOOD_DT Say 'Y' here if you want your kernel to support the Marvell Kirkwood using flattened device tree. +config MACH_GURUPLUG_DT + bool "Marvell GuruPlug Reference Board (Flattened Device Tree)" + select ARCH_KIRKWOOD_DT + help + Say 'Y' here if you want your kernel to support the + Marvell GuruPlug Reference Board (Flattened Device Tree). + config MACH_DREAMPLUG_DT bool "Marvell DreamPlug (Flattened Device Tree)" select ARCH_KIRKWOOD_DT diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index d6653095a1eb..4cc4bee4d0cf 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_MACH_T5325) += t5325-setup.o obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o obj-$(CONFIG_MACH_DREAMPLUG_DT) += board-dreamplug.o +obj-$(CONFIG_MACH_GURUPLUG_DT) += board-guruplug.o obj-$(CONFIG_MACH_ICONNECT_DT) += board-iconnect.o obj-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += board-dnskw.o obj-$(CONFIG_MACH_IB62X0_DT) += board-ib62x0.o diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 8eac5487773b..05b3b7ea41f7 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -98,6 +98,9 @@ static void __init kirkwood_dt_init(void) if (of_machine_is_compatible("globalscale,dreamplug")) dreamplug_init(); + if (of_machine_is_compatible("globalscale,guruplug")) + guruplug_dt_init(); + if (of_machine_is_compatible("dlink,dns-kirkwood")) dnskw_init(); @@ -149,6 +152,7 @@ static void __init kirkwood_dt_init(void) static const char * const kirkwood_dt_board_compat[] = { "globalscale,dreamplug", + "globalscale,guruplug", "dlink,dns-320", "dlink,dns-325", "iom,iconnect", diff --git a/arch/arm/mach-kirkwood/board-guruplug.c b/arch/arm/mach-kirkwood/board-guruplug.c new file mode 100644 index 000000000000..0a0df4554d8b --- /dev/null +++ b/arch/arm/mach-kirkwood/board-guruplug.c @@ -0,0 +1,39 @@ +/* + * arch/arm/mach-kirkwood/board-guruplug.c + * + * Marvell Guruplug Reference Board Init for drivers not converted to + * flattened device tree yet. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include "common.h" + +static struct mv643xx_eth_platform_data guruplug_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), +}; + +static struct mv643xx_eth_platform_data guruplug_ge01_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(1), +}; + +static struct mvsdio_platform_data guruplug_mvsdio_data = { + /* unfortunately the CD signal has not been connected */ +}; + +void __init guruplug_dt_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_ge00_init(&guruplug_ge00_data); + kirkwood_ge01_init(&guruplug_ge01_data); + kirkwood_sdio_init(&guruplug_mvsdio_data); +} diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index e956d0277dd1..537bdf816af7 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -60,6 +60,11 @@ void dreamplug_init(void); #else static inline void dreamplug_init(void) {}; #endif +#ifdef CONFIG_MACH_GURUPLUG_DT +void guruplug_dt_init(void); +#else +static inline void guruplug_dt_init(void) {}; +#endif #ifdef CONFIG_MACH_TS219_DT void qnap_dt_ts219_init(void); #else -- cgit v1.2.3 From 9b75ac0cbf11199c4d125e68c3b86ae7d0ee941f Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 23 Jan 2013 12:26:32 -0300 Subject: arm: mvebu: Update defconfig to select USB support Cc: Lior Amsalem Cc: Thomas Petazzoni Cc: Gregory CLEMENT Tested-by: Nobuhiro Iwamatsu Tested-by: Florian Fainelli Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 4e6f0ceb9b12..28e3332ede74 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -44,7 +44,10 @@ CONFIG_I2C_MV64XXX=y CONFIG_SERIAL_8250_DW=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y -# CONFIG_USB_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_MMC=y CONFIG_MMC_MVSDIO=y CONFIG_NEW_LEDS=y -- cgit v1.2.3 From 3a6f08a3708f6faf6aba4abbdeaa9da29393f696 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 25 Jan 2013 18:32:41 +0100 Subject: arm: mvebu: Add support for local interrupt MPIC allows the use of private interrupt for each CPUs. The 28th first interrupts are per-cpu. This patch adds support to use them. Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/irq-armada-370-xp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c index f99a4a2a250d..274ff58271de 100644 --- a/arch/arm/mach-mvebu/irq-armada-370-xp.c +++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c @@ -145,10 +145,17 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, { armada_370_xp_irq_mask(irq_get_irq_data(virq)); writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); - - irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, - handle_level_irq); irq_set_status_flags(virq, IRQ_LEVEL); + + if (hw < ARMADA_370_XP_MAX_PER_CPU_IRQS) { + irq_set_percpu_devid(virq); + irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, + handle_percpu_devid_irq); + + } else { + irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, + handle_level_irq); + } set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); return 0; @@ -245,7 +252,7 @@ asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs if (irqnr > 1022) break; - if (irqnr >= 8) { + if (irqnr > 0) { irqnr = irq_find_mapping(armada_370_xp_mpic_domain, irqnr); handle_IRQ(irqnr, regs); -- cgit v1.2.3 From ddd3f69f9f01063edabeb8ca5b1551936f98dfb1 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 25 Jan 2013 18:32:42 +0100 Subject: clocksource: time-armada-370-xp: add local timer support On the SOCs Armada 370 and Armada XP, each CPU comes with two private timers. This patch use the timer 0 of each CPU as local timer for the clockevent if CONFIG_LOCAL_TIMER is selected. In the other case, use only the private Timer 0 of CPU 0. Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- drivers/clocksource/time-armada-370-xp.c | 150 +++++++++++++++++++++++-------- 1 file changed, 112 insertions(+), 38 deletions(-) diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index a4605fd7e303..47a673070d70 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -27,8 +27,10 @@ #include #include #include -#include +#include +#include +#include /* * Timer block registers. */ @@ -49,6 +51,7 @@ #define TIMER1_RELOAD_OFF 0x0018 #define TIMER1_VAL_OFF 0x001c +#define LCL_TIMER_EVENTS_STATUS 0x0028 /* Global timers are connected to the coherency fabric clock, and the below divider reduces their incrementing frequency. */ #define TIMER_DIVIDER_SHIFT 5 @@ -57,14 +60,17 @@ /* * SoC-specific data. */ -static void __iomem *timer_base; -static int timer_irq; +static void __iomem *timer_base, *local_base; +static unsigned int timer_clk; +static bool timer25Mhz = true; /* * Number of timer ticks per jiffy. */ static u32 ticks_per_jiffy; +static struct clock_event_device __percpu **percpu_armada_370_xp_evt; + static u32 notrace armada_370_xp_read_sched_clock(void) { return ~readl(timer_base + TIMER0_VAL_OFF); @@ -78,24 +84,23 @@ armada_370_xp_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) { u32 u; - /* * Clear clockevent timer interrupt. */ - writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS); + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); /* * Setup new clockevent timer value. */ - writel(delta, timer_base + TIMER1_VAL_OFF); + writel(delta, local_base + TIMER0_VAL_OFF); /* * Enable the timer. */ - u = readl(timer_base + TIMER_CTRL_OFF); - u = ((u & ~TIMER1_RELOAD_EN) | TIMER1_EN | - TIMER1_DIV(TIMER_DIVIDER_SHIFT)); - writel(u, timer_base + TIMER_CTRL_OFF); + u = readl(local_base + TIMER_CTRL_OFF); + u = ((u & ~TIMER0_RELOAD_EN) | TIMER0_EN | + TIMER0_DIV(TIMER_DIVIDER_SHIFT)); + writel(u, local_base + TIMER_CTRL_OFF); return 0; } @@ -107,37 +112,38 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, u32 u; if (mode == CLOCK_EVT_MODE_PERIODIC) { + /* * Setup timer to fire at 1/HZ intervals. */ - writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF); - writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF); + writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); + writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); /* * Enable timer. */ - u = readl(timer_base + TIMER_CTRL_OFF); - writel((u | TIMER1_EN | TIMER1_RELOAD_EN | - TIMER1_DIV(TIMER_DIVIDER_SHIFT)), - timer_base + TIMER_CTRL_OFF); + u = readl(local_base + TIMER_CTRL_OFF); + + writel((u | TIMER0_EN | TIMER0_RELOAD_EN | + TIMER0_DIV(TIMER_DIVIDER_SHIFT)), + local_base + TIMER_CTRL_OFF); } else { /* * Disable timer. */ - u = readl(timer_base + TIMER_CTRL_OFF); - writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF); + u = readl(local_base + TIMER_CTRL_OFF); + writel(u & ~TIMER0_EN, local_base + TIMER_CTRL_OFF); /* * ACK pending timer interrupt. */ - writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS); - + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); } } static struct clock_event_device armada_370_xp_clkevt = { - .name = "armada_370_xp_tick", + .name = "armada_370_xp_per_cpu_tick", .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .shift = 32, .rating = 300, @@ -150,32 +156,78 @@ static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) /* * ACK timer interrupt and call event handler. */ + struct clock_event_device *evt = *(struct clock_event_device **)dev_id; - writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS); - armada_370_xp_clkevt.event_handler(&armada_370_xp_clkevt); + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + evt->event_handler(evt); return IRQ_HANDLED; } -static struct irqaction armada_370_xp_timer_irq = { - .name = "armada_370_xp_tick", - .flags = IRQF_DISABLED | IRQF_TIMER, - .handler = armada_370_xp_timer_interrupt +/* + * Setup the local clock events for a CPU. + */ +static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt) +{ + u32 u; + int cpu = smp_processor_id(); + + /* Use existing clock_event for cpu 0 */ + if (!smp_processor_id()) + return 0; + + u = readl(local_base + TIMER_CTRL_OFF); + if (timer25Mhz) + writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF); + else + writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF); + + evt->name = armada_370_xp_clkevt.name; + evt->irq = armada_370_xp_clkevt.irq; + evt->features = armada_370_xp_clkevt.features; + evt->shift = armada_370_xp_clkevt.shift; + evt->rating = armada_370_xp_clkevt.rating, + evt->set_next_event = armada_370_xp_clkevt_next_event, + evt->set_mode = armada_370_xp_clkevt_mode, + evt->cpumask = cpumask_of(cpu); + + *__this_cpu_ptr(percpu_armada_370_xp_evt) = evt; + + clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); + enable_percpu_irq(evt->irq, 0); + + return 0; +} + +static void armada_370_xp_timer_stop(struct clock_event_device *evt) +{ + evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + disable_percpu_irq(evt->irq); +} + +static struct local_timer_ops armada_370_xp_local_timer_ops __cpuinitdata = { + .setup = armada_370_xp_timer_setup, + .stop = armada_370_xp_timer_stop, }; void __init armada_370_xp_timer_init(void) { u32 u; struct device_node *np; - unsigned int timer_clk; + int res; + np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer"); timer_base = of_iomap(np, 0); WARN_ON(!timer_base); + local_base = of_iomap(np, 1); if (of_find_property(np, "marvell,timer-25Mhz", NULL)) { /* The fixed 25MHz timer is available so let's use it */ + u = readl(local_base + TIMER_CTRL_OFF); + writel(u | TIMER0_25MHZ, + local_base + TIMER_CTRL_OFF); u = readl(timer_base + TIMER_CTRL_OFF); - writel(u | TIMER0_25MHZ | TIMER1_25MHZ, + writel(u | TIMER0_25MHZ, timer_base + TIMER_CTRL_OFF); timer_clk = 25000000; } else { @@ -183,15 +235,23 @@ void __init armada_370_xp_timer_init(void) struct clk *clk = of_clk_get(np, 0); WARN_ON(IS_ERR(clk)); rate = clk_get_rate(clk); + u = readl(local_base + TIMER_CTRL_OFF); + writel(u & ~(TIMER0_25MHZ), + local_base + TIMER_CTRL_OFF); + u = readl(timer_base + TIMER_CTRL_OFF); - writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ), + writel(u & ~(TIMER0_25MHZ), timer_base + TIMER_CTRL_OFF); + timer_clk = rate / TIMER_DIVIDER; + timer25Mhz = false; } - /* We use timer 0 as clocksource, and timer 1 for - clockevents */ - timer_irq = irq_of_parse_and_map(np, 1); + /* + * We use timer 0 as clocksource, and private(local) timer 0 + * for clockevents + */ + armada_370_xp_clkevt.irq = irq_of_parse_and_map(np, 4); ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; @@ -216,12 +276,26 @@ void __init armada_370_xp_timer_init(void) "armada_370_xp_clocksource", timer_clk, 300, 32, clocksource_mmio_readl_down); - /* - * Setup clockevent timer (interrupt-driven). - */ - setup_irq(timer_irq, &armada_370_xp_timer_irq); + /* Register the clockevent on the private timer of CPU 0 */ armada_370_xp_clkevt.cpumask = cpumask_of(0); clockevents_config_and_register(&armada_370_xp_clkevt, timer_clk, 1, 0xfffffffe); -} + percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *); + + + /* + * Setup clockevent timer (interrupt-driven). + */ + *__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt; + res = request_percpu_irq(armada_370_xp_clkevt.irq, + armada_370_xp_timer_interrupt, + armada_370_xp_clkevt.name, + percpu_armada_370_xp_evt); + if (!res) { + enable_percpu_irq(armada_370_xp_clkevt.irq, 0); +#ifdef CONFIG_LOCAL_TIMERS + local_timer_register(&armada_370_xp_local_timer_ops); +#endif + } +} -- cgit v1.2.3 From cecf42c5d7a864509ee5cc6630d2414676f0b8a9 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 25 Jan 2013 18:32:43 +0100 Subject: arm: mvebu: update defconfig with local timer support Now that we have support for local timers, enable it by default Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 28e3332ede74..4476a3014a72 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -14,7 +14,6 @@ CONFIG_MACH_ARMADA_XP=y # CONFIG_CACHE_L2X0 is not set # CONFIG_SWP_EMULATE is not set CONFIG_SMP=y -# CONFIG_LOCAL_TIMERS is not set CONFIG_AEABI=y CONFIG_HIGHMEM=y # CONFIG_COMPACTION is not set -- cgit v1.2.3 From 568fc0a321a7f3ae1c3626a4f471d49ff005779c Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 31 Jan 2013 15:50:12 +0100 Subject: arm: mvebu: support for the new Armada XP development board(DB-MV784MP-GP) This is the new Armada XP evaluation board from Marvell. It comes with a RS232 port over USB, a SATA link, an internal SSD, 4 Ethernet Gigabit links. Support for USB (Host and device), SDIO, PCIe will be added as drivers when they become available for Armada XP in mainline. Tested-by: Simon Guinot Tested-by: Florian Fainelli Signed-off-by: Gregory CLEMENT Tested-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/armada-xp-gp.dts | 101 +++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 arch/arm/boot/dts/armada-xp-gp.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index ebba972d774b..157fbebc9c24 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -80,6 +80,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \ armada-370-mirabox.dtb \ armada-370-rd.dtb \ armada-xp-db.dtb \ + armada-xp-gp.dtb \ armada-xp-openblocks-ax3-4.dtb dtb-$(CONFIG_ARCH_MXC) += imx51-babbage.dtb \ imx53-ard.dtb \ diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts new file mode 100644 index 000000000000..3eea53106a1f --- /dev/null +++ b/arch/arm/boot/dts/armada-xp-gp.dts @@ -0,0 +1,101 @@ +/* + * Device Tree file for Marvell Armada XP development board + * (DB-MV784MP-GP) + * + * Copyright (C) 2013 Marvell + * + * Lior Amsalem + * Gregory CLEMENT + * Thomas Petazzoni + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/dts-v1/; +/include/ "armada-xp-mv78460.dtsi" + +/ { + model = "Marvell Armada XP Development Board DB-MV784MP-GP"; + compatible = "marvell,axp-gp", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp"; + + chosen { + bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { + device_type = "memory"; + + /* + * 4 GB of plug-in RAM modules by default but only 3GB + * are visible, the amount of memory available can be + * changed by the bootloader according the size of the + * module actually plugged + */ + reg = <0x00000000 0xC0000000>; + }; + + soc { + serial@d0012000 { + clock-frequency = <250000000>; + status = "okay"; + }; + serial@d0012100 { + clock-frequency = <250000000>; + status = "okay"; + }; + serial@d0012200 { + clock-frequency = <250000000>; + status = "okay"; + }; + serial@d0012300 { + clock-frequency = <250000000>; + status = "okay"; + }; + + sata@d00a0000 { + nr-ports = <2>; + status = "okay"; + }; + + mdio { + phy0: ethernet-phy@0 { + reg = <16>; + }; + + phy1: ethernet-phy@1 { + reg = <17>; + }; + + phy2: ethernet-phy@2 { + reg = <18>; + }; + + phy3: ethernet-phy@3 { + reg = <19>; + }; + }; + + ethernet@d0070000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + ethernet@d0074000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + ethernet@d0030000 { + status = "okay"; + phy = <&phy2>; + phy-mode = "rgmii-id"; + }; + ethernet@d0034000 { + status = "okay"; + phy = <&phy3>; + phy-mode = "rgmii-id"; + }; + }; +}; -- cgit v1.2.3 From d2d1ef4f021d8a56f787af60a0b44ee758ef5013 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 6 Feb 2013 10:06:22 -0300 Subject: ARM: mvebu: Update defconfig to select SPI support Cc: Thomas Petazzoni Cc: Lior Amsalem Acked-by: Gregory Clement Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 4476a3014a72..12da3230bba0 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -39,6 +39,8 @@ CONFIG_MWIFIEX_SDIO=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_SPI_ORION=y CONFIG_I2C_MV64XXX=y CONFIG_SERIAL_8250_DW=y CONFIG_GPIOLIB=y -- cgit v1.2.3 From d0b8a49c4bddca6e9d55fc2eb1e151a7403a8093 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 6 Feb 2013 10:06:24 -0300 Subject: ARM: mvebu: Update defconfig to select SPI flash and MTD support The Armada XP DB-MV784MP-GP board has an SPI flash device. These options allow to access that device over MTD. Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 12da3230bba0..da6ad6bd41e0 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -42,6 +42,9 @@ CONFIG_I2C=y CONFIG_SPI=y CONFIG_SPI_ORION=y CONFIG_I2C_MV64XXX=y +CONFIG_MTD=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_M25P80=y CONFIG_SERIAL_8250_DW=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y -- cgit v1.2.3 From d57c3590f5136a125e4684a1c1ab24f1b5dd2cfd Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 4 Feb 2013 18:21:07 +0100 Subject: arm: mvebu: update defconfig with ATAG support when using DT Some of the mvebu boards (mainly the development board) come with plug-in RAM modules. This patch allows to let the bootloaders which have no support for DTS to give the real amount of memory available on the board. Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/configs/mvebu_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index da6ad6bd41e0..2ec8119cff73 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -20,6 +20,7 @@ CONFIG_HIGHMEM=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_VFP=y CONFIG_NET=y CONFIG_INET=y -- cgit v1.2.3 From 0db98549bdb4837bd63becc9c0f70929ca8b88f7 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 12 Dec 2012 10:06:24 +0100 Subject: arm: mvebu: Add RTC support for Armada 370 and Armada XP The Armada 370 and Armada XP Socs have the same controller that the one used in the orion platforms. This patch updates the device tree for these SoCs. Signed-off-by: Gregory CLEMENT Acked-by: Andrew Lunn Tested-by: Florian Fainelli Acked-by: Arnd Bergmann Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-xp.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index 4c0abe85405f..5b2922599f0e 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -131,6 +131,12 @@ clocks = <&coreclk 0>; status = "disabled"; }; + + rtc@10300 { + compatible = "marvell,orion-rtc"; + reg = <0xd0010300 0x20>; + interrupts = <50>; + }; }; }; -- cgit v1.2.3 From 42bb531671d5f32af2d0afe4ea7a9eb54992ed21 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:04 +0100 Subject: arm: mvebu: add DT information for the SDIO interface of Armada 370/XP Now that the mvsdio MMC driver has a Device Tree binding, we add the Device Tree informations to describe the SDIO interface available in the Armada 370/XP SoCs. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-xp.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index 5b2922599f0e..28276fe79d28 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -137,6 +137,14 @@ reg = <0xd0010300 0x20>; interrupts = <50>; }; + + mvsdio@d00d4000 { + compatible = "marvell,orion-sdio"; + reg = <0xd00d4000 0x200>; + interrupts = <54>; + clocks = <&gateclk 17>; + status = "disabled"; + }; }; }; -- cgit v1.2.3 From fa1b21d13538d52639ee19eea2aa6148a6c3ba47 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:05 +0100 Subject: arm: mvebu: add pin muxing options for the SDIO interface on Armada 370 The SDIO interface is available either on pins MPP9/11/12/13/14/15 or MPP47/48/49/50/51/52 on the Armada 370. Even though all combinations are potentially possible, those two muxing options are the most probable ones, so we provide those at the SoC level .dtsi file. In practice, in turns out the Armada 370 DB board uses the former, while the Armada 370 Mirabox uses the latter. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi index 636cf7d4009e..88f9bab44d52 100644 --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi @@ -47,6 +47,18 @@ pinctrl { compatible = "marvell,mv88f6710-pinctrl"; reg = <0xd0018000 0x38>; + + sdio_pins1: sdio-pins1 { + marvell,pins = "mpp9", "mpp11", "mpp12", + "mpp13", "mpp14", "mpp15"; + marvell,function = "sd0"; + }; + + sdio_pins2: sdio-pins2 { + marvell,pins = "mpp47", "mpp48", "mpp49", + "mpp50", "mpp51", "mpp52"; + marvell,function = "sd0"; + }; }; gpio0: gpio@d0018100 { -- cgit v1.2.3 From 6d36e8e08fd9eafd2fe9776f52d2dcddf3d984f5 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:06 +0100 Subject: arm: mvebu: add pin muxing options for the SDIO interface on Armada XP The SDIO interface is only available on pins MPP30/31/32/33/34/35 on the various Armada XP variants, so we provide a pin muxing option for this in the Armada XP .dtsi files. Even though those muxing options are the same for MV78230, MV78260 and MV78460, we keep them in each .dtsi file, because the number of pins, and therefore the declaration of the pinctrl node, is different for each SoC variant. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-mv78230.dtsi | 6 ++++++ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 6 ++++++ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi index e041f42ed711..f56c40599f5b 100644 --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi @@ -47,6 +47,12 @@ pinctrl { compatible = "marvell,mv78230-pinctrl"; reg = <0xd0018000 0x38>; + + sdio_pins: sdio-pins { + marvell,pins = "mpp30", "mpp31", "mpp32", + "mpp33", "mpp34", "mpp35"; + marvell,function = "sd0"; + }; }; gpio0: gpio@d0018100 { diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 9e23bd8c9536..f8f2b787d2b0 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi @@ -48,6 +48,12 @@ pinctrl { compatible = "marvell,mv78260-pinctrl"; reg = <0xd0018000 0x38>; + + sdio_pins: sdio-pins { + marvell,pins = "mpp30", "mpp31", "mpp32", + "mpp33", "mpp34", "mpp35"; + marvell,function = "sd0"; + }; }; gpio0: gpio@d0018100 { diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi index 965966110e38..936c25dc32b0 100644 --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi @@ -63,6 +63,12 @@ pinctrl { compatible = "marvell,mv78460-pinctrl"; reg = <0xd0018000 0x38>; + + sdio_pins: sdio-pins { + marvell,pins = "mpp30", "mpp31", "mpp32", + "mpp33", "mpp34", "mpp35"; + marvell,function = "sd0"; + }; }; gpio0: gpio@d0018100 { -- cgit v1.2.3 From d64c129b44d90fd7075dc7cf4b0f30ef70c316f7 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:07 +0100 Subject: arm: mvebu: enable the SD card slot on Armada XP DB board The Armada XP DB evaluation board has one SD card slot, directly connected to the SDIO IP of the SoC, so we enable this IP. Unfortunately, there are no GPIOs for card-detect and write-protect. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-db.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index 8e53b25b5508..c7035c5d0dee 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts @@ -90,5 +90,12 @@ phy = <&phy3>; phy-mode = "sgmii"; }; + + mvsdio@d00d4000 { + pinctrl-0 = <&sdio_pins>; + pinctrl-names = "default"; + status = "okay"; + /* No CD or WP GPIOs */ + }; }; }; -- cgit v1.2.3 From b6150c710658faed9ebe80f989f622175eaf0e14 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:08 +0100 Subject: arm: mvebu: enable the SD card slot on Armada 370 DB board The Armada XP DB evaluation board has one SD card slot, directly connected to the SDIO IP of the SoC, so we add a device tree description for it. However, in the default configuration of the board, the SD card slot is not usable: the connector plugged into CON40 must be changed against a different one, provided with the board by the manufacturer. Since such a manual modification of the hardware is needed, we did not enable the SDIO interface by default, and left it to the board user to modify the Device Tree if needed. Since this board is really only an evaluation board for developers and not a final product, it is not too bad. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-db.dts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 9b82facb2561..8e66a7c00e18 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -59,5 +59,20 @@ phy = <&phy1>; phy-mode = "rgmii-id"; }; + + mvsdio@d00d4000 { + pinctrl-0 = <&sdio_pins1>; + pinctrl-names = "default"; + /* + * This device is disabled by default, because + * using the SD card connector requires + * changing the default CON40 connector + * "DB-88F6710_MPP_2xRGMII_DEVICE_Jumper" to a + * different connector + * "DB-88F6710_MPP_RGMII_SD_Jumper". + */ + status = "disabled"; + /* No CD or WP GPIOs */ + }; }; }; -- cgit v1.2.3 From 5f6d11c398e67c9009e526b2fb1268e87b0e6ba0 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:09 +0100 Subject: arm: mvebu: enable the SDIO interface on the Globalscale Mirabox The Globalscale Mirabox uses the SDIO interface of the Armada 370 to connect to a Wifi/Bluetooth SD8787 chip, so we enable the SDIO interface of this board in its Device Tree file. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-mirabox.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts index 3b4071336599..1864820dde25 100644 --- a/arch/arm/boot/dts/armada-370-mirabox.dts +++ b/arch/arm/boot/dts/armada-370-mirabox.dts @@ -52,5 +52,15 @@ phy = <&phy1>; phy-mode = "rgmii-id"; }; + + mvsdio@d00d4000 { + pinctrl-0 = <&sdio_pins2>; + pinctrl-names = "default"; + status = "okay"; + /* + * No CD or WP GPIOs: SDIO interface used for + * Wifi/Bluetooth chip + */ + }; }; }; -- cgit v1.2.3 From ec05fcf679fe97994b5355ebf1d7d8cb0020eacf Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:10 +0100 Subject: arm: kirkwood: add Device Tree informations for the SDIO controller Now that the SDIO controller has a Device Tree binding, let's use it in kirkwood.dtsi. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi index d6ab442b7011..2c738d9dc82a 100644 --- a/arch/arm/boot/dts/kirkwood.dtsi +++ b/arch/arm/boot/dts/kirkwood.dtsi @@ -193,5 +193,13 @@ clocks = <&gate_clk 17>; status = "okay"; }; + + mvsdio@90000 { + compatible = "marvell,orion-sdio"; + reg = <0x90000 0x200>; + interrupts = <28>; + clocks = <&gate_clk 4>; + status = "disabled"; + }; }; }; -- cgit v1.2.3 From a49da46c5274228334393083a6635d04eee04363 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:11 +0100 Subject: arm: kirkwood: dreamplug: use Device Tree to probe SDIO Now that the mvsdio driver has a Device Tree binding, and the SDIO controller is declared in kirkwood.dtsi, migrate the dreamplug board to use the Device Tree to probe the SDIO controller and to mux this interface properly. Signed-off-by: Thomas Petazzoni Cc: Jason Cooper Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-dreamplug.dts | 7 +++++++ arch/arm/mach-kirkwood/board-dreamplug.c | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts index f2d386c95b07..ef2d8c705709 100644 --- a/arch/arm/boot/dts/kirkwood-dreamplug.dts +++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts @@ -74,6 +74,13 @@ status = "okay"; nr-ports = <1>; }; + + mvsdio@90000 { + pinctrl-0 = <&pmx_sdio>; + pinctrl-names = "default"; + status = "okay"; + /* No CD or WP GPIOs */ + }; }; gpio-leds { diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c index 08248e24ffcd..0903242c00dc 100644 --- a/arch/arm/mach-kirkwood/board-dreamplug.c +++ b/arch/arm/mach-kirkwood/board-dreamplug.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "common.h" static struct mv643xx_eth_platform_data dreamplug_ge00_data = { @@ -26,10 +25,6 @@ static struct mv643xx_eth_platform_data dreamplug_ge01_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(1), }; -static struct mvsdio_platform_data dreamplug_mvsdio_data = { - /* unfortunately the CD signal has not been connected */ -}; - void __init dreamplug_init(void) { /* @@ -37,5 +32,4 @@ void __init dreamplug_init(void) */ kirkwood_ge00_init(&dreamplug_ge00_data); kirkwood_ge01_init(&dreamplug_ge01_data); - kirkwood_sdio_init(&dreamplug_mvsdio_data); } -- cgit v1.2.3 From 5dd8a01003355da95e23e3609e98a968001c3ee8 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:12 +0100 Subject: arm: kirkwood: mplcec4: use Device Tree to probe SDIO Now that the mvsdio driver has a Device Tree binding, and the SDIO controller is declared in kirkwood.dtsi, migrate the mplcec4 board to use the Device Tree to probe the SDIO controller and to mux the pins of the SDIO interface correctly. This patch has not been tested, it remains to be tested by a person having access to the hardware. Signed-off-by: Thomas Petazzoni Cc: Stefan Peter Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-mplcec4.dts | 11 +++++++++-- arch/arm/mach-kirkwood/board-mplcec4.c | 7 ------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts index 262c65403760..662dfd81b1ce 100644 --- a/arch/arm/boot/dts/kirkwood-mplcec4.dts +++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts @@ -20,12 +20,11 @@ pinctrl: pinctrl@10000 { pinctrl-0 = < &pmx_nand &pmx_uart0 - &pmx_led_health &pmx_sdio + &pmx_led_health &pmx_sata0 &pmx_sata1 &pmx_led_user1o &pmx_led_user1g &pmx_led_user0o &pmx_led_user0g &pmx_led_misc - &pmx_sdio_cd >; pinctrl-names = "default"; @@ -133,6 +132,14 @@ status = "okay"; }; + + mvsdio@90000 { + pinctrl-0 = <&pmx_sdio &pmx_sdio_cd>; + pinctrl-names = "default"; + status = "okay"; + cd-gpios = <&gpio1 15 0>; + /* No WP GPIO */ + }; }; gpio-leds { diff --git a/arch/arm/mach-kirkwood/board-mplcec4.c b/arch/arm/mach-kirkwood/board-mplcec4.c index 3264925b8318..7d6dc669e17f 100644 --- a/arch/arm/mach-kirkwood/board-mplcec4.c +++ b/arch/arm/mach-kirkwood/board-mplcec4.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "common.h" static struct mv643xx_eth_platform_data mplcec4_ge00_data = { @@ -23,11 +22,6 @@ static struct mv643xx_eth_platform_data mplcec4_ge01_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(2), }; -static struct mvsdio_platform_data mplcec4_mvsdio_data = { - .gpio_card_detect = 47, /* MPP47 used as SD card detect */ -}; - - void __init mplcec4_init(void) { /* @@ -35,7 +29,6 @@ void __init mplcec4_init(void) */ kirkwood_ge00_init(&mplcec4_ge00_data); kirkwood_ge01_init(&mplcec4_ge01_data); - kirkwood_sdio_init(&mplcec4_mvsdio_data); kirkwood_pcie_init(KW_PCIE0); } -- cgit v1.2.3 From 8059fc1de2f574db6daec76c0818b31ff840a29d Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 21 Dec 2012 15:49:13 +0100 Subject: arm: kirkwood: add pinmux option for the SDIO interface on 88F6282 This commit adds a pinmux option, pmx_sdio, to enable the muxing of the SDIO interface on the 88F6282 SoC from Marvell. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-6282.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi index 4ccea2130a6c..ff00dbb28988 100644 --- a/arch/arm/boot/dts/kirkwood-6282.dtsi +++ b/arch/arm/boot/dts/kirkwood-6282.dtsi @@ -30,6 +30,11 @@ marvell,pins = "mpp13", "mpp14"; marvell,function = "uart1"; }; + pmx_sdio: pmx-sdio { + marvell,pins = "mpp12", "mpp13", "mpp14", + "mpp15", "mpp16", "mpp17"; + marvell,function = "sdio"; + }; }; i2c@11100 { -- cgit v1.2.3 From 00211e96507a1f061d38519e2e7e385c74962c5c Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sun, 23 Dec 2012 11:34:34 +0900 Subject: ARM: Kirkwood: Add pinctrl of TWSI1 to 88f6282 The 88f6282 has one more TWSI(TWSI1). This add the information to enable pinctl of TWSI1. Signed-off-by: Nobuhiro Iwamatsu Acked-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-6282.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi index ff00dbb28988..64b937441fa0 100644 --- a/arch/arm/boot/dts/kirkwood-6282.dtsi +++ b/arch/arm/boot/dts/kirkwood-6282.dtsi @@ -21,6 +21,12 @@ marvell,pins = "mpp8", "mpp9"; marvell,function = "twsi0"; }; + + pmx_twsi1: pmx-twsi1 { + marvell,pins = "mpp36", "mpp37"; + marvell,function = "twsi1"; + }; + pmx_uart0: pmx-uart0 { marvell,pins = "mpp10", "mpp11"; marvell,function = "uart0"; -- cgit v1.2.3 From 92904699173d237c8e907ef7e4ef20a3dff577a4 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sun, 23 Dec 2012 11:34:36 +0900 Subject: ARM: Kirkwood: Add pinctrl of NAND to 88f6282 Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-6282.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi index 64b937441fa0..192cf76fbf93 100644 --- a/arch/arm/boot/dts/kirkwood-6282.dtsi +++ b/arch/arm/boot/dts/kirkwood-6282.dtsi @@ -5,6 +5,12 @@ compatible = "marvell,88f6282-pinctrl"; reg = <0x10000 0x20>; + pmx_nand: pmx-nand { + marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3", + "mpp4", "mpp5", "mpp18", "mpp19"; + marvell,function = "nand"; + }; + pmx_sata0: pmx-sata0 { marvell,pins = "mpp5", "mpp21", "mpp23"; marvell,function = "sata0"; -- cgit v1.2.3 From 50ab9554861a8e1473a16ca80cf481fa2ee0e8c9 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sun, 23 Dec 2012 11:34:37 +0900 Subject: ARM: Kirkwood: Convert openblocks A6 board to pinctrl Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-openblocks_a6.dts | 116 +++++++++++++++++++++++++++ arch/arm/mach-kirkwood/board-openblocks_a6.c | 44 ---------- 2 files changed, 116 insertions(+), 44 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts index 49d3d74d4d38..ede7fe0d7a87 100644 --- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts +++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts @@ -75,6 +75,122 @@ reg = <0x30>; }; }; + + pinctrl: pinctrl@10000 { + pinctrl-0 = < &pmx_nand &pmx_uart0 + &pmx_uart1 &pmx_twsi1 + &pmx_dip_sw0 &pmx_dip_sw1 + &pmx_dip_sw2 &pmx_dip_sw3 + &pmx_gpio_0 &pmx_gpio_1 + &pmx_gpio_2 &pmx_gpio_3 + &pmx_gpio_4 &pmx_gpio_5 + &pmx_gpio_6 &pmx_gpio_7 + &pmx_led_red &pmx_led_green + &pmx_led_yellow >; + pinctrl-names = "default"; + + pmx_uart0: pmx-uart0 { + marvell,pins = "mpp10", "mpp11", "mpp15", + "mpp16"; + marvell,function = "uart0"; + }; + + pmx_uart1: pmx-uart1 { + marvell,pins = "mpp13", "mpp14", "mpp8", + "mpp9"; + marvell,function = "uart1"; + }; + + pmx_sysrst: pmx-sysrst { + marvell,pins = "mpp6"; + marvell,function = "sysrst"; + }; + + pmx_dip_sw0: pmx-dip-sw0 { + marvell,pins = "mpp20"; + marvell,function = "gpio"; + }; + + pmx_dip_sw1: pmx-dip-sw1 { + marvell,pins = "mpp21"; + marvell,function = "gpio"; + }; + + pmx_dip_sw2: pmx-dip-sw2 { + marvell,pins = "mpp22"; + marvell,function = "gpio"; + }; + + pmx_dip_sw3: pmx-dip-sw3 { + marvell,pins = "mpp23"; + marvell,function = "gpio"; + }; + + pmx_gpio_0: pmx-gpio-0 { + marvell,pins = "mpp24"; + marvell,function = "gpio"; + }; + + pmx_gpio_1: pmx-gpio-1 { + marvell,pins = "mpp25"; + marvell,function = "gpio"; + }; + + pmx_gpio_2: pmx-gpio-2 { + marvell,pins = "mpp26"; + marvell,function = "gpio"; + }; + + pmx_gpio_3: pmx-gpio-3 { + marvell,pins = "mpp27"; + marvell,function = "gpio"; + }; + + pmx_gpio_4: pmx-gpio-4 { + marvell,pins = "mpp28"; + marvell,function = "gpio"; + }; + + pmx_gpio_5: pmx-gpio-5 { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + pmx_gpio_6: pmx-gpio-6 { + marvell,pins = "mpp30"; + marvell,function = "gpio"; + }; + + pmx_gpio_7: pmx-gpio-7 { + marvell,pins = "mpp31"; + marvell,function = "gpio"; + }; + + pmx_gpio_init: pmx-init { + marvell,pins = "mpp38"; + marvell,function = "gpio"; + }; + + pmx_usb_oc: pmx-usb-oc { + marvell,pins = "mpp39"; + marvell,function = "gpio"; + }; + + pmx_led_red: pmx-led-red { + marvell,pins = "mpp41"; + marvell,function = "gpio"; + }; + + pmx_led_green: pmx-led-green { + marvell,pins = "mpp42"; + marvell,function = "gpio"; + }; + + pmx_led_yellow: pmx-led-yellow { + marvell,pins = "mpp43"; + marvell,function = "gpio"; + }; + }; }; gpio-leds { diff --git a/arch/arm/mach-kirkwood/board-openblocks_a6.c b/arch/arm/mach-kirkwood/board-openblocks_a6.c index 815fc6451d52..b11d8fdeca93 100644 --- a/arch/arm/mach-kirkwood/board-openblocks_a6.c +++ b/arch/arm/mach-kirkwood/board-openblocks_a6.c @@ -11,60 +11,16 @@ #include #include #include -#include -#include #include "common.h" -#include "mpp.h" static struct mv643xx_eth_platform_data openblocks_ge00_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(0), }; -static unsigned int openblocks_a6_mpp_config[] __initdata = { - MPP0_NF_IO2, - MPP1_NF_IO3, - MPP2_NF_IO4, - MPP3_NF_IO5, - MPP4_NF_IO6, - MPP5_NF_IO7, - MPP6_SYSRST_OUTn, - MPP8_UART1_RTS, - MPP9_UART1_CTS, - MPP10_UART0_TXD, - MPP11_UART0_RXD, - MPP13_UART1_TXD, - MPP14_UART1_RXD, - MPP15_UART0_RTS, - MPP16_UART0_CTS, - MPP18_NF_IO0, - MPP19_NF_IO1, - MPP20_GPIO, /* DIP SW0 */ - MPP21_GPIO, /* DIP SW1 */ - MPP22_GPIO, /* DIP SW2 */ - MPP23_GPIO, /* DIP SW3 */ - MPP24_GPIO, /* GPIO 0 */ - MPP25_GPIO, /* GPIO 1 */ - MPP26_GPIO, /* GPIO 2 */ - MPP27_GPIO, /* GPIO 3 */ - MPP28_GPIO, /* GPIO 4 */ - MPP29_GPIO, /* GPIO 5 */ - MPP30_GPIO, /* GPIO 6 */ - MPP31_GPIO, /* GPIO 7 */ - MPP36_TW1_SDA, - MPP37_TW1_SCK, - MPP38_GPIO, /* INIT */ - MPP39_GPIO, /* USB OC */ - MPP41_GPIO, /* LED: Red */ - MPP42_GPIO, /* LED: Green */ - MPP43_GPIO, /* LED: Yellow */ - 0, -}; - void __init openblocks_a6_init(void) { /* * Basic setup. Needs to be called early. */ - kirkwood_mpp_conf(openblocks_a6_mpp_config); kirkwood_ge00_init(&openblocks_ge00_data); } -- cgit v1.2.3 From e35e40cd553f7950c0bcb60f1d8f9672bd69d6a2 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 27 Dec 2012 23:21:10 +0100 Subject: ARM: Dove: move CuBox led pinctrl to gpio-leds node gpio-leds has support for pinctrl allocation, make use of it. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Jason Cooper --- arch/arm/boot/dts/dove-cubox.dts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts index cdee96fca6e2..bed5b62b73a3 100644 --- a/arch/arm/boot/dts/dove-cubox.dts +++ b/arch/arm/boot/dts/dove-cubox.dts @@ -17,6 +17,9 @@ leds { compatible = "gpio-leds"; + pinctrl-0 = <&pmx_gpio_18>; + pinctrl-names = "default"; + power { label = "Power"; gpios = <&gpio0 18 1>; @@ -47,7 +50,7 @@ }; &pinctrl { - pinctrl-0 = <&pmx_gpio_12 &pmx_gpio_18>; + pinctrl-0 = <&pmx_gpio_12>; pinctrl-names = "default"; pmx_gpio_12: pmx-gpio-12 { -- cgit v1.2.3 From 41e364bb2494afe21803aff43bd8cb89ce6fc097 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 27 Dec 2012 23:21:59 +0100 Subject: ARM: Dove: add fixed regulator for CuBox USB power CuBox needs to enable USB power on a gpio pin. Add a fixed regulator to always enable usb power on boot. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Jason Cooper --- arch/arm/boot/dts/dove-cubox.dts | 25 ++++++++++++++++++++++++- arch/arm/mach-dove/Kconfig | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts index bed5b62b73a3..7e3065abd751 100644 --- a/arch/arm/boot/dts/dove-cubox.dts +++ b/arch/arm/boot/dts/dove-cubox.dts @@ -26,6 +26,24 @@ linux,default-trigger = "default-on"; }; }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + usb_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "USB Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 1 0>; + }; + }; }; &uart0 { status = "okay"; }; @@ -50,9 +68,14 @@ }; &pinctrl { - pinctrl-0 = <&pmx_gpio_12>; + pinctrl-0 = <&pmx_gpio_1 &pmx_gpio_12>; pinctrl-names = "default"; + pmx_gpio_1: pmx-gpio-1 { + marvell,pins = "mpp1"; + marvell,function = "gpio"; + }; + pmx_gpio_12: pmx-gpio-12 { marvell,pins = "mpp12"; marvell,function = "gpio"; diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig index aedd0baa04bf..36469d813951 100644 --- a/arch/arm/mach-dove/Kconfig +++ b/arch/arm/mach-dove/Kconfig @@ -24,6 +24,8 @@ config MACH_DOVE_DT bool "Marvell Dove Flattened Device Tree" select MVEBU_CLK_CORE select MVEBU_CLK_GATING + select REGULATOR + select REGULATOR_FIXED_VOLTAGE select USE_OF help Say 'Y' here if you want your kernel to support the -- cgit v1.2.3 From 12131b5424577b2eb1bef5a41220d310594e42dc Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 28 Dec 2012 15:08:48 +0100 Subject: ARM: Kirkwood: Convert NSA310 to DT based regulators. Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-nsa310.dts | 17 +++++++++++++++++ arch/arm/mach-kirkwood/board-nsa310.c | 4 ---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts index 5509f9659546..2dc1d0929e89 100644 --- a/arch/arm/boot/dts/kirkwood-nsa310.dts +++ b/arch/arm/boot/dts/kirkwood-nsa310.dts @@ -141,4 +141,21 @@ gpios = <&gpio1 8 0>; }; }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + usb0_power_off: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "USB Power Off"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 21 0>; + }; + }; }; diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c index 2fa71400ecb3..891322b44633 100644 --- a/arch/arm/mach-kirkwood/board-nsa310.c +++ b/arch/arm/mach-kirkwood/board-nsa310.c @@ -17,7 +17,6 @@ #include "common.h" #include "mpp.h" -#define NSA310_GPIO_USB_POWER_OFF 21 #define NSA310_GPIO_POWER_OFF 48 static unsigned int nsa310_mpp_config[] __initdata = { @@ -70,9 +69,6 @@ static void __init nsa310_gpio_init(void) "Power Off"); if (!err) pm_power_off = nsa310_power_off; - - nsa310_gpio_request(NSA310_GPIO_USB_POWER_OFF, GPIOF_OUT_INIT_LOW, - "USB Power Off"); } void __init nsa310_init(void) -- cgit v1.2.3 From 7dcc628349de9a878c43ef4b30e6c8ccbe1d207a Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 28 Dec 2012 15:08:49 +0100 Subject: ARM: Kirkwood: Convert NSA310 to use gpio-poweroff driver Remove the C code and add a Device Tree node for gpio-poweroff. Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-nsa310.dts | 5 +++++ arch/arm/mach-kirkwood/board-nsa310.c | 33 --------------------------------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts index 2dc1d0929e89..85cce36491da 100644 --- a/arch/arm/boot/dts/kirkwood-nsa310.dts +++ b/arch/arm/boot/dts/kirkwood-nsa310.dts @@ -142,6 +142,11 @@ }; }; + gpio_poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio1 16 0>; + }; + regulators { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c index 891322b44633..cf2c78cf6513 100644 --- a/arch/arm/mach-kirkwood/board-nsa310.c +++ b/arch/arm/mach-kirkwood/board-nsa310.c @@ -11,14 +11,11 @@ #include #include #include -#include #include #include #include "common.h" #include "mpp.h" -#define NSA310_GPIO_POWER_OFF 48 - static unsigned int nsa310_mpp_config[] __initdata = { MPP12_GPIO, /* led esata green */ MPP13_GPIO, /* led esata red */ @@ -43,40 +40,10 @@ static struct i2c_board_info __initdata nsa310_i2c_info[] = { { I2C_BOARD_INFO("adt7476", 0x2e) }, }; -static void nsa310_power_off(void) -{ - gpio_set_value(NSA310_GPIO_POWER_OFF, 1); -} - -static int __init nsa310_gpio_request(unsigned int gpio, unsigned long flags, - const char *label) -{ - int err; - - err = gpio_request_one(gpio, flags, label); - if (err) - pr_err("NSA-310: can't setup GPIO%u (%s), err=%d\n", - gpio, label, err); - - return err; -} - -static void __init nsa310_gpio_init(void) -{ - int err; - - err = nsa310_gpio_request(NSA310_GPIO_POWER_OFF, GPIOF_OUT_INIT_LOW, - "Power Off"); - if (!err) - pm_power_off = nsa310_power_off; -} - void __init nsa310_init(void) { kirkwood_mpp_conf(nsa310_mpp_config); - nsa310_gpio_init(); - i2c_register_board_info(0, ARRAY_AND_SIZE(nsa310_i2c_info)); } -- cgit v1.2.3 From b4d2a24fa522afd3891c9718443686cab71df24f Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 28 Dec 2012 15:08:50 +0100 Subject: ARM: Kirkwood: Convert NSA310 I2C to device tree Add a sub-node into the I2C node to represent the adt7476 device. Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-nsa310.dts | 5 +++++ arch/arm/mach-kirkwood/board-nsa310.c | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts index 85cce36491da..dbb3551017fe 100644 --- a/arch/arm/boot/dts/kirkwood-nsa310.dts +++ b/arch/arm/boot/dts/kirkwood-nsa310.dts @@ -29,6 +29,11 @@ i2c@11000 { status = "okay"; + + adt7476: adt7476a@2e { + compatible = "adt7476"; + reg = <0x2e>; + }; }; nand@3000000 { diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c index cf2c78cf6513..6966c86e0c34 100644 --- a/arch/arm/mach-kirkwood/board-nsa310.c +++ b/arch/arm/mach-kirkwood/board-nsa310.c @@ -36,15 +36,9 @@ static unsigned int nsa310_mpp_config[] __initdata = { 0 }; -static struct i2c_board_info __initdata nsa310_i2c_info[] = { - { I2C_BOARD_INFO("adt7476", 0x2e) }, -}; - void __init nsa310_init(void) { kirkwood_mpp_conf(nsa310_mpp_config); - - i2c_register_board_info(0, ARRAY_AND_SIZE(nsa310_i2c_info)); } static int __init nsa310_pci_init(void) -- cgit v1.2.3 From 102c9543ff368709980c6d68b7a75f840edda6b5 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 28 Dec 2012 15:14:10 +0100 Subject: ARM: Kirkwood: Convert NS2 to gpio-poweroff. Remove C code and add a Device Tree node in its place. Signed-off-by: Andrew Lunn Tested-by: Simon Guinot Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-ns2-common.dtsi | 6 ++++++ arch/arm/mach-kirkwood/board-ns2.c | 14 -------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi index 77d21abfcdf7..e8e7ecef1650 100644 --- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi @@ -76,4 +76,10 @@ gpios = <&gpio0 12 0>; }; }; + + gpio_poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 31 0>; + }; + }; diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c index f4632a809f68..f2ea3b7ad726 100644 --- a/arch/arm/mach-kirkwood/board-ns2.c +++ b/arch/arm/mach-kirkwood/board-ns2.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "common.h" @@ -23,13 +22,6 @@ static struct mv643xx_eth_platform_data ns2_ge00_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; -#define NS2_GPIO_POWER_OFF 31 - -static void ns2_power_off(void) -{ - gpio_set_value(NS2_GPIO_POWER_OFF, 1); -} - void __init ns2_init(void) { /* @@ -39,10 +31,4 @@ void __init ns2_init(void) of_machine_is_compatible("lacie,netspace_mini_v2")) ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0); kirkwood_ge00_init(&ns2_ge00_data); - - if (gpio_request(NS2_GPIO_POWER_OFF, "power-off") == 0 && - gpio_direction_output(NS2_GPIO_POWER_OFF, 0) == 0) - pm_power_off = ns2_power_off; - else - pr_err("ns2: failed to configure power-off GPIO\n"); } -- cgit v1.2.3 From 4ca73962a15caccd310093266783be89a81d571f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 7 Jan 2013 17:29:58 +0100 Subject: arm: mvebu: add button for OpenBlocks AX3-4 The OpenBlocks AX3-4 board has one software-controlled button on the front side, labeled "INIT", so we add minimal support for this button in the kernel. Signed-off-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts index b42652fd3d8c..ec368643e478 100644 --- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts @@ -66,6 +66,18 @@ }; }; + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + button@1 { + label = "Init Button"; + linux,code = <116>; + gpios = <&gpio1 28 0>; + }; + }; + mdio { phy0: ethernet-phy@0 { reg = <0>; -- cgit v1.2.3 From b2bb806f553f57459b8052fc5b8e2489e21ddf24 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 23 Jan 2013 12:26:30 -0300 Subject: arm: mvebu: Add support for USB host controllers in Armada 370/XP The Armada 370 and Armada XP SoC has an Orion EHCI USB controller. This patch adds support for this controller in Armada 370 and Armada XP SoC common device tree files. Cc: Lior Amsalem Cc: Thomas Petazzoni Tested-by: Nobuhiro Iwamatsu Tested-by: Florian Fainelli Signed-off-by: Gregory CLEMENT Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-xp.dtsi | 15 +++++++++++++++ arch/arm/boot/dts/armada-370.dtsi | 9 +++++++++ arch/arm/boot/dts/armada-xp.dtsi | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index 28276fe79d28..fa025c44abda 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -145,6 +145,21 @@ clocks = <&gateclk 17>; status = "disabled"; }; + + usb@d0050000 { + compatible = "marvell,orion-ehci"; + reg = <0xd0050000 0x500>; + interrupts = <45>; + status = "disabled"; + }; + + usb@d0051000 { + compatible = "marvell,orion-ehci"; + reg = <0xd0051000 0x500>; + interrupts = <46>; + status = "disabled"; + }; + }; }; diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi index 88f9bab44d52..8188d138020e 100644 --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi @@ -144,5 +144,14 @@ dmacap,memset; }; }; + + usb@d0050000 { + clocks = <&coreclk 0>; + }; + + usb@d0051000 { + clocks = <&coreclk 0>; + }; + }; }; diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 390ba9888f36..1443949c165e 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -134,5 +134,22 @@ dmacap,memset; }; }; + + usb@d0050000 { + clocks = <&gateclk 18>; + }; + + usb@d0051000 { + clocks = <&gateclk 19>; + }; + + usb@d0052000 { + compatible = "marvell,orion-ehci"; + reg = <0xd0052000 0x500>; + interrupts = <47>; + clocks = <&gateclk 20>; + status = "disabled"; + }; + }; }; -- cgit v1.2.3 From 200506b1b616f1b3ccef41b19446e4e8ea0f9b68 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 23 Jan 2013 12:26:31 -0300 Subject: arm: mvebu: Enable USB controllers on Armada 370/XP boards This patch activates every USB port provided by each SoC. Except for Armada XP Openblocks AX3-4 board, where we enable only the first two USB ports until we have more information on the third one usage. Cc: Lior Amsalem Cc: Thomas Petazzoni Cc: Gregory CLEMENT Tested-by: Nobuhiro Iwamatsu Tested-by: Florian Fainelli Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-db.dts | 8 ++++++++ arch/arm/boot/dts/armada-370-mirabox.dts | 8 ++++++++ arch/arm/boot/dts/armada-xp-db.dts | 12 ++++++++++++ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 6 ++++++ 4 files changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 8e66a7c00e18..3d93902048db 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -74,5 +74,13 @@ status = "disabled"; /* No CD or WP GPIOs */ }; + + usb@d0050000 { + status = "okay"; + }; + + usb@d0051000 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts index 1864820dde25..dd0c57dd9f30 100644 --- a/arch/arm/boot/dts/armada-370-mirabox.dts +++ b/arch/arm/boot/dts/armada-370-mirabox.dts @@ -62,5 +62,13 @@ * Wifi/Bluetooth chip */ }; + + usb@d0050000 { + status = "okay"; + }; + + usb@d0051000 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index c7035c5d0dee..c84e1feddd68 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts @@ -97,5 +97,17 @@ status = "okay"; /* No CD or WP GPIOs */ }; + + usb@d0050000 { + status = "okay"; + }; + + usb@d0051000 { + status = "okay"; + }; + + usb@d0052000 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts index ec368643e478..3818a82176a2 100644 --- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts @@ -133,5 +133,11 @@ nr-ports = <2>; status = "okay"; }; + usb@d0050000 { + status = "okay"; + }; + usb@d0051000 { + status = "okay"; + }; }; }; -- cgit v1.2.3 From a1abcd7c2339088a6628381fa13239d89d639961 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Mon, 28 Jan 2013 16:54:08 +0100 Subject: ARM: Dove: convert usb host controller to DT With DT support for orion-ehci also convert Dove to it and remove the legacy calls and clock aliases. This patch is based on "ARM: Dove: split legacy and DT setup" applied to mvebu/boards recently. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Jason Cooper --- arch/arm/boot/dts/dove.dtsi | 16 ++++++++++++++++ arch/arm/mach-dove/board-dt.c | 10 ---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index 740630f9cd65..c07220300714 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi @@ -156,6 +156,22 @@ status = "disabled"; }; + ehci0: usb-host@50000 { + compatible = "marvell,orion-ehci"; + reg = <0x50000 0x1000>; + interrupts = <24>; + clocks = <&gate_clk 0>; + status = "okay"; + }; + + ehci1: usb-host@51000 { + compatible = "marvell,orion-ehci"; + reg = <0x51000 0x1000>; + interrupts = <25>; + clocks = <&gate_clk 1>; + status = "okay"; + }; + sdio0: sdio@92000 { compatible = "marvell,dove-sdhci"; reg = <0x92000 0x100>; diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c index 61c2b595494a..fbde1dd67113 100644 --- a/arch/arm/mach-dove/board-dt.c +++ b/arch/arm/mach-dove/board-dt.c @@ -34,14 +34,6 @@ static void __init dove_legacy_clk_init(void) clkspec.np = np; clkspec.args_count = 1; - clkspec.args[0] = CLOCK_GATING_BIT_USB0; - orion_clkdev_add(NULL, "orion-ehci.0", - of_clk_get_from_provider(&clkspec)); - - clkspec.args[0] = CLOCK_GATING_BIT_USB1; - orion_clkdev_add(NULL, "orion-ehci.1", - of_clk_get_from_provider(&clkspec)); - clkspec.args[0] = CLOCK_GATING_BIT_GBE; orion_clkdev_add(NULL, "mv643xx_eth_port.0", of_clk_get_from_provider(&clkspec)); @@ -79,8 +71,6 @@ static void __init dove_dt_init(void) /* Internal devices not ported to DT yet */ dove_ge00_init(&dove_dt_ge00_data); - dove_ehci0_init(); - dove_ehci1_init(); dove_pcie_init(1, 1); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -- cgit v1.2.3 From e1dd464901080ecf7ebd3fd27dfc5735719055f4 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 25 Jan 2013 18:32:44 +0100 Subject: arm: mvebu: update DT to support local timers Now that the time-armada-370-xp support local timers, updated the device tree to take it into account. Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-xp.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index fa025c44abda..cb434b2de628 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -68,8 +68,9 @@ timer@d0020300 { compatible = "marvell,armada-370-xp-timer"; - reg = <0xd0020300 0x30>; - interrupts = <37>, <38>, <39>, <40>; + reg = <0xd0020300 0x30>, + <0xd0021040 0x30>; + interrupts = <37>, <38>, <39>, <40>, <5>, <6>; clocks = <&coreclk 2>; }; -- cgit v1.2.3 From 37dd39513c33d518ccd8ea39ebe43d0f117590da Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 25 Jan 2013 18:32:45 +0100 Subject: clocksource: update and move armada-370-xp-timer documentation to timer directory Timer driver for Armada 370 and Armada XP have gained local timers support. So it needs new resources information regarding the IRQs and the registers. Also move the documentation in the new and more accurate directory Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- .../devicetree/bindings/arm/armada-370-xp-timer.txt | 12 ------------ .../bindings/timer/marvell,armada-370-xp-timer.txt | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 12 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt create mode 100644 Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt deleted file mode 100644 index 64830118b013..000000000000 --- a/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt +++ /dev/null @@ -1,12 +0,0 @@ -Marvell Armada 370 and Armada XP Global Timers ----------------------------------------------- - -Required properties: -- compatible: Should be "marvell,armada-370-xp-timer" -- interrupts: Should contain the list of Global Timer interrupts -- reg: Should contain the base address of the Global Timer registers -- clocks: clock driving the timer hardware - -Optional properties: -- marvell,timer-25Mhz: Tells whether the Global timer supports the 25 - Mhz fixed mode (available on Armada XP and not on Armada 370) diff --git a/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt b/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt new file mode 100644 index 000000000000..36381129d141 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt @@ -0,0 +1,15 @@ +Marvell Armada 370 and Armada XP Timers +--------------------------------------- + +Required properties: +- compatible: Should be "marvell,armada-370-xp-timer" +- interrupts: Should contain the list of Global Timer interrupts and + then local timer interrupts +- reg: Should contain location and length for timers register. First + pair for the Global Timer registers, second pair for the + local/private timers. +- clocks: clock driving the timer hardware + +Optional properties: +- marvell,timer-25Mhz: Tells whether the Global timer supports the 25 + Mhz fixed mode (available on Armada XP and not on Armada 370) -- cgit v1.2.3 From d5dc035eaa967cded8a295d4b07b7eb944c9044a Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 6 Feb 2013 10:06:21 -0300 Subject: arm: mvebu: Add support for SPI controller in Armada 370/XP The Armada 370 and Armada XP SoC has an SPI controller. This patch adds support for this controller in Armada 370 and Armada XP SoC common device tree files. Note that the Armada XP SPI register length is 0x50 bytes, while Armada 370 SPI register length is 0x28 bytes, so we choose the smaller of the two. Cc: Thomas Petazzoni Cc: Lior Amsalem Acked-by: Gregory Clement Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-xp.dtsi | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index cb434b2de628..6f1acc75e155 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -161,6 +161,27 @@ status = "disabled"; }; + spi0: spi@d0010600 { + compatible = "marvell,orion-spi"; + reg = <0xd0010600 0x28>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <30>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + spi1: spi@d0010680 { + compatible = "marvell,orion-spi"; + reg = <0xd0010680 0x28>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + interrupts = <92>; + clocks = <&coreclk 0>; + status = "disabled"; + }; }; }; -- cgit v1.2.3 From 9dc3e34687b2af14d5b8e95b27d06b6cdfc87479 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 6 Feb 2013 10:06:23 -0300 Subject: arm: mvebu: Add SPI flash on Armada XP-GP board This patch adds an SPI master device node for Armada XP-GP board. This master node is an SPI flash controller 'n25q128a13'. Since there is no 'partitions' node declared, one full sized partition named as the device will be created. Cc: Thomas Petazzoni Cc: Lior Amsalem Tested-by: Gregory Clement Signed-off-by: Ezequiel Garcia Acked-by: Gregory Clement Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-gp.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts index 3eea53106a1f..1c8afe2ffebc 100644 --- a/arch/arm/boot/dts/armada-xp-gp.dts +++ b/arch/arm/boot/dts/armada-xp-gp.dts @@ -97,5 +97,17 @@ phy = <&phy3>; phy-mode = "rgmii-id"; }; + + spi0: spi@d0010600 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; + }; }; }; -- cgit v1.2.3 From 1f24a21f8e8acd6e85b3629f41e2eafbcd86d85c Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Tue, 5 Feb 2013 21:54:54 +0100 Subject: arm: mvebu: Add SPI flash on Armada XP-DB board This patch add support for the SPI flash M25P64 which is present on the Armada XP DB board. This flash stores the bootloader and its environment. Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-db.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index c84e1feddd68..e83505e4c236 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts @@ -109,5 +109,17 @@ usb@d0052000 { status = "okay"; }; + + spi0: spi@d0010600 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p64"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <20000000>; + }; + }; }; }; -- cgit v1.2.3 From 04e09b72731f4a49f8f0c2f882fe838a865c847c Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Tue, 5 Feb 2013 21:54:55 +0100 Subject: arm: mvebu: Add SPI flash on Armada 370 DB board This patch add support for the SPI flash MX25l25635E which is present on the Armada 370 DB board. This flash stores the bootloader and its environment. Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-db.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 3d93902048db..e34b280ce6ec 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -82,5 +82,17 @@ usb@d0051000 { status = "okay"; }; + + spi0: spi@d0010600 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l25635e"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + }; + }; }; }; -- cgit v1.2.3 From 8be7a962e86ac47b5ee2b339e08cca1e5c063c15 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Tue, 29 Jan 2013 21:59:46 +0100 Subject: ARM: dove: convert serial DT nodes to clocks property of_serial now has support for using clocks property and we have a DT clock provider. This patch replaces the hard coded clock-frequency property with a clocks phandle to tclk. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Jason Cooper --- arch/arm/boot/dts/dove.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index c07220300714..67dbe20868a2 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi @@ -55,7 +55,7 @@ reg = <0x12000 0x100>; reg-shift = <2>; interrupts = <7>; - clock-frequency = <166666667>; + clocks = <&core_clk 0>; status = "disabled"; }; @@ -64,7 +64,7 @@ reg = <0x12100 0x100>; reg-shift = <2>; interrupts = <8>; - clock-frequency = <166666667>; + clocks = <&core_clk 0>; status = "disabled"; }; @@ -73,7 +73,7 @@ reg = <0x12000 0x100>; reg-shift = <2>; interrupts = <9>; - clock-frequency = <166666667>; + clocks = <&core_clk 0>; status = "disabled"; }; @@ -82,7 +82,7 @@ reg = <0x12100 0x100>; reg-shift = <2>; interrupts = <10>; - clock-frequency = <166666667>; + clocks = <&core_clk 0>; status = "disabled"; }; -- cgit v1.2.3 From 15989543d45505ed32e70505c2fce0907e5af161 Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Sat, 26 Jan 2013 20:50:11 +0000 Subject: ARM: kirkwood: topkick: convert to pinctrl Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-topkick.dts | 90 ++++++++++++++++++++++++++++++ arch/arm/mach-kirkwood/board-usi_topkick.c | 42 -------------- 2 files changed, 90 insertions(+), 42 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts index cd15452a52a6..bb1d4df5c690 100644 --- a/arch/arm/boot/dts/kirkwood-topkick.dts +++ b/arch/arm/boot/dts/kirkwood-topkick.dts @@ -1,6 +1,7 @@ /dts-v1/; /include/ "kirkwood.dtsi" +/include/ "kirkwood-6282.dtsi" / { model = "Univeral Scientific Industrial Co. Topkick-1281P2"; @@ -16,6 +17,95 @@ }; ocp@f1000000 { + pinctrl: pinctrl@10000 { + /* + * GPIO LED layout + * + * /-SYS_LED(2) + * | + * | /-DISK_LED + * | | + * | | /-WLAN_LED(2) + * | | | + * [SW] [*] [*] [*] + */ + + /* + * Switch positions + * + * /-SW_LEFT(2) + * | + * | /-SW_IDLE + * | | + * | | /-SW_RIGHT + * | | | + * PS [L] [I] [R] LEDS + */ + pinctrl-0 = < &pmx_led_disk_yellow + &pmx_sata0_pwr_enable + &pmx_led_sys_red + &pmx_led_sys_blue + &pmx_led_wifi_green + &pmx_sw_left + &pmx_sw_right + &pmx_sw_idle + &pmx_sw_left2 + &pmx_led_wifi_yellow + &pmx_uart0 + &pmx_nand >; + pinctrl-names = "default"; + + pmx_led_disk_yellow: pmx-led-disk-yellow { + marvell,pins = "mpp21"; + marvell,function = "gpio"; + }; + + pmx_sata0_pwr_enable: pmx-sata0-pwr-enable { + marvell,pins = "mpp36"; + marvell,function = "gpio"; + }; + + pmx_led_sys_red: pmx-led-sys-red { + marvell,pins = "mpp37"; + marvell,function = "gpio"; + }; + + pmx_led_sys_blue: pmx-led-sys-blue { + marvell,pins = "mpp38"; + marvell,function = "gpio"; + }; + + pmx_led_wifi_green: pmx-led-wifi-green { + marvell,pins = "mpp39"; + marvell,function = "gpio"; + }; + + pmx_sw_left: pmx-sw-left { + marvell,pins = "mpp43"; + marvell,function = "gpio"; + }; + + pmx_sw_right: pmx-sw-right { + marvell,pins = "mpp44"; + marvell,function = "gpio"; + }; + + pmx_sw_idle: pmx-sw-idle { + marvell,pins = "mpp45"; + marvell,function = "gpio"; + }; + + pmx_sw_left2: pmx-sw-left2 { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + + pmx_led_wifi_yellow: pmx-led-wifi-yellow { + marvell,pins = "mpp48"; + marvell,function = "gpio"; + }; + }; + serial@12000 { clock-frequency = <200000000>; status = "ok"; diff --git a/arch/arm/mach-kirkwood/board-usi_topkick.c b/arch/arm/mach-kirkwood/board-usi_topkick.c index 23d2dd1b1b1e..3fce1d018966 100644 --- a/arch/arm/mach-kirkwood/board-usi_topkick.c +++ b/arch/arm/mach-kirkwood/board-usi_topkick.c @@ -16,7 +16,6 @@ #include #include #include "common.h" -#include "mpp.h" static struct mv643xx_eth_platform_data topkick_ge00_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(0), @@ -26,52 +25,11 @@ static struct mvsdio_platform_data topkick_mvsdio_data = { /* unfortunately the CD signal has not been connected */ }; -/* - * GPIO LED layout - * - * /-SYS_LED(2) - * | - * | /-DISK_LED - * | | - * | | /-WLAN_LED(2) - * | | | - * [SW] [*] [*] [*] - */ - -/* - * Switch positions - * - * /-SW_LEFT - * | - * | /-SW_IDLE - * | | - * | | /-SW_RIGHT - * | | | - * PS [L] [I] [R] LEDS - */ - -static unsigned int topkick_mpp_config[] __initdata = { - MPP21_GPIO, /* DISK_LED (low active) - yellow */ - MPP36_GPIO, /* SATA0 power enable (high active) */ - MPP37_GPIO, /* SYS_LED2 (low active) - red */ - MPP38_GPIO, /* SYS_LED (low active) - blue */ - MPP39_GPIO, /* WLAN_LED (low active) - green */ - MPP43_GPIO, /* SW_LEFT (low active) */ - MPP44_GPIO, /* SW_RIGHT (low active) */ - MPP45_GPIO, /* SW_IDLE (low active) */ - MPP46_GPIO, /* SW_LEFT (low active) */ - MPP48_GPIO, /* WLAN_LED2 (low active) - yellow */ - 0 -}; - void __init usi_topkick_init(void) { /* * Basic setup. Needs to be called early. */ - kirkwood_mpp_conf(topkick_mpp_config); - - kirkwood_ge00_init(&topkick_ge00_data); kirkwood_sdio_init(&topkick_mvsdio_data); } -- cgit v1.2.3 From 44d032e7940131fd991a01a948630747d91fe983 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 26 Jan 2013 20:50:12 +0000 Subject: ARM: Kirkwood: topkick: Enable i2c bus. Add a DT node for I2C and pinctrl hog for the pins. There appears to be an i2c bus on topkick with a device on it: i2cdetect 0 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-0. I will probe address range 0x03-0x77. Continue? [Y/n] y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- 64 -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- Signed-off-by: Andrew Lunn Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-topkick.dts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts index bb1d4df5c690..754f7efc0eec 100644 --- a/arch/arm/boot/dts/kirkwood-topkick.dts +++ b/arch/arm/boot/dts/kirkwood-topkick.dts @@ -52,7 +52,8 @@ &pmx_sw_left2 &pmx_led_wifi_yellow &pmx_uart0 - &pmx_nand >; + &pmx_nand + &pmx_twsi0 >; pinctrl-names = "default"; pmx_led_disk_yellow: pmx-led-disk-yellow { @@ -144,6 +145,10 @@ status = "okay"; nr-ports = <1>; }; + + i2c@11000 { + status = "ok"; + }; }; gpio-leds { -- cgit v1.2.3 From 4ded65751c262e4897dbaf8c11d11d85332eecf3 Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Sat, 26 Jan 2013 20:50:14 +0000 Subject: ARM: kirkwood: nsa310: convert to pinctrl Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-nsa310.dts | 99 +++++++++++++++++++++++++++++++++++ arch/arm/mach-kirkwood/board-dt.c | 3 -- arch/arm/mach-kirkwood/board-nsa310.c | 26 --------- arch/arm/mach-kirkwood/common.h | 6 --- 4 files changed, 99 insertions(+), 35 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts index dbb3551017fe..3a178cf708d7 100644 --- a/arch/arm/boot/dts/kirkwood-nsa310.dts +++ b/arch/arm/boot/dts/kirkwood-nsa310.dts @@ -16,6 +16,105 @@ }; ocp@f1000000 { + pinctrl: pinctrl@10000 { + pinctrl-0 = < &pmx_led_esata_green + &pmx_led_esata_red + &pmx_led_usb_green + &pmx_led_usb_red + &pmx_usb_power_off + &pmx_led_sys_green + &pmx_led_sys_red + &pmx_btn_reset + &pmx_btn_copy + &pmx_led_copy_green + &pmx_led_copy_red + &pmx_led_hdd_green + &pmx_led_hdd_red + &pmx_unknown + &pmx_btn_power + &pmx_pwr_off >; + pinctrl-names = "default"; + + pmx_led_esata_green: pmx-led-esata-green { + marvell,pins = "mpp12"; + marvell,function = "gpio"; + }; + + pmx_led_esata_red: pmx-led-esata-red { + marvell,pins = "mpp13"; + marvell,function = "gpio"; + }; + + pmx_led_usb_green: pmx-led-usb-green { + marvell,pins = "mpp15"; + marvell,function = "gpio"; + }; + + pmx_led_usb_red: pmx-led-usb-red { + marvell,pins = "mpp16"; + marvell,function = "gpio"; + }; + + pmx_usb_power_off: pmx-usb-power-off { + marvell,pins = "mpp21"; + marvell,function = "gpio"; + }; + + pmx_led_sys_green: pmx-led-sys-green { + marvell,pins = "mpp28"; + marvell,function = "gpio"; + }; + + pmx_led_sys_red: pmx-led-sys-red { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + pmx_btn_reset: pmx-btn-reset { + marvell,pins = "mpp36"; + marvell,function = "gpio"; + }; + + pmx_btn_copy: pmx-btn-copy { + marvell,pins = "mpp37"; + marvell,function = "gpio"; + }; + + pmx_led_copy_green: pmx-led-copy-green { + marvell,pins = "mpp39"; + marvell,function = "gpio"; + }; + + pmx_led_copy_red: pmx-led-copy-red { + marvell,pins = "mpp40"; + marvell,function = "gpio"; + }; + + pmx_led_hdd_green: pmx-led-hdd-green { + marvell,pins = "mpp41"; + marvell,function = "gpio"; + }; + + pmx_led_hdd_red: pmx-led-hdd-red { + marvell,pins = "mpp42"; + marvell,function = "gpio"; + }; + + pmx_unknown: pmx-unknown { + marvell,pins = "mpp44"; + marvell,function = "gpio"; + }; + + pmx_btn_power: pmx-btn-power { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + + pmx_pwr_off: pmx-pwr-off { + marvell,pins = "mpp48"; + marvell,function = "gpio"; + }; + }; serial@12000 { clock-frequency = <200000000>; diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 05b3b7ea41f7..2e73e9d53f70 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -144,9 +144,6 @@ static void __init kirkwood_dt_init(void) if (of_machine_is_compatible("usi,topkick")) usi_topkick_init(); - if (of_machine_is_compatible("zyxel,nsa310")) - nsa310_init(); - of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL); } diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c index 6966c86e0c34..544f83a46679 100644 --- a/arch/arm/mach-kirkwood/board-nsa310.c +++ b/arch/arm/mach-kirkwood/board-nsa310.c @@ -14,32 +14,6 @@ #include #include #include "common.h" -#include "mpp.h" - -static unsigned int nsa310_mpp_config[] __initdata = { - MPP12_GPIO, /* led esata green */ - MPP13_GPIO, /* led esata red */ - MPP15_GPIO, /* led usb green */ - MPP16_GPIO, /* led usb red */ - MPP21_GPIO, /* control usb power off */ - MPP28_GPIO, /* led sys green */ - MPP29_GPIO, /* led sys red */ - MPP36_GPIO, /* key reset */ - MPP37_GPIO, /* key copy */ - MPP39_GPIO, /* led copy green */ - MPP40_GPIO, /* led copy red */ - MPP41_GPIO, /* led hdd green */ - MPP42_GPIO, /* led hdd red */ - MPP44_GPIO, /* ?? */ - MPP46_GPIO, /* key power */ - MPP48_GPIO, /* control power off */ - 0 -}; - -void __init nsa310_init(void) -{ - kirkwood_mpp_conf(nsa310_mpp_config); -} static int __init nsa310_pci_init(void) { diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 537bdf816af7..5ed70565c843 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -135,12 +135,6 @@ void ns2_init(void); static inline void ns2_init(void) {}; #endif -#ifdef CONFIG_MACH_NSA310_DT -void nsa310_init(void); -#else -static inline void nsa310_init(void) {}; -#endif - #ifdef CONFIG_MACH_OPENBLOCKS_A6_DT void openblocks_a6_init(void); #else -- cgit v1.2.3 From 0dbe6ce0373394ff79744684b78e37bc4430daac Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Sat, 26 Jan 2013 20:50:10 +0000 Subject: ARM: kirkwood: topkick: init mvsdio via DT Signed-off-by: Jason Cooper Tested-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-topkick.dts | 7 +++++++ arch/arm/mach-kirkwood/board-usi_topkick.c | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts index 754f7efc0eec..842ff95d60df 100644 --- a/arch/arm/boot/dts/kirkwood-topkick.dts +++ b/arch/arm/boot/dts/kirkwood-topkick.dts @@ -149,6 +149,13 @@ i2c@11000 { status = "ok"; }; + + mvsdio@90000 { + pinctrl-0 = <&pmx_sdio>; + pinctrl-names = "default"; + status = "okay"; + /* No CD or WP GPIOs */ + }; }; gpio-leds { diff --git a/arch/arm/mach-kirkwood/board-usi_topkick.c b/arch/arm/mach-kirkwood/board-usi_topkick.c index 3fce1d018966..1cc04ec33f0b 100644 --- a/arch/arm/mach-kirkwood/board-usi_topkick.c +++ b/arch/arm/mach-kirkwood/board-usi_topkick.c @@ -14,22 +14,16 @@ #include #include #include -#include #include "common.h" static struct mv643xx_eth_platform_data topkick_ge00_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(0), }; -static struct mvsdio_platform_data topkick_mvsdio_data = { - /* unfortunately the CD signal has not been connected */ -}; - void __init usi_topkick_init(void) { /* * Basic setup. Needs to be called early. */ kirkwood_ge00_init(&topkick_ge00_data); - kirkwood_sdio_init(&topkick_mvsdio_data); } -- cgit v1.2.3 From 564991205956d869db0e45dfabe23a31b596fa15 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 1 Feb 2013 11:38:28 +0100 Subject: arm: mvebu: enable the SD card slot on Armada 370 Reference Design board The Armada 370 Reference Design board has one SD card slot, directly connected to the SDIO IP of the SoC, so we enable this IP. there are no GPIOs for card-detect and write-protect so we do not specify any. Signed-off-by: Florian Fainelli Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-rd.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts index d62dfac61924..f8e4855bc9a5 100644 --- a/arch/arm/boot/dts/armada-370-rd.dts +++ b/arch/arm/boot/dts/armada-370-rd.dts @@ -57,5 +57,12 @@ phy = <&phy1>; phy-mode = "rgmii-id"; }; + + mvsdio@d00d4000 { + pinctrl-0 = <&sdio_pins1>; + pinctrl-names = "default"; + status = "okay"; + /* No CD or WP GPIOs */ + }; }; }; -- cgit v1.2.3