Skip to content

Commit c959a6b

Browse files
ahunter6storulf
authored andcommitted
mmc: sdhci-pci: Don't re-tune with runtime pm for some Intel devices
Make use of an Intel ACPI _DSM that indicates if re-tuning is needed after D3. Signed-off-by: Adrian Hunter <[email protected]> Signed-off-by: Ulf Hansson <[email protected]> Tested-by: Ludovic Desroches <[email protected]>
1 parent ac9f67b commit c959a6b

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

drivers/mmc/host/sdhci-pci-core.c

+90
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,77 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
259259
.probe_slot = pch_hc_probe_slot,
260260
};
261261

262+
enum {
263+
INTEL_DSM_FNS = 0,
264+
INTEL_DSM_D3_RETUNE = 10,
265+
};
266+
267+
struct intel_host {
268+
u32 dsm_fns;
269+
bool d3_retune;
270+
};
271+
272+
const u8 intel_dsm_uuid[] = {
273+
0xA5, 0x3E, 0xC1, 0xF6, 0xCD, 0x65, 0x1F, 0x46,
274+
0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61,
275+
};
276+
277+
static int __intel_dsm(struct intel_host *intel_host, struct device *dev,
278+
unsigned int fn, u32 *result)
279+
{
280+
union acpi_object *obj;
281+
int err = 0;
282+
283+
obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), intel_dsm_uuid, 0, fn, NULL);
284+
if (!obj)
285+
return -EOPNOTSUPP;
286+
287+
if (obj->type != ACPI_TYPE_BUFFER || obj->buffer.length < 1) {
288+
err = -EINVAL;
289+
goto out;
290+
}
291+
292+
if (obj->buffer.length >= 4)
293+
*result = *(u32 *)obj->buffer.pointer;
294+
else if (obj->buffer.length >= 2)
295+
*result = *(u16 *)obj->buffer.pointer;
296+
else
297+
*result = *(u8 *)obj->buffer.pointer;
298+
out:
299+
ACPI_FREE(obj);
300+
301+
return err;
302+
}
303+
304+
static int intel_dsm(struct intel_host *intel_host, struct device *dev,
305+
unsigned int fn, u32 *result)
306+
{
307+
if (fn > 31 || !(intel_host->dsm_fns & (1 << fn)))
308+
return -EOPNOTSUPP;
309+
310+
return __intel_dsm(intel_host, dev, fn, result);
311+
}
312+
313+
static void intel_dsm_init(struct intel_host *intel_host, struct device *dev,
314+
struct mmc_host *mmc)
315+
{
316+
int err;
317+
u32 val;
318+
319+
err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns);
320+
if (err) {
321+
pr_debug("%s: DSM not supported, error %d\n",
322+
mmc_hostname(mmc), err);
323+
return;
324+
}
325+
326+
pr_debug("%s: DSM function mask %#x\n",
327+
mmc_hostname(mmc), intel_host->dsm_fns);
328+
329+
err = intel_dsm(intel_host, dev, INTEL_DSM_D3_RETUNE, &val);
330+
intel_host->d3_retune = err ? true : !!val;
331+
}
332+
262333
static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
263334
{
264335
u8 reg;
@@ -359,8 +430,19 @@ static int bxt_get_cd(struct mmc_host *mmc)
359430
return ret;
360431
}
361432

433+
static void byt_read_dsm(struct sdhci_pci_slot *slot)
434+
{
435+
struct intel_host *intel_host = sdhci_pci_priv(slot);
436+
struct device *dev = &slot->chip->pdev->dev;
437+
struct mmc_host *mmc = slot->host->mmc;
438+
439+
intel_dsm_init(intel_host, dev, mmc);
440+
slot->chip->rpm_retune = intel_host->d3_retune;
441+
}
442+
362443
static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
363444
{
445+
byt_read_dsm(slot);
364446
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
365447
MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
366448
MMC_CAP_CMD_DURING_TFR |
@@ -405,6 +487,8 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
405487
{
406488
int err;
407489

490+
byt_read_dsm(slot);
491+
408492
err = ni_set_max_freq(slot);
409493
if (err)
410494
return err;
@@ -416,13 +500,15 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
416500

417501
static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
418502
{
503+
byt_read_dsm(slot);
419504
slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
420505
MMC_CAP_WAIT_WHILE_BUSY;
421506
return 0;
422507
}
423508

424509
static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
425510
{
511+
byt_read_dsm(slot);
426512
slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
427513
slot->cd_idx = 0;
428514
slot->cd_override_level = true;
@@ -488,6 +574,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
488574
SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 |
489575
SDHCI_QUIRK2_STOP_WITH_TC,
490576
.ops = &sdhci_intel_byt_ops,
577+
.priv_size = sizeof(struct intel_host),
491578
};
492579

493580
static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
@@ -497,6 +584,7 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
497584
.allow_runtime_pm = true,
498585
.probe_slot = ni_byt_sdio_probe_slot,
499586
.ops = &sdhci_intel_byt_ops,
587+
.priv_size = sizeof(struct intel_host),
500588
};
501589

502590
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
@@ -506,6 +594,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
506594
.allow_runtime_pm = true,
507595
.probe_slot = byt_sdio_probe_slot,
508596
.ops = &sdhci_intel_byt_ops,
597+
.priv_size = sizeof(struct intel_host),
509598
};
510599

511600
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
@@ -517,6 +606,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
517606
.own_cd_for_runtime_pm = true,
518607
.probe_slot = byt_sd_probe_slot,
519608
.ops = &sdhci_intel_byt_ops,
609+
.priv_size = sizeof(struct intel_host),
520610
};
521611

522612
/* Define Host controllers for Intel Merrifield platform */

0 commit comments

Comments
 (0)