diff options
-rw-r--r-- | drivers/mmc/host/sdhci-spear.c | 79 |
1 files changed, 17 insertions, 62 deletions
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 676df4623057..0316dec3f006 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
29 | #include <linux/mmc/sdhci-spear.h> | 29 | #include <linux/mmc/sdhci-spear.h> |
30 | #include <linux/mmc/slot-gpio.h> | ||
30 | #include <linux/io.h> | 31 | #include <linux/io.h> |
31 | #include "sdhci.h" | 32 | #include "sdhci.h" |
32 | 33 | ||
@@ -40,28 +41,6 @@ static const struct sdhci_ops sdhci_pltfm_ops = { | |||
40 | /* Nothing to do for now. */ | 41 | /* Nothing to do for now. */ |
41 | }; | 42 | }; |
42 | 43 | ||
43 | /* gpio card detection interrupt handler */ | ||
44 | static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id) | ||
45 | { | ||
46 | struct platform_device *pdev = dev_id; | ||
47 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
48 | struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); | ||
49 | unsigned long gpio_irq_type; | ||
50 | int val; | ||
51 | |||
52 | val = gpio_get_value(sdhci->data->card_int_gpio); | ||
53 | |||
54 | /* val == 1 -> card removed, val == 0 -> card inserted */ | ||
55 | /* if card removed - set irq for low level, else vice versa */ | ||
56 | gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH; | ||
57 | irq_set_irq_type(irq, gpio_irq_type); | ||
58 | |||
59 | /* inform sdhci driver about card insertion/removal */ | ||
60 | tasklet_schedule(&host->card_tasklet); | ||
61 | |||
62 | return IRQ_HANDLED; | ||
63 | } | ||
64 | |||
65 | #ifdef CONFIG_OF | 44 | #ifdef CONFIG_OF |
66 | static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) | 45 | static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) |
67 | { | 46 | { |
@@ -152,6 +131,22 @@ static int sdhci_probe(struct platform_device *pdev) | |||
152 | sdhci->data = dev_get_platdata(&pdev->dev); | 131 | sdhci->data = dev_get_platdata(&pdev->dev); |
153 | } | 132 | } |
154 | 133 | ||
134 | /* | ||
135 | * It is optional to use GPIOs for sdhci card detection. If | ||
136 | * sdhci->data is NULL, then use original sdhci lines otherwise | ||
137 | * GPIO lines. We use the built-in GPIO support for this. | ||
138 | */ | ||
139 | if (sdhci->data && sdhci->data->card_int_gpio >= 0) { | ||
140 | ret = mmc_gpio_request_cd(host->mmc, | ||
141 | sdhci->data->card_int_gpio, 0); | ||
142 | if (ret < 0) { | ||
143 | dev_dbg(&pdev->dev, | ||
144 | "failed to request card-detect gpio%d\n", | ||
145 | sdhci->data->card_int_gpio); | ||
146 | goto disable_clk; | ||
147 | } | ||
148 | } | ||
149 | |||
155 | ret = sdhci_add_host(host); | 150 | ret = sdhci_add_host(host); |
156 | if (ret) { | 151 | if (ret) { |
157 | dev_dbg(&pdev->dev, "error adding host\n"); | 152 | dev_dbg(&pdev->dev, "error adding host\n"); |
@@ -160,48 +155,8 @@ static int sdhci_probe(struct platform_device *pdev) | |||
160 | 155 | ||
161 | platform_set_drvdata(pdev, host); | 156 | platform_set_drvdata(pdev, host); |
162 | 157 | ||
163 | /* | ||
164 | * It is optional to use GPIOs for sdhci Power control & sdhci card | ||
165 | * interrupt detection. If sdhci->data is NULL, then use original sdhci | ||
166 | * lines otherwise GPIO lines. | ||
167 | * If GPIO is selected for power control, then power should be disabled | ||
168 | * after card removal and should be enabled when card insertion | ||
169 | * interrupt occurs | ||
170 | */ | ||
171 | if (!sdhci->data) | ||
172 | return 0; | ||
173 | |||
174 | if (sdhci->data->card_int_gpio >= 0) { | ||
175 | ret = devm_gpio_request(&pdev->dev, sdhci->data->card_int_gpio, | ||
176 | "sdhci"); | ||
177 | if (ret < 0) { | ||
178 | dev_dbg(&pdev->dev, "gpio request fail: %d\n", | ||
179 | sdhci->data->card_int_gpio); | ||
180 | goto set_drvdata; | ||
181 | } | ||
182 | |||
183 | ret = gpio_direction_input(sdhci->data->card_int_gpio); | ||
184 | if (ret) { | ||
185 | dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", | ||
186 | sdhci->data->card_int_gpio); | ||
187 | goto set_drvdata; | ||
188 | } | ||
189 | ret = devm_request_irq(&pdev->dev, | ||
190 | gpio_to_irq(sdhci->data->card_int_gpio), | ||
191 | sdhci_gpio_irq, IRQF_TRIGGER_LOW, | ||
192 | mmc_hostname(host->mmc), pdev); | ||
193 | if (ret) { | ||
194 | dev_dbg(&pdev->dev, "gpio request irq fail: %d\n", | ||
195 | sdhci->data->card_int_gpio); | ||
196 | goto set_drvdata; | ||
197 | } | ||
198 | |||
199 | } | ||
200 | |||
201 | return 0; | 158 | return 0; |
202 | 159 | ||
203 | set_drvdata: | ||
204 | sdhci_remove_host(host, 1); | ||
205 | disable_clk: | 160 | disable_clk: |
206 | clk_disable_unprepare(sdhci->clk); | 161 | clk_disable_unprepare(sdhci->clk); |
207 | err_host: | 162 | err_host: |