1 /* 2 * Secure Digital Host Controller Interface ACPI driver. 3 * 4 * Copyright (c) 2012, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 */ 20 21 #include <linux/init.h> 22 #include <linux/export.h> 23 #include <linux/module.h> 24 #include <linux/device.h> 25 #include <linux/platform_device.h> 26 #include <linux/ioport.h> 27 #include <linux/io.h> 28 #include <linux/dma-mapping.h> 29 #include <linux/compiler.h> 30 #include <linux/stddef.h> 31 #include <linux/bitops.h> 32 #include <linux/types.h> 33 #include <linux/err.h> 34 #include <linux/interrupt.h> 35 #include <linux/acpi.h> 36 #include <linux/pm.h> 37 #include <linux/pm_runtime.h> 38 39 #include <linux/mmc/host.h> 40 #include <linux/mmc/pm.h> 41 #include <linux/mmc/sdhci.h> 42 43 #include "sdhci.h" 44 45 enum { 46 SDHCI_ACPI_SD_CD = BIT(0), 47 SDHCI_ACPI_RUNTIME_PM = BIT(1), 48 }; 49 50 struct sdhci_acpi_chip { 51 const struct sdhci_ops *ops; 52 unsigned int quirks; 53 unsigned int quirks2; 54 unsigned long caps; 55 unsigned int caps2; 56 mmc_pm_flag_t pm_caps; 57 }; 58 59 struct sdhci_acpi_slot { 60 const struct sdhci_acpi_chip *chip; 61 unsigned int quirks; 62 unsigned int quirks2; 63 unsigned long caps; 64 unsigned int caps2; 65 mmc_pm_flag_t pm_caps; 66 unsigned int flags; 67 }; 68 69 struct sdhci_acpi_host { 70 struct sdhci_host *host; 71 const struct sdhci_acpi_slot *slot; 72 struct platform_device *pdev; 73 bool use_runtime_pm; 74 }; 75 76 static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) 77 { 78 return c->slot && (c->slot->flags & flag); 79 } 80 81 static int sdhci_acpi_enable_dma(struct sdhci_host *host) 82 { 83 return 0; 84 } 85 86 static const struct sdhci_ops sdhci_acpi_ops_dflt = { 87 .enable_dma = sdhci_acpi_enable_dma, 88 }; 89 90 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { 91 .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, 92 .caps2 = MMC_CAP2_HC_ERASE_SZ, 93 .flags = SDHCI_ACPI_RUNTIME_PM, 94 }; 95 96 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { 97 .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, 98 .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD, 99 .flags = SDHCI_ACPI_RUNTIME_PM, 100 .pm_caps = MMC_PM_KEEP_POWER, 101 }; 102 103 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { 104 }; 105 106 struct sdhci_acpi_uid_slot { 107 const char *hid; 108 const char *uid; 109 const struct sdhci_acpi_slot *slot; 110 }; 111 112 static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { 113 { "80860F14" , "1" , &sdhci_acpi_slot_int_emmc }, 114 { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, 115 { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, 116 { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, 117 { "PNP0D40" }, 118 { }, 119 }; 120 121 static const struct acpi_device_id sdhci_acpi_ids[] = { 122 { "80860F14" }, 123 { "INT33BB" }, 124 { "INT33C6" }, 125 { "PNP0D40" }, 126 { }, 127 }; 128 MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); 129 130 static const struct sdhci_acpi_slot *sdhci_acpi_get_slot_by_ids(const char *hid, 131 const char *uid) 132 { 133 const struct sdhci_acpi_uid_slot *u; 134 135 for (u = sdhci_acpi_uids; u->hid; u++) { 136 if (strcmp(u->hid, hid)) 137 continue; 138 if (!u->uid) 139 return u->slot; 140 if (uid && !strcmp(u->uid, uid)) 141 return u->slot; 142 } 143 return NULL; 144 } 145 146 static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, 147 const char *hid) 148 { 149 const struct sdhci_acpi_slot *slot; 150 struct acpi_device_info *info; 151 const char *uid = NULL; 152 acpi_status status; 153 154 status = acpi_get_object_info(handle, &info); 155 if (!ACPI_FAILURE(status) && (info->valid & ACPI_VALID_UID)) 156 uid = info->unique_id.string; 157 158 slot = sdhci_acpi_get_slot_by_ids(hid, uid); 159 160 kfree(info); 161 return slot; 162 } 163 164 static int sdhci_acpi_probe(struct platform_device *pdev) 165 { 166 struct device *dev = &pdev->dev; 167 acpi_handle handle = ACPI_HANDLE(dev); 168 struct acpi_device *device; 169 struct sdhci_acpi_host *c; 170 struct sdhci_host *host; 171 struct resource *iomem; 172 resource_size_t len; 173 const char *hid; 174 int err; 175 176 if (acpi_bus_get_device(handle, &device)) 177 return -ENODEV; 178 179 if (acpi_bus_get_status(device) || !device->status.present) 180 return -ENODEV; 181 182 hid = acpi_device_hid(device); 183 184 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 185 if (!iomem) 186 return -ENOMEM; 187 188 len = resource_size(iomem); 189 if (len < 0x100) 190 dev_err(dev, "Invalid iomem size!\n"); 191 192 if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) 193 return -ENOMEM; 194 195 host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); 196 if (IS_ERR(host)) 197 return PTR_ERR(host); 198 199 c = sdhci_priv(host); 200 c->host = host; 201 c->slot = sdhci_acpi_get_slot(handle, hid); 202 c->pdev = pdev; 203 c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); 204 205 platform_set_drvdata(pdev, c); 206 207 host->hw_name = "ACPI"; 208 host->ops = &sdhci_acpi_ops_dflt; 209 host->irq = platform_get_irq(pdev, 0); 210 211 host->ioaddr = devm_ioremap_nocache(dev, iomem->start, 212 resource_size(iomem)); 213 if (host->ioaddr == NULL) { 214 err = -ENOMEM; 215 goto err_free; 216 } 217 218 if (!dev->dma_mask) { 219 u64 dma_mask; 220 221 if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) { 222 /* 64-bit DMA is not supported at present */ 223 dma_mask = DMA_BIT_MASK(32); 224 } else { 225 dma_mask = DMA_BIT_MASK(32); 226 } 227 228 dev->dma_mask = &dev->coherent_dma_mask; 229 dev->coherent_dma_mask = dma_mask; 230 } 231 232 if (c->slot) { 233 if (c->slot->chip) { 234 host->ops = c->slot->chip->ops; 235 host->quirks |= c->slot->chip->quirks; 236 host->quirks2 |= c->slot->chip->quirks2; 237 host->mmc->caps |= c->slot->chip->caps; 238 host->mmc->caps2 |= c->slot->chip->caps2; 239 host->mmc->pm_caps |= c->slot->chip->pm_caps; 240 } 241 host->quirks |= c->slot->quirks; 242 host->quirks2 |= c->slot->quirks2; 243 host->mmc->caps |= c->slot->caps; 244 host->mmc->caps2 |= c->slot->caps2; 245 host->mmc->pm_caps |= c->slot->pm_caps; 246 } 247 248 host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; 249 250 err = sdhci_add_host(host); 251 if (err) 252 goto err_free; 253 254 if (c->use_runtime_pm) { 255 pm_runtime_set_active(dev); 256 pm_suspend_ignore_children(dev, 1); 257 pm_runtime_set_autosuspend_delay(dev, 50); 258 pm_runtime_use_autosuspend(dev); 259 pm_runtime_enable(dev); 260 } 261 262 return 0; 263 264 err_free: 265 platform_set_drvdata(pdev, NULL); 266 sdhci_free_host(c->host); 267 return err; 268 } 269 270 static int sdhci_acpi_remove(struct platform_device *pdev) 271 { 272 struct sdhci_acpi_host *c = platform_get_drvdata(pdev); 273 struct device *dev = &pdev->dev; 274 int dead; 275 276 if (c->use_runtime_pm) { 277 pm_runtime_get_sync(dev); 278 pm_runtime_disable(dev); 279 pm_runtime_put_noidle(dev); 280 } 281 282 dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); 283 sdhci_remove_host(c->host, dead); 284 platform_set_drvdata(pdev, NULL); 285 sdhci_free_host(c->host); 286 287 return 0; 288 } 289 290 #ifdef CONFIG_PM_SLEEP 291 292 static int sdhci_acpi_suspend(struct device *dev) 293 { 294 struct sdhci_acpi_host *c = dev_get_drvdata(dev); 295 296 return sdhci_suspend_host(c->host); 297 } 298 299 static int sdhci_acpi_resume(struct device *dev) 300 { 301 struct sdhci_acpi_host *c = dev_get_drvdata(dev); 302 303 return sdhci_resume_host(c->host); 304 } 305 306 #else 307 308 #define sdhci_acpi_suspend NULL 309 #define sdhci_acpi_resume NULL 310 311 #endif 312 313 #ifdef CONFIG_PM_RUNTIME 314 315 static int sdhci_acpi_runtime_suspend(struct device *dev) 316 { 317 struct sdhci_acpi_host *c = dev_get_drvdata(dev); 318 319 return sdhci_runtime_suspend_host(c->host); 320 } 321 322 static int sdhci_acpi_runtime_resume(struct device *dev) 323 { 324 struct sdhci_acpi_host *c = dev_get_drvdata(dev); 325 326 return sdhci_runtime_resume_host(c->host); 327 } 328 329 static int sdhci_acpi_runtime_idle(struct device *dev) 330 { 331 return 0; 332 } 333 334 #else 335 336 #define sdhci_acpi_runtime_suspend NULL 337 #define sdhci_acpi_runtime_resume NULL 338 #define sdhci_acpi_runtime_idle NULL 339 340 #endif 341 342 static const struct dev_pm_ops sdhci_acpi_pm_ops = { 343 .suspend = sdhci_acpi_suspend, 344 .resume = sdhci_acpi_resume, 345 .runtime_suspend = sdhci_acpi_runtime_suspend, 346 .runtime_resume = sdhci_acpi_runtime_resume, 347 .runtime_idle = sdhci_acpi_runtime_idle, 348 }; 349 350 static struct platform_driver sdhci_acpi_driver = { 351 .driver = { 352 .name = "sdhci-acpi", 353 .owner = THIS_MODULE, 354 .acpi_match_table = sdhci_acpi_ids, 355 .pm = &sdhci_acpi_pm_ops, 356 }, 357 .probe = sdhci_acpi_probe, 358 .remove = sdhci_acpi_remove, 359 }; 360 361 module_platform_driver(sdhci_acpi_driver); 362 363 MODULE_DESCRIPTION("Secure Digital Host Controller Interface ACPI driver"); 364 MODULE_AUTHOR("Adrian Hunter"); 365 MODULE_LICENSE("GPL v2"); 366