diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2011-12-27 08:48:44 -0500 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-01-11 23:58:47 -0500 |
commit | c5e027a4a19d6267e36107fc32b5a4f3cd27976a (patch) | |
tree | 73f3d6c4e2e7efe957858e857a07ace69f558764 /drivers/mmc | |
parent | 52c506f0bc72530fb786838e7ffd4f158a2e5c3a (diff) |
mmc: sdhci-pci: get gpio numbers from platform data
Retrieve the GPIO numbers for hardware reset and
card detect from platform data.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 109 |
1 files changed, 41 insertions, 68 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 4e8f324e2c84..646680a5993a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/sfi.h> | ||
27 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
28 | #include <linux/mmc/sdhci-pci-data.h> | 27 | #include <linux/mmc/sdhci-pci-data.h> |
29 | 28 | ||
@@ -173,32 +172,9 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip) | |||
173 | return 0; | 172 | return 0; |
174 | } | 173 | } |
175 | 174 | ||
176 | /* Medfield eMMC hardware reset GPIOs */ | ||
177 | static int mfd_emmc0_rst_gpio = -EINVAL; | ||
178 | static int mfd_emmc1_rst_gpio = -EINVAL; | ||
179 | |||
180 | static int mfd_emmc_gpio_parse(struct sfi_table_header *table) | ||
181 | { | ||
182 | struct sfi_table_simple *sb = (struct sfi_table_simple *)table; | ||
183 | struct sfi_gpio_table_entry *entry; | ||
184 | int i, num; | ||
185 | |||
186 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
187 | entry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
188 | |||
189 | for (i = 0; i < num; i++, entry++) { | ||
190 | if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN)) | ||
191 | mfd_emmc0_rst_gpio = entry->pin_no; | ||
192 | else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN)) | ||
193 | mfd_emmc1_rst_gpio = entry->pin_no; | ||
194 | } | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | #ifdef CONFIG_PM_RUNTIME | 175 | #ifdef CONFIG_PM_RUNTIME |
200 | 176 | ||
201 | static irqreturn_t mfd_sd_cd(int irq, void *dev_id) | 177 | static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id) |
202 | { | 178 | { |
203 | struct sdhci_pci_slot *slot = dev_id; | 179 | struct sdhci_pci_slot *slot = dev_id; |
204 | struct sdhci_host *host = slot->host; | 180 | struct sdhci_host *host = slot->host; |
@@ -207,15 +183,16 @@ static irqreturn_t mfd_sd_cd(int irq, void *dev_id) | |||
207 | return IRQ_HANDLED; | 183 | return IRQ_HANDLED; |
208 | } | 184 | } |
209 | 185 | ||
210 | #define MFLD_SD_CD_PIN 69 | 186 | static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot) |
211 | |||
212 | static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) | ||
213 | { | 187 | { |
214 | int err, irq, gpio = MFLD_SD_CD_PIN; | 188 | int err, irq, gpio = slot->cd_gpio; |
215 | 189 | ||
216 | slot->cd_gpio = -EINVAL; | 190 | slot->cd_gpio = -EINVAL; |
217 | slot->cd_irq = -EINVAL; | 191 | slot->cd_irq = -EINVAL; |
218 | 192 | ||
193 | if (!gpio_is_valid(gpio)) | ||
194 | return; | ||
195 | |||
219 | err = gpio_request(gpio, "sd_cd"); | 196 | err = gpio_request(gpio, "sd_cd"); |
220 | if (err < 0) | 197 | if (err < 0) |
221 | goto out; | 198 | goto out; |
@@ -228,7 +205,7 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) | |||
228 | if (irq < 0) | 205 | if (irq < 0) |
229 | goto out_free; | 206 | goto out_free; |
230 | 207 | ||
231 | err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING | | 208 | err = request_irq(irq, sdhci_pci_sd_cd, IRQF_TRIGGER_RISING | |
232 | IRQF_TRIGGER_FALLING, "sd_cd", slot); | 209 | IRQF_TRIGGER_FALLING, "sd_cd", slot); |
233 | if (err) | 210 | if (err) |
234 | goto out_free; | 211 | goto out_free; |
@@ -237,65 +214,41 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) | |||
237 | slot->cd_irq = irq; | 214 | slot->cd_irq = irq; |
238 | slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION; | 215 | slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION; |
239 | 216 | ||
240 | return 0; | 217 | return; |
241 | 218 | ||
242 | out_free: | 219 | out_free: |
243 | gpio_free(gpio); | 220 | gpio_free(gpio); |
244 | out: | 221 | out: |
245 | dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n"); | 222 | dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n"); |
246 | return 0; | ||
247 | } | 223 | } |
248 | 224 | ||
249 | static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead) | 225 | static void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot) |
250 | { | 226 | { |
251 | if (slot->cd_irq >= 0) | 227 | if (slot->cd_irq >= 0) |
252 | free_irq(slot->cd_irq, slot); | 228 | free_irq(slot->cd_irq, slot); |
253 | gpio_free(slot->cd_gpio); | 229 | if (gpio_is_valid(slot->cd_gpio)) |
230 | gpio_free(slot->cd_gpio); | ||
254 | } | 231 | } |
255 | 232 | ||
256 | #else | 233 | #else |
257 | 234 | ||
258 | #define mfd_sd_probe_slot NULL | 235 | static inline void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot) |
259 | #define mfd_sd_remove_slot NULL | 236 | { |
237 | } | ||
238 | |||
239 | static inline void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot) | ||
240 | { | ||
241 | } | ||
260 | 242 | ||
261 | #endif | 243 | #endif |
262 | 244 | ||
263 | static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) | 245 | static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) |
264 | { | 246 | { |
265 | const char *name = NULL; | ||
266 | int gpio = -EINVAL; | ||
267 | |||
268 | sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse); | ||
269 | |||
270 | switch (slot->chip->pdev->device) { | ||
271 | case PCI_DEVICE_ID_INTEL_MFD_EMMC0: | ||
272 | gpio = mfd_emmc0_rst_gpio; | ||
273 | name = "eMMC0_reset"; | ||
274 | break; | ||
275 | case PCI_DEVICE_ID_INTEL_MFD_EMMC1: | ||
276 | gpio = mfd_emmc1_rst_gpio; | ||
277 | name = "eMMC1_reset"; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | if (!gpio_request(gpio, name)) { | ||
282 | gpio_direction_output(gpio, 1); | ||
283 | slot->rst_n_gpio = gpio; | ||
284 | slot->host->mmc->caps |= MMC_CAP_HW_RESET; | ||
285 | } | ||
286 | |||
287 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; | 247 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; |
288 | |||
289 | slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC; | 248 | slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC; |
290 | |||
291 | return 0; | 249 | return 0; |
292 | } | 250 | } |
293 | 251 | ||
294 | static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead) | ||
295 | { | ||
296 | gpio_free(slot->rst_n_gpio); | ||
297 | } | ||
298 | |||
299 | static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = { | 252 | static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = { |
300 | .quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT, | 253 | .quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT, |
301 | .probe_slot = mrst_hc_probe_slot, | 254 | .probe_slot = mrst_hc_probe_slot, |
@@ -309,8 +262,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = { | |||
309 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { | 262 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { |
310 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 263 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
311 | .allow_runtime_pm = true, | 264 | .allow_runtime_pm = true, |
312 | .probe_slot = mfd_sd_probe_slot, | ||
313 | .remove_slot = mfd_sd_remove_slot, | ||
314 | }; | 265 | }; |
315 | 266 | ||
316 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { | 267 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { |
@@ -322,7 +273,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = { | |||
322 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 273 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
323 | .allow_runtime_pm = true, | 274 | .allow_runtime_pm = true, |
324 | .probe_slot = mfd_emmc_probe_slot, | 275 | .probe_slot = mfd_emmc_probe_slot, |
325 | .remove_slot = mfd_emmc_remove_slot, | ||
326 | }; | 276 | }; |
327 | 277 | ||
328 | /* O2Micro extra registers */ | 278 | /* O2Micro extra registers */ |
@@ -1229,6 +1179,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
1229 | slot->host = host; | 1179 | slot->host = host; |
1230 | slot->pci_bar = bar; | 1180 | slot->pci_bar = bar; |
1231 | slot->rst_n_gpio = -EINVAL; | 1181 | slot->rst_n_gpio = -EINVAL; |
1182 | slot->cd_gpio = -EINVAL; | ||
1232 | 1183 | ||
1233 | /* Retrieve platform data if there is any */ | 1184 | /* Retrieve platform data if there is any */ |
1234 | if (*sdhci_pci_get_data) | 1185 | if (*sdhci_pci_get_data) |
@@ -1242,6 +1193,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
1242 | goto free; | 1193 | goto free; |
1243 | } | 1194 | } |
1244 | } | 1195 | } |
1196 | slot->rst_n_gpio = slot->data->rst_n_gpio; | ||
1197 | slot->cd_gpio = slot->data->cd_gpio; | ||
1245 | } | 1198 | } |
1246 | 1199 | ||
1247 | host->hw_name = "PCI"; | 1200 | host->hw_name = "PCI"; |
@@ -1269,15 +1222,30 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
1269 | goto unmap; | 1222 | goto unmap; |
1270 | } | 1223 | } |
1271 | 1224 | ||
1225 | if (gpio_is_valid(slot->rst_n_gpio)) { | ||
1226 | if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { | ||
1227 | gpio_direction_output(slot->rst_n_gpio, 1); | ||
1228 | slot->host->mmc->caps |= MMC_CAP_HW_RESET; | ||
1229 | } else { | ||
1230 | dev_warn(&pdev->dev, "failed to request rst_n_gpio\n"); | ||
1231 | slot->rst_n_gpio = -EINVAL; | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1272 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; | 1235 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; |
1273 | 1236 | ||
1274 | ret = sdhci_add_host(host); | 1237 | ret = sdhci_add_host(host); |
1275 | if (ret) | 1238 | if (ret) |
1276 | goto remove; | 1239 | goto remove; |
1277 | 1240 | ||
1241 | sdhci_pci_add_own_cd(slot); | ||
1242 | |||
1278 | return slot; | 1243 | return slot; |
1279 | 1244 | ||
1280 | remove: | 1245 | remove: |
1246 | if (gpio_is_valid(slot->rst_n_gpio)) | ||
1247 | gpio_free(slot->rst_n_gpio); | ||
1248 | |||
1281 | if (chip->fixes && chip->fixes->remove_slot) | 1249 | if (chip->fixes && chip->fixes->remove_slot) |
1282 | chip->fixes->remove_slot(slot, 0); | 1250 | chip->fixes->remove_slot(slot, 0); |
1283 | 1251 | ||
@@ -1302,6 +1270,8 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) | |||
1302 | int dead; | 1270 | int dead; |
1303 | u32 scratch; | 1271 | u32 scratch; |
1304 | 1272 | ||
1273 | sdhci_pci_remove_own_cd(slot); | ||
1274 | |||
1305 | dead = 0; | 1275 | dead = 0; |
1306 | scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); | 1276 | scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); |
1307 | if (scratch == (u32)-1) | 1277 | if (scratch == (u32)-1) |
@@ -1309,6 +1279,9 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) | |||
1309 | 1279 | ||
1310 | sdhci_remove_host(slot->host, dead); | 1280 | sdhci_remove_host(slot->host, dead); |
1311 | 1281 | ||
1282 | if (gpio_is_valid(slot->rst_n_gpio)) | ||
1283 | gpio_free(slot->rst_n_gpio); | ||
1284 | |||
1312 | if (slot->chip->fixes && slot->chip->fixes->remove_slot) | 1285 | if (slot->chip->fixes && slot->chip->fixes->remove_slot) |
1313 | slot->chip->fixes->remove_slot(slot, dead); | 1286 | slot->chip->fixes->remove_slot(slot, dead); |
1314 | 1287 | ||