aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-acpi.c')
-rw-r--r--drivers/mmc/host/sdhci-acpi.c174
1 files changed, 129 insertions, 45 deletions
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 08ae0ff13513..b988997a1e80 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -73,6 +73,7 @@ struct sdhci_acpi_slot {
73 unsigned int caps2; 73 unsigned int caps2;
74 mmc_pm_flag_t pm_caps; 74 mmc_pm_flag_t pm_caps;
75 unsigned int flags; 75 unsigned int flags;
76 size_t priv_size;
76 int (*probe_slot)(struct platform_device *, const char *, const char *); 77 int (*probe_slot)(struct platform_device *, const char *, const char *);
77 int (*remove_slot)(struct platform_device *); 78 int (*remove_slot)(struct platform_device *);
78}; 79};
@@ -82,13 +83,118 @@ struct sdhci_acpi_host {
82 const struct sdhci_acpi_slot *slot; 83 const struct sdhci_acpi_slot *slot;
83 struct platform_device *pdev; 84 struct platform_device *pdev;
84 bool use_runtime_pm; 85 bool use_runtime_pm;
86 unsigned long private[0] ____cacheline_aligned;
85}; 87};
86 88
89static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
90{
91 return (void *)c->private;
92}
93
87static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) 94static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
88{ 95{
89 return c->slot && (c->slot->flags & flag); 96 return c->slot && (c->slot->flags & flag);
90} 97}
91 98
99enum {
100 INTEL_DSM_FNS = 0,
101 INTEL_DSM_V18_SWITCH = 3,
102 INTEL_DSM_V33_SWITCH = 4,
103};
104
105struct intel_host {
106 u32 dsm_fns;
107};
108
109static const guid_t intel_dsm_guid =
110 GUID_INIT(0xF6C13EA5, 0x65CD, 0x461F,
111 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61);
112
113static int __intel_dsm(struct intel_host *intel_host, struct device *dev,
114 unsigned int fn, u32 *result)
115{
116 union acpi_object *obj;
117 int err = 0;
118
119 obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL);
120 if (!obj)
121 return -EOPNOTSUPP;
122
123 if (obj->type == ACPI_TYPE_INTEGER) {
124 *result = obj->integer.value;
125 } else if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length > 0) {
126 size_t len = min_t(size_t, obj->buffer.length, 4);
127
128 *result = 0;
129 memcpy(result, obj->buffer.pointer, len);
130 } else {
131 dev_err(dev, "%s DSM fn %u obj->type %d obj->buffer.length %d\n",
132 __func__, fn, obj->type, obj->buffer.length);
133 err = -EINVAL;
134 }
135
136 ACPI_FREE(obj);
137
138 return err;
139}
140
141static int intel_dsm(struct intel_host *intel_host, struct device *dev,
142 unsigned int fn, u32 *result)
143{
144 if (fn > 31 || !(intel_host->dsm_fns & (1 << fn)))
145 return -EOPNOTSUPP;
146
147 return __intel_dsm(intel_host, dev, fn, result);
148}
149
150static void intel_dsm_init(struct intel_host *intel_host, struct device *dev,
151 struct mmc_host *mmc)
152{
153 int err;
154
155 err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns);
156 if (err) {
157 pr_debug("%s: DSM not supported, error %d\n",
158 mmc_hostname(mmc), err);
159 return;
160 }
161
162 pr_debug("%s: DSM function mask %#x\n",
163 mmc_hostname(mmc), intel_host->dsm_fns);
164}
165
166static int intel_start_signal_voltage_switch(struct mmc_host *mmc,
167 struct mmc_ios *ios)
168{
169 struct device *dev = mmc_dev(mmc);
170 struct sdhci_acpi_host *c = dev_get_drvdata(dev);
171 struct intel_host *intel_host = sdhci_acpi_priv(c);
172 unsigned int fn;
173 u32 result = 0;
174 int err;
175
176 err = sdhci_start_signal_voltage_switch(mmc, ios);
177 if (err)
178 return err;
179
180 switch (ios->signal_voltage) {
181 case MMC_SIGNAL_VOLTAGE_330:
182 fn = INTEL_DSM_V33_SWITCH;
183 break;
184 case MMC_SIGNAL_VOLTAGE_180:
185 fn = INTEL_DSM_V18_SWITCH;
186 break;
187 default:
188 return 0;
189 }
190
191 err = intel_dsm(intel_host, dev, fn, &result);
192 pr_debug("%s: %s DSM fn %u error %d result %u\n",
193 mmc_hostname(mmc), __func__, fn, err, result);
194
195 return 0;
196}
197
92static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) 198static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
93{ 199{
94 u8 reg; 200 u8 reg;
@@ -269,56 +375,26 @@ out:
269 return ret; 375 return ret;
270} 376}
271 377
272static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev, 378static int intel_probe_slot(struct platform_device *pdev, const char *hid,
273 const char *hid, const char *uid) 379 const char *uid)
274{ 380{
275 struct sdhci_acpi_host *c = platform_get_drvdata(pdev); 381 struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
276 struct sdhci_host *host; 382 struct intel_host *intel_host = sdhci_acpi_priv(c);
277 383 struct sdhci_host *host = c->host;
278 if (!c || !c->host)
279 return 0;
280
281 host = c->host;
282
283 /* Platform specific code during emmc probe slot goes here */
284 384
285 if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && 385 if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") &&
286 sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 && 386 sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 &&
287 sdhci_readl(host, SDHCI_CAPABILITIES_1) == 0x00000807) 387 sdhci_readl(host, SDHCI_CAPABILITIES_1) == 0x00000807)
288 host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ 388 host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */
289 389
290 return 0;
291}
292
293static int sdhci_acpi_sdio_probe_slot(struct platform_device *pdev,
294 const char *hid, const char *uid)
295{
296 struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
297
298 if (!c || !c->host)
299 return 0;
300
301 /* Platform specific code during sdio probe slot goes here */
302
303 return 0;
304}
305
306static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev,
307 const char *hid, const char *uid)
308{
309 struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
310 struct sdhci_host *host;
311
312 if (!c || !c->host || !c->slot)
313 return 0;
314
315 host = c->host;
316
317 /* Platform specific code during sd probe slot goes here */
318
319 if (hid && !strcmp(hid, "80865ACA")) 390 if (hid && !strcmp(hid, "80865ACA"))
320 host->mmc_host_ops.get_cd = bxt_get_cd; 391 host->mmc_host_ops.get_cd = bxt_get_cd;
321 392
393 intel_dsm_init(intel_host, &pdev->dev, host->mmc);
394
395 host->mmc_host_ops.start_signal_voltage_switch =
396 intel_start_signal_voltage_switch;
397
322 return 0; 398 return 0;
323} 399}
324 400
@@ -332,7 +408,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
332 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 408 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
333 SDHCI_QUIRK2_STOP_WITH_TC | 409 SDHCI_QUIRK2_STOP_WITH_TC |
334 SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, 410 SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400,
335 .probe_slot = sdhci_acpi_emmc_probe_slot, 411 .probe_slot = intel_probe_slot,
412 .priv_size = sizeof(struct intel_host),
336}; 413};
337 414
338static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { 415static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
@@ -343,7 +420,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
343 MMC_CAP_WAIT_WHILE_BUSY, 420 MMC_CAP_WAIT_WHILE_BUSY,
344 .flags = SDHCI_ACPI_RUNTIME_PM, 421 .flags = SDHCI_ACPI_RUNTIME_PM,
345 .pm_caps = MMC_PM_KEEP_POWER, 422 .pm_caps = MMC_PM_KEEP_POWER,
346 .probe_slot = sdhci_acpi_sdio_probe_slot, 423 .probe_slot = intel_probe_slot,
424 .priv_size = sizeof(struct intel_host),
347}; 425};
348 426
349static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { 427static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
@@ -353,7 +431,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
353 .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | 431 .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
354 SDHCI_QUIRK2_STOP_WITH_TC, 432 SDHCI_QUIRK2_STOP_WITH_TC,
355 .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, 433 .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM,
356 .probe_slot = sdhci_acpi_sd_probe_slot, 434 .probe_slot = intel_probe_slot,
435 .priv_size = sizeof(struct intel_host),
357}; 436};
358 437
359static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = { 438static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = {
@@ -429,11 +508,13 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid,
429static int sdhci_acpi_probe(struct platform_device *pdev) 508static int sdhci_acpi_probe(struct platform_device *pdev)
430{ 509{
431 struct device *dev = &pdev->dev; 510 struct device *dev = &pdev->dev;
511 const struct sdhci_acpi_slot *slot;
432 struct acpi_device *device, *child; 512 struct acpi_device *device, *child;
433 struct sdhci_acpi_host *c; 513 struct sdhci_acpi_host *c;
434 struct sdhci_host *host; 514 struct sdhci_host *host;
435 struct resource *iomem; 515 struct resource *iomem;
436 resource_size_t len; 516 resource_size_t len;
517 size_t priv_size;
437 const char *hid; 518 const char *hid;
438 const char *uid; 519 const char *uid;
439 int err; 520 int err;
@@ -443,7 +524,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
443 return -ENODEV; 524 return -ENODEV;
444 525
445 hid = acpi_device_hid(device); 526 hid = acpi_device_hid(device);
446 uid = device->pnp.unique_id; 527 uid = acpi_device_uid(device);
528
529 slot = sdhci_acpi_get_slot(hid, uid);
447 530
448 /* Power on the SDHCI controller and its children */ 531 /* Power on the SDHCI controller and its children */
449 acpi_device_fix_up_power(device); 532 acpi_device_fix_up_power(device);
@@ -467,13 +550,14 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
467 if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) 550 if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev)))
468 return -ENOMEM; 551 return -ENOMEM;
469 552
470 host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); 553 priv_size = slot ? slot->priv_size : 0;
554 host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host) + priv_size);
471 if (IS_ERR(host)) 555 if (IS_ERR(host))
472 return PTR_ERR(host); 556 return PTR_ERR(host);
473 557
474 c = sdhci_priv(host); 558 c = sdhci_priv(host);
475 c->host = host; 559 c->host = host;
476 c->slot = sdhci_acpi_get_slot(hid, uid); 560 c->slot = slot;
477 c->pdev = pdev; 561 c->pdev = pdev;
478 c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); 562 c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
479 563