From: Wolfram Sang <hidden> Date: 2011-02-10 19:14:46
Hi,
I finally could do a second version of my write protect-patches and the first
version of a card detect approach (thanks to Olof for the inspiration here).
Note that these feature are only needed for i.mx25/35 as the i.mx5x-series
_finally_ seem to be able to route the gpios to the controller directly.
These patches apply to mmc-next and have been tested with a mx35-based pcm043.
I think the first three patches should go via Chris and the latter two via
Sascha. The last one is more a cleanup-patch, but it depends on the former, so
I included it here.
The branch can be found at:
git://git.pengutronix.de/git/wsa/linux-2.6.git pcm043-mmc
Eric: Would be awesome if you could test these on your boards!
Looking forward to comments,
Wolfram
Wolfram Sang (5):
mmc: sdhci-esdhc-imx: add support for write protect on custom GPIO
mmc: sdhci-esdhc: broken card detection is not a default quirk
mmc: sdhci-esdhc-imx: add card detect on custom GPIO
arm: mach-mx3: pcm043: add write-protect and card-detect for SD1
arm: mach-mx3: use IMX_GPIO_NR instead of hard-coded values
arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c | 4 +-
arch/arm/mach-mx3/mach-cpuimx35.c | 2 +-
arch/arm/mach-mx3/mach-pcm043.c | 19 +++-
arch/arm/plat-mxc/include/mach/esdhc.h | 12 ++-
drivers/mmc/host/sdhci-esdhc-imx.c | 129 +++++++++++++++++++++++---
drivers/mmc/host/sdhci-esdhc.h | 1 -
drivers/mmc/host/sdhci-of-esdhc.c | 3 +-
7 files changed, 148 insertions(+), 22 deletions(-)
--
1.7.2.3
@@ -100,10 +102,31 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)returnclk_get_rate(pltfm_host->clk)/256/16;}+staticunsignedintesdhc_pltfm_get_ro(structsdhci_host*host)+{+structesdhc_platform_data*boarddata=host->mmc->parent->platform_data;++if(boarddata&&gpio_is_valid(boarddata->wp_gpio))+returngpio_get_value(boarddata->wp_gpio);+else+return-ENOSYS;+}++staticstructsdhci_opssdhci_esdhc_ops={+.read_w=esdhc_readw_le,+.write_w=esdhc_writew_le,+.write_b=esdhc_writeb_le,+.set_clock=esdhc_set_clock,+.get_max_clock=esdhc_pltfm_get_max_clock,+.get_min_clock=esdhc_pltfm_get_min_clock,+};+staticintesdhc_pltfm_init(structsdhci_host*host,structsdhci_pltfm_data*pdata){structsdhci_pltfm_host*pltfm_host=sdhci_priv(host);+structesdhc_platform_data*boarddata=host->mmc->parent->platform_data;structclk*clk;+interr;clk=clk_get(mmc_dev(host->mmc),NULL);if(IS_ERR(clk)){
@@ -116,9 +139,20 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdif(cpu_is_mx35()||cpu_is_mx51())host->quirks|=SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;-/* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */-if(cpu_is_mx25()||cpu_is_mx35())+if(cpu_is_mx25()||cpu_is_mx35()){+/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */host->quirks|=SDHCI_QUIRK_NO_MULTIBLOCK;+/* write_protect can't be routed to controller, use gpio */+sdhci_esdhc_ops.get_ro=esdhc_pltfm_get_ro;+}++if(boarddata){+err=gpio_request_one(boarddata->wp_gpio,GPIOF_IN,"ESDHC_WP");+if(err){+dev_warn(mmc_dev(host->mmc),"can't get wp_pin!\n");+boarddata->wp_gpio=err;+}+}return0;}
@@ -126,20 +160,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdstaticvoidesdhc_pltfm_exit(structsdhci_host*host){structsdhci_pltfm_host*pltfm_host=sdhci_priv(host);+structesdhc_platform_data*boarddata=host->mmc->parent->platform_data;++if(boarddata&&gpio_is_valid(boarddata->wp_gpio))+gpio_free(boarddata->wp_gpio);clk_disable(pltfm_host->clk);clk_put(pltfm_host->clk);}-staticstructsdhci_opssdhci_esdhc_ops={-.read_w=esdhc_readw_le,-.write_w=esdhc_writew_le,-.write_b=esdhc_writeb_le,-.set_clock=esdhc_set_clock,-.get_max_clock=esdhc_pltfm_get_max_clock,-.get_min_clock=esdhc_pltfm_get_min_clock,-};-structsdhci_pltfm_datasdhci_esdhc_imx_pdata={.quirks=ESDHC_DEFAULT_QUIRKS|SDHCI_QUIRK_BROKEN_ADMA,/* ADMA has issues. Might be fixable */
From: Marc Reilly <hidden> Date: 2011-02-10 22:24:38
Hi Wolfram,
First three patches work well on my vpr200 board (mx35).
One comment inline...
I ran some tests of insert/remove card with the card locked and unlocked, and
trying to append a file. It behaved as expected, thus:
Tested-by: Marc Reilly <redacted>
@@ -116,9 +139,20 @@ static int esdhc_pltfm_init(struct sdhci_host *host,
struct sdhci_pltfm_data *pd if (cpu_is_mx35() || cpu_is_mx51())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
- /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
- if (cpu_is_mx25() || cpu_is_mx35())
+ if (cpu_is_mx25() || cpu_is_mx35()) {
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* write_protect can't be routed to controller, use gpio */
+ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ }
+
+ if (boarddata) {
Perhaps (boarddata && gpio_is_valid(boarddata->wp_gpio) as above?
For example what if someone sets up the boarddata for a card detect, but not
write protect.
From: Wolfram Sang <hidden> Date: 2011-02-11 09:42:48
Marc,
On Fri, Feb 11, 2011 at 09:24:38AM +1100, Marc Reilly wrote:
Tested-by: Marc Reilly <redacted>
Thanks a lot!
quoted
+ if (boarddata) {
Perhaps (boarddata && gpio_is_valid(boarddata->wp_gpio) as above?
For example what if someone sets up the boarddata for a card detect, but not
write protect.
Well, I couldn't do this here, because later the cd_pin-stuff will also
be added to the if-block. However, I see what you mean and that could
still be added before the gpio_request below. That would add another
level of indentation, though, for a case I'd consider to be more
theoretical (and definately not recommended). Maybe I will adjust the
warning message to be also understandable for the case a GPIO is preset
with an invalid number. I think the warning itself is justified.
From: Wolfram Sang <hidden> Date: 2011-02-10 19:14:48
It can be worked around using a GPIO which will be done for i.MX later.
Signed-off-by: Wolfram Sang <redacted>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++-
drivers/mmc/host/sdhci-esdhc.h | 1 -
drivers/mmc/host/sdhci-of-esdhc.c | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
@@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)}structsdhci_of_datasdhci_esdhc={-.quirks=ESDHC_DEFAULT_QUIRKS,+/* card detection could be handled via GPIO */+.quirks=ESDHC_DEFAULT_QUIRKS|SDHCI_QUIRK_BROKEN_CARD_DETECTION,.ops={.read_l=sdhci_be32bs_readl,.read_w=esdhc_readw,
From: Wolfram Sang <hidden> Date: 2011-02-10 19:18:21
Adding Anton to Cc...
On Thu, Feb 10, 2011 at 08:14:48PM +0100, Wolfram Sang wrote:
quoted hunk
It can be worked around using a GPIO which will be done for i.MX later.
Signed-off-by: Wolfram Sang <redacted>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++-
drivers/mmc/host/sdhci-esdhc.h | 1 -
drivers/mmc/host/sdhci-of-esdhc.c | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
@@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)}structsdhci_of_datasdhci_esdhc={-.quirks=ESDHC_DEFAULT_QUIRKS,+/* card detection could be handled via GPIO */+.quirks=ESDHC_DEFAULT_QUIRKS|SDHCI_QUIRK_BROKEN_CARD_DETECTION,.ops={.read_l=sdhci_be32bs_readl,.read_w=esdhc_readw,
Minor nit: "|" should be on the previous line.
Otherwise,
Acked-by: Anton Vorontsov <redacted>
Thanks!
--
Anton Vorontsov
Email: cbouatmailru at gmail.com
@@ -32,6 +32,39 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, iwritel(((readl(base)&~(mask<<shift))|(val<<shift)),base);}+staticu32esdhc_readl_le(structsdhci_host*host,intreg)+{+/* fake CARD_PRESENT flag on mx25/35 */+u32val=readl(host->ioaddr+reg);++if(unlikely(reg==SDHCI_PRESENT_STATE)){+structesdhc_platform_data*boarddata=+host->mmc->parent->platform_data;++if(boarddata&&gpio_is_valid(boarddata->cd_gpio)+&&gpio_get_value(boarddata->cd_gpio))+/* no card, if a valid gpio says so... */+val&=SDHCI_CARD_PRESENT;+else+/* ... in all other cases assume card is present */+val|=SDHCI_CARD_PRESENT;+}++returnval;+}++staticvoidesdhc_writel_le(structsdhci_host*host,u32val,intreg)+{+if(unlikely(reg==SDHCI_INT_ENABLE))+/*+*theseinterruptswon'tworkwithacustomcard_detectgpio+*(onlyappliedtomx25/35)+*/+val&=~(SDHCI_INT_CARD_REMOVE|SDHCI_INT_CARD_INSERT);++writel(val,host->ioaddr+reg);+}+staticu16esdhc_readw_le(structsdhci_host*host,intreg){if(unlikely(reg==SDHCI_HOST_VERSION))
@@ -142,6 +183,8 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdif(cpu_is_mx25()||cpu_is_mx35()){/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */host->quirks|=SDHCI_QUIRK_NO_MULTIBLOCK;+/* card_detect can't be routed to controller, mark broken */+host->quirks|=SDHCI_QUIRK_BROKEN_CARD_DETECTION;/* write_protect can't be routed to controller, use gpio */sdhci_esdhc_ops.get_ro=esdhc_pltfm_get_ro;}
@@ -152,9 +195,34 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pddev_warn(mmc_dev(host->mmc),"can't get wp_pin!\n");boarddata->wp_gpio=err;}++err=gpio_request_one(boarddata->cd_gpio,GPIOF_IN,"ESDHC_CD");+if(err){+dev_warn(mmc_dev(host->mmc),"can't get cd_pin!\n");+gotono_card_detect_pin;+}++err=request_irq(gpio_to_irq(boarddata->cd_gpio),cd_irq,+IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,+mmc_hostname(host->mmc),host);+if(err){+dev_warn(mmc_dev(host->mmc),"request irq error\n");+gotono_card_detect_irq;+}++sdhci_esdhc_ops.write_l=esdhc_writel_le;+sdhci_esdhc_ops.read_l=esdhc_readl_le;+/* Now we have a working card_detect again */+host->quirks&=~SDHCI_QUIRK_BROKEN_CARD_DETECTION;}return0;++no_card_detect_irq:+gpio_free(boarddata->cd_gpio);+no_card_detect_pin:+boarddata->cd_gpio=err;+return0;}staticvoidesdhc_pltfm_exit(structsdhci_host*host)
From: Wolfram Sang <hidden> Date: 2011-02-10 19:14:51
The latter are error-prone because the bank number is one less than one
would read in the documentation.
Signed-off-by: Wolfram Sang <redacted>
Cc: Eric B?nard <redacted>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c | 4 ++--
arch/arm/mach-mx3/mach-cpuimx35.c | 2 +-
arch/arm/mach-mx3/mach-pcm043.c | 10 +++++-----
3 files changed, 8 insertions(+), 8 deletions(-)