aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorWolfram Sang <w.sang@pengutronix.de>2011-02-26 08:44:39 -0500
committerChris Ball <cjb@laptop.org>2011-03-17 15:35:00 -0400
commit0c6d49ce53bc18c0ac637fb137f1e01ee9082201 (patch)
treedd7228fc94fbf638e57ec31352805eb0b2bde95a /drivers/mmc
parentdffc55adfa2676a02a838d56a0cc4edd3809510c (diff)
mmc: sdhci-esdhc-imx: add write protect on custom GPIO on mx25/35
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Tested-by: Marc Reilly <marc@cpdesign.com.au> Tested-by: Eric Benard <eric@eukrea.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9b82910b9db..65df00bb00d 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -15,9 +15,11 @@
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/clk.h> 17#include <linux/clk.h>
18#include <linux/gpio.h>
18#include <linux/mmc/host.h> 19#include <linux/mmc/host.h>
19#include <linux/mmc/sdhci-pltfm.h> 20#include <linux/mmc/sdhci-pltfm.h>
20#include <mach/hardware.h> 21#include <mach/hardware.h>
22#include <mach/esdhc.h>
21#include "sdhci.h" 23#include "sdhci.h"
22#include "sdhci-pltfm.h" 24#include "sdhci-pltfm.h"
23#include "sdhci-esdhc.h" 25#include "sdhci-esdhc.h"
@@ -100,10 +102,31 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
100 return clk_get_rate(pltfm_host->clk) / 256 / 16; 102 return clk_get_rate(pltfm_host->clk) / 256 / 16;
101} 103}
102 104
105static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
106{
107 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
108
109 if (boarddata && gpio_is_valid(boarddata->wp_gpio))
110 return gpio_get_value(boarddata->wp_gpio);
111 else
112 return -ENOSYS;
113}
114
115static struct sdhci_ops sdhci_esdhc_ops = {
116 .read_w = esdhc_readw_le,
117 .write_w = esdhc_writew_le,
118 .write_b = esdhc_writeb_le,
119 .set_clock = esdhc_set_clock,
120 .get_max_clock = esdhc_pltfm_get_max_clock,
121 .get_min_clock = esdhc_pltfm_get_min_clock,
122};
123
103static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata) 124static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
104{ 125{
105 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 126 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
127 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
106 struct clk *clk; 128 struct clk *clk;
129 int err;
107 130
108 clk = clk_get(mmc_dev(host->mmc), NULL); 131 clk = clk_get(mmc_dev(host->mmc), NULL);
109 if (IS_ERR(clk)) { 132 if (IS_ERR(clk)) {
@@ -116,9 +139,21 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
116 if (cpu_is_mx35() || cpu_is_mx51()) 139 if (cpu_is_mx35() || cpu_is_mx51())
117 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 140 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
118 141
119 /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */ 142 if (cpu_is_mx25() || cpu_is_mx35()) {
120 if (cpu_is_mx25() || cpu_is_mx35()) 143 /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
121 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; 144 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
145 /* write_protect can't be routed to controller, use gpio */
146 sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
147 }
148
149 if (boarddata) {
150 err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
151 if (err) {
152 dev_warn(mmc_dev(host->mmc),
153 "no write-protect pin available!\n");
154 boarddata->wp_gpio = err;
155 }
156 }
122 157
123 return 0; 158 return 0;
124} 159}
@@ -126,20 +161,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
126static void esdhc_pltfm_exit(struct sdhci_host *host) 161static void esdhc_pltfm_exit(struct sdhci_host *host)
127{ 162{
128 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 163 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
164 struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
165
166 if (boarddata && gpio_is_valid(boarddata->wp_gpio))
167 gpio_free(boarddata->wp_gpio);
129 168
130 clk_disable(pltfm_host->clk); 169 clk_disable(pltfm_host->clk);
131 clk_put(pltfm_host->clk); 170 clk_put(pltfm_host->clk);
132} 171}
133 172
134static struct sdhci_ops sdhci_esdhc_ops = {
135 .read_w = esdhc_readw_le,
136 .write_w = esdhc_writew_le,
137 .write_b = esdhc_writeb_le,
138 .set_clock = esdhc_set_clock,
139 .get_max_clock = esdhc_pltfm_get_max_clock,
140 .get_min_clock = esdhc_pltfm_get_min_clock,
141};
142
143struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { 173struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
144 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA, 174 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
145 /* ADMA has issues. Might be fixable */ 175 /* ADMA has issues. Might be fixable */