* [PATCH 0/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers @ 2017-10-19 10:41 Adrian Hunter 2017-10-19 10:41 ` [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() Adrian Hunter ` (3 more replies) 0 siblings, 4 replies; 11+ messages in thread From: Adrian Hunter @ 2017-10-19 10:41 UTC (permalink / raw) To: Ulf Hansson; +Cc: linux-mmc Hi Here are a few patches to fix voltage switching on some Intel host controllers. Adrian Hunter (4): mmc: sdhci-acpi: Use helper function acpi_device_uid() mmc: sdhci-acpi: Tidy Intel slot probe functions into one mmc: sdhci-acpi: Let devices define their own private data mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers drivers/mmc/host/sdhci-acpi.c | 174 +++++++++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 45 deletions(-) Regards Adrian ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() 2017-10-19 10:41 [PATCH 0/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter @ 2017-10-19 10:41 ` Adrian Hunter 2017-10-20 10:03 ` Ulf Hansson 2017-10-19 10:41 ` [PATCH 2/4] mmc: sdhci-acpi: Tidy Intel slot probe functions into one Adrian Hunter ` (2 subsequent siblings) 3 siblings, 1 reply; 11+ messages in thread From: Adrian Hunter @ 2017-10-19 10:41 UTC (permalink / raw) To: Ulf Hansson; +Cc: linux-mmc Make use of acpi_device_uid() instead of open coding. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- drivers/mmc/host/sdhci-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 08ae0ff13513..e4b7fac5efb2 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -443,7 +443,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) return -ENODEV; hid = acpi_device_hid(device); - uid = device->pnp.unique_id; + uid = acpi_device_uid(device); /* Power on the SDHCI controller and its children */ acpi_device_fix_up_power(device); -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() 2017-10-19 10:41 ` [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() Adrian Hunter @ 2017-10-20 10:03 ` Ulf Hansson 0 siblings, 0 replies; 11+ messages in thread From: Ulf Hansson @ 2017-10-20 10:03 UTC (permalink / raw) To: Adrian Hunter; +Cc: linux-mmc On 19 October 2017 at 12:41, Adrian Hunter <adrian.hunter@intel.com> wrote: > Make use of acpi_device_uid() instead of open coding. > > Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Thanks, applied for next! Kind regards Uffe > --- > drivers/mmc/host/sdhci-acpi.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c > index 08ae0ff13513..e4b7fac5efb2 100644 > --- a/drivers/mmc/host/sdhci-acpi.c > +++ b/drivers/mmc/host/sdhci-acpi.c > @@ -443,7 +443,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) > return -ENODEV; > > hid = acpi_device_hid(device); > - uid = device->pnp.unique_id; > + uid = acpi_device_uid(device); > > /* Power on the SDHCI controller and its children */ > acpi_device_fix_up_power(device); > -- > 1.9.1 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/4] mmc: sdhci-acpi: Tidy Intel slot probe functions into one 2017-10-19 10:41 [PATCH 0/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 2017-10-19 10:41 ` [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() Adrian Hunter @ 2017-10-19 10:41 ` Adrian Hunter 2017-10-20 10:03 ` Ulf Hansson 2017-10-19 10:41 ` [PATCH 3/4] mmc: sdhci-acpi: Let devices define their own private data Adrian Hunter 2017-10-19 10:41 ` [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 3 siblings, 1 reply; 11+ messages in thread From: Adrian Hunter @ 2017-10-19 10:41 UTC (permalink / raw) To: Ulf Hansson; +Cc: linux-mmc Tidy Intel slot probe functions into one. A single function can be used because the logic uses hid / uid as necessary to identify devices anyway. This gets rid of some pointless comments and checks for variables that cannot possibly be NULL, as well as giving the function a name that identifies it as specific to Intel controllers. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- drivers/mmc/host/sdhci-acpi.c | 48 ++++++------------------------------------- 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index e4b7fac5efb2..640be5b618fc 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -269,53 +269,17 @@ static int bxt_get_cd(struct mmc_host *mmc) return ret; } -static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev, - const char *hid, const char *uid) +static int intel_probe_slot(struct platform_device *pdev, const char *hid, + const char *uid) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); - struct sdhci_host *host; - - if (!c || !c->host) - return 0; - - host = c->host; - - /* Platform specific code during emmc probe slot goes here */ + struct sdhci_host *host = c->host; if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 && sdhci_readl(host, SDHCI_CAPABILITIES_1) == 0x00000807) host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ - return 0; -} - -static int sdhci_acpi_sdio_probe_slot(struct platform_device *pdev, - const char *hid, const char *uid) -{ - struct sdhci_acpi_host *c = platform_get_drvdata(pdev); - - if (!c || !c->host) - return 0; - - /* Platform specific code during sdio probe slot goes here */ - - return 0; -} - -static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, - const char *hid, const char *uid) -{ - struct sdhci_acpi_host *c = platform_get_drvdata(pdev); - struct sdhci_host *host; - - if (!c || !c->host || !c->slot) - return 0; - - host = c->host; - - /* Platform specific code during sd probe slot goes here */ - if (hid && !strcmp(hid, "80865ACA")) host->mmc_host_ops.get_cd = bxt_get_cd; @@ -332,7 +296,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | SDHCI_QUIRK2_STOP_WITH_TC | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, - .probe_slot = sdhci_acpi_emmc_probe_slot, + .probe_slot = intel_probe_slot, }; static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { @@ -343,7 +307,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, MMC_CAP_WAIT_WHILE_BUSY, .flags = SDHCI_ACPI_RUNTIME_PM, .pm_caps = MMC_PM_KEEP_POWER, - .probe_slot = sdhci_acpi_sdio_probe_slot, + .probe_slot = intel_probe_slot, }; static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { @@ -353,7 +317,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | SDHCI_QUIRK2_STOP_WITH_TC, .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, - .probe_slot = sdhci_acpi_sd_probe_slot, + .probe_slot = intel_probe_slot, }; static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = { -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/4] mmc: sdhci-acpi: Tidy Intel slot probe functions into one 2017-10-19 10:41 ` [PATCH 2/4] mmc: sdhci-acpi: Tidy Intel slot probe functions into one Adrian Hunter @ 2017-10-20 10:03 ` Ulf Hansson 0 siblings, 0 replies; 11+ messages in thread From: Ulf Hansson @ 2017-10-20 10:03 UTC (permalink / raw) To: Adrian Hunter; +Cc: linux-mmc On 19 October 2017 at 12:41, Adrian Hunter <adrian.hunter@intel.com> wrote: > Tidy Intel slot probe functions into one. A single function can be used > because the logic uses hid / uid as necessary to identify devices anyway. > This gets rid of some pointless comments and checks for variables that > cannot possibly be NULL, as well as giving the function a name that > identifies it as specific to Intel controllers. > > Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Thanks, applied for next! Kind regards Uffe > --- > drivers/mmc/host/sdhci-acpi.c | 48 ++++++------------------------------------- > 1 file changed, 6 insertions(+), 42 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c > index e4b7fac5efb2..640be5b618fc 100644 > --- a/drivers/mmc/host/sdhci-acpi.c > +++ b/drivers/mmc/host/sdhci-acpi.c > @@ -269,53 +269,17 @@ static int bxt_get_cd(struct mmc_host *mmc) > return ret; > } > > -static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev, > - const char *hid, const char *uid) > +static int intel_probe_slot(struct platform_device *pdev, const char *hid, > + const char *uid) > { > struct sdhci_acpi_host *c = platform_get_drvdata(pdev); > - struct sdhci_host *host; > - > - if (!c || !c->host) > - return 0; > - > - host = c->host; > - > - /* Platform specific code during emmc probe slot goes here */ > + struct sdhci_host *host = c->host; > > if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && > sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 && > sdhci_readl(host, SDHCI_CAPABILITIES_1) == 0x00000807) > host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ > > - return 0; > -} > - > -static int sdhci_acpi_sdio_probe_slot(struct platform_device *pdev, > - const char *hid, const char *uid) > -{ > - struct sdhci_acpi_host *c = platform_get_drvdata(pdev); > - > - if (!c || !c->host) > - return 0; > - > - /* Platform specific code during sdio probe slot goes here */ > - > - return 0; > -} > - > -static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, > - const char *hid, const char *uid) > -{ > - struct sdhci_acpi_host *c = platform_get_drvdata(pdev); > - struct sdhci_host *host; > - > - if (!c || !c->host || !c->slot) > - return 0; > - > - host = c->host; > - > - /* Platform specific code during sd probe slot goes here */ > - > if (hid && !strcmp(hid, "80865ACA")) > host->mmc_host_ops.get_cd = bxt_get_cd; > > @@ -332,7 +296,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, > .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | > SDHCI_QUIRK2_STOP_WITH_TC | > SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, > - .probe_slot = sdhci_acpi_emmc_probe_slot, > + .probe_slot = intel_probe_slot, > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { > @@ -343,7 +307,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, > MMC_CAP_WAIT_WHILE_BUSY, > .flags = SDHCI_ACPI_RUNTIME_PM, > .pm_caps = MMC_PM_KEEP_POWER, > - .probe_slot = sdhci_acpi_sdio_probe_slot, > + .probe_slot = intel_probe_slot, > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { > @@ -353,7 +317,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, > .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | > SDHCI_QUIRK2_STOP_WITH_TC, > .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, > - .probe_slot = sdhci_acpi_sd_probe_slot, > + .probe_slot = intel_probe_slot, > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = { > -- > 1.9.1 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/4] mmc: sdhci-acpi: Let devices define their own private data 2017-10-19 10:41 [PATCH 0/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 2017-10-19 10:41 ` [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() Adrian Hunter 2017-10-19 10:41 ` [PATCH 2/4] mmc: sdhci-acpi: Tidy Intel slot probe functions into one Adrian Hunter @ 2017-10-19 10:41 ` Adrian Hunter 2017-10-30 11:40 ` Ulf Hansson 2017-10-19 10:41 ` [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 3 siblings, 1 reply; 11+ messages in thread From: Adrian Hunter @ 2017-10-19 10:41 UTC (permalink / raw) To: Ulf Hansson; +Cc: linux-mmc Let devices define their own private data to facilitate device-specific operations. The size of the private structure is specified in the sdhci_acpi_slot structure, then sdhci_acpi_probe() will allocate extra space for it, and sdhci_acpi_priv() can be used to get a reference to it. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- drivers/mmc/host/sdhci-acpi.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 640be5b618fc..5bb5880403b2 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -73,6 +73,7 @@ struct sdhci_acpi_slot { unsigned int caps2; mmc_pm_flag_t pm_caps; unsigned int flags; + size_t priv_size; int (*probe_slot)(struct platform_device *, const char *, const char *); int (*remove_slot)(struct platform_device *); }; @@ -82,8 +83,14 @@ struct sdhci_acpi_host { const struct sdhci_acpi_slot *slot; struct platform_device *pdev; bool use_runtime_pm; + unsigned long private[0] ____cacheline_aligned; }; +static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c) +{ + return (void *)c->private; +} + static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) { return c->slot && (c->slot->flags & flag); @@ -393,11 +400,13 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid, static int sdhci_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct sdhci_acpi_slot *slot; struct acpi_device *device, *child; struct sdhci_acpi_host *c; struct sdhci_host *host; struct resource *iomem; resource_size_t len; + size_t priv_size; const char *hid; const char *uid; int err; @@ -409,6 +418,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev) hid = acpi_device_hid(device); uid = acpi_device_uid(device); + slot = sdhci_acpi_get_slot(hid, uid); + /* Power on the SDHCI controller and its children */ acpi_device_fix_up_power(device); if (!sdhci_acpi_no_fixup_child_power(hid, uid)) { @@ -431,13 +442,14 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) return -ENOMEM; - host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); + priv_size = slot ? slot->priv_size : 0; + host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host) + priv_size); if (IS_ERR(host)) return PTR_ERR(host); c = sdhci_priv(host); c->host = host; - c->slot = sdhci_acpi_get_slot(hid, uid); + c->slot = slot; c->pdev = pdev; c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] mmc: sdhci-acpi: Let devices define their own private data 2017-10-19 10:41 ` [PATCH 3/4] mmc: sdhci-acpi: Let devices define their own private data Adrian Hunter @ 2017-10-30 11:40 ` Ulf Hansson 0 siblings, 0 replies; 11+ messages in thread From: Ulf Hansson @ 2017-10-30 11:40 UTC (permalink / raw) To: Adrian Hunter; +Cc: linux-mmc On 19 October 2017 at 12:41, Adrian Hunter <adrian.hunter@intel.com> wrote: > Let devices define their own private data to facilitate device-specific > operations. The size of the private structure is specified in the > sdhci_acpi_slot structure, then sdhci_acpi_probe() will allocate extra > space for it, and sdhci_acpi_priv() can be used to get a reference to it. > > Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Thanks, applied for next! Kind regards Uffe > --- > drivers/mmc/host/sdhci-acpi.c | 16 ++++++++++++++-- > 1 file changed, 14 insertions(+), 2 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c > index 640be5b618fc..5bb5880403b2 100644 > --- a/drivers/mmc/host/sdhci-acpi.c > +++ b/drivers/mmc/host/sdhci-acpi.c > @@ -73,6 +73,7 @@ struct sdhci_acpi_slot { > unsigned int caps2; > mmc_pm_flag_t pm_caps; > unsigned int flags; > + size_t priv_size; > int (*probe_slot)(struct platform_device *, const char *, const char *); > int (*remove_slot)(struct platform_device *); > }; > @@ -82,8 +83,14 @@ struct sdhci_acpi_host { > const struct sdhci_acpi_slot *slot; > struct platform_device *pdev; > bool use_runtime_pm; > + unsigned long private[0] ____cacheline_aligned; > }; > > +static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c) > +{ > + return (void *)c->private; > +} > + > static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) > { > return c->slot && (c->slot->flags & flag); > @@ -393,11 +400,13 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid, > static int sdhci_acpi_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > + const struct sdhci_acpi_slot *slot; > struct acpi_device *device, *child; > struct sdhci_acpi_host *c; > struct sdhci_host *host; > struct resource *iomem; > resource_size_t len; > + size_t priv_size; > const char *hid; > const char *uid; > int err; > @@ -409,6 +418,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev) > hid = acpi_device_hid(device); > uid = acpi_device_uid(device); > > + slot = sdhci_acpi_get_slot(hid, uid); > + > /* Power on the SDHCI controller and its children */ > acpi_device_fix_up_power(device); > if (!sdhci_acpi_no_fixup_child_power(hid, uid)) { > @@ -431,13 +442,14 @@ static int sdhci_acpi_probe(struct platform_device *pdev) > if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) > return -ENOMEM; > > - host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); > + priv_size = slot ? slot->priv_size : 0; > + host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host) + priv_size); > if (IS_ERR(host)) > return PTR_ERR(host); > > c = sdhci_priv(host); > c->host = host; > - c->slot = sdhci_acpi_get_slot(hid, uid); > + c->slot = slot; > c->pdev = pdev; > c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); > > -- > 1.9.1 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers 2017-10-19 10:41 [PATCH 0/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter ` (2 preceding siblings ...) 2017-10-19 10:41 ` [PATCH 3/4] mmc: sdhci-acpi: Let devices define their own private data Adrian Hunter @ 2017-10-19 10:41 ` Adrian Hunter 2017-10-20 9:16 ` Ulf Hansson 2017-10-30 11:40 ` Ulf Hansson 3 siblings, 2 replies; 11+ messages in thread From: Adrian Hunter @ 2017-10-19 10:41 UTC (permalink / raw) To: Ulf Hansson; +Cc: linux-mmc Some Intel host controllers use an ACPI device-specific method to ensure correct voltage switching. Fix voltage switch for those, by adding a call to the DSM. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- drivers/mmc/host/sdhci-acpi.c | 108 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 5bb5880403b2..b988997a1e80 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -96,6 +96,105 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) return c->slot && (c->slot->flags & flag); } +enum { + INTEL_DSM_FNS = 0, + INTEL_DSM_V18_SWITCH = 3, + INTEL_DSM_V33_SWITCH = 4, +}; + +struct intel_host { + u32 dsm_fns; +}; + +static const guid_t intel_dsm_guid = + GUID_INIT(0xF6C13EA5, 0x65CD, 0x461F, + 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61); + +static int __intel_dsm(struct intel_host *intel_host, struct device *dev, + unsigned int fn, u32 *result) +{ + union acpi_object *obj; + int err = 0; + + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL); + if (!obj) + return -EOPNOTSUPP; + + if (obj->type == ACPI_TYPE_INTEGER) { + *result = obj->integer.value; + } else if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length > 0) { + size_t len = min_t(size_t, obj->buffer.length, 4); + + *result = 0; + memcpy(result, obj->buffer.pointer, len); + } else { + dev_err(dev, "%s DSM fn %u obj->type %d obj->buffer.length %d\n", + __func__, fn, obj->type, obj->buffer.length); + err = -EINVAL; + } + + ACPI_FREE(obj); + + return err; +} + +static int intel_dsm(struct intel_host *intel_host, struct device *dev, + unsigned int fn, u32 *result) +{ + if (fn > 31 || !(intel_host->dsm_fns & (1 << fn))) + return -EOPNOTSUPP; + + return __intel_dsm(intel_host, dev, fn, result); +} + +static void intel_dsm_init(struct intel_host *intel_host, struct device *dev, + struct mmc_host *mmc) +{ + int err; + + err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns); + if (err) { + pr_debug("%s: DSM not supported, error %d\n", + mmc_hostname(mmc), err); + return; + } + + pr_debug("%s: DSM function mask %#x\n", + mmc_hostname(mmc), intel_host->dsm_fns); +} + +static int intel_start_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct device *dev = mmc_dev(mmc); + struct sdhci_acpi_host *c = dev_get_drvdata(dev); + struct intel_host *intel_host = sdhci_acpi_priv(c); + unsigned int fn; + u32 result = 0; + int err; + + err = sdhci_start_signal_voltage_switch(mmc, ios); + if (err) + return err; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + fn = INTEL_DSM_V33_SWITCH; + break; + case MMC_SIGNAL_VOLTAGE_180: + fn = INTEL_DSM_V18_SWITCH; + break; + default: + return 0; + } + + err = intel_dsm(intel_host, dev, fn, &result); + pr_debug("%s: %s DSM fn %u error %d result %u\n", + mmc_hostname(mmc), __func__, fn, err, result); + + return 0; +} + static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) { u8 reg; @@ -280,6 +379,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, const char *uid) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); + struct intel_host *intel_host = sdhci_acpi_priv(c); struct sdhci_host *host = c->host; if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && @@ -290,6 +390,11 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, if (hid && !strcmp(hid, "80865ACA")) host->mmc_host_ops.get_cd = bxt_get_cd; + intel_dsm_init(intel_host, &pdev->dev, host->mmc); + + host->mmc_host_ops.start_signal_voltage_switch = + intel_start_signal_voltage_switch; + return 0; } @@ -304,6 +409,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, SDHCI_QUIRK2_STOP_WITH_TC | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, .probe_slot = intel_probe_slot, + .priv_size = sizeof(struct intel_host), }; static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { @@ -315,6 +421,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, .flags = SDHCI_ACPI_RUNTIME_PM, .pm_caps = MMC_PM_KEEP_POWER, .probe_slot = intel_probe_slot, + .priv_size = sizeof(struct intel_host), }; static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { @@ -325,6 +432,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, SDHCI_QUIRK2_STOP_WITH_TC, .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, .probe_slot = intel_probe_slot, + .priv_size = sizeof(struct intel_host), }; static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = { -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers 2017-10-19 10:41 ` [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter @ 2017-10-20 9:16 ` Ulf Hansson 2017-10-20 11:11 ` Adrian Hunter 2017-10-30 11:40 ` Ulf Hansson 1 sibling, 1 reply; 11+ messages in thread From: Ulf Hansson @ 2017-10-20 9:16 UTC (permalink / raw) To: Adrian Hunter; +Cc: linux-mmc On 19 October 2017 at 12:41, Adrian Hunter <adrian.hunter@intel.com> wrote: > Some Intel host controllers use an ACPI device-specific method to ensure > correct voltage switching. Fix voltage switch for those, by adding a call > to the DSM. > > Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> > --- > drivers/mmc/host/sdhci-acpi.c | 108 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 108 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c > index 5bb5880403b2..b988997a1e80 100644 > --- a/drivers/mmc/host/sdhci-acpi.c > +++ b/drivers/mmc/host/sdhci-acpi.c > @@ -96,6 +96,105 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) > return c->slot && (c->slot->flags & flag); > } > > +enum { > + INTEL_DSM_FNS = 0, > + INTEL_DSM_V18_SWITCH = 3, > + INTEL_DSM_V33_SWITCH = 4, > +}; > + > +struct intel_host { > + u32 dsm_fns; > +}; > + > +static const guid_t intel_dsm_guid = > + GUID_INIT(0xF6C13EA5, 0x65CD, 0x461F, > + 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61); > + > +static int __intel_dsm(struct intel_host *intel_host, struct device *dev, > + unsigned int fn, u32 *result) > +{ > + union acpi_object *obj; > + int err = 0; > + > + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL); > + if (!obj) > + return -EOPNOTSUPP; > + > + if (obj->type == ACPI_TYPE_INTEGER) { > + *result = obj->integer.value; > + } else if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length > 0) { > + size_t len = min_t(size_t, obj->buffer.length, 4); > + > + *result = 0; > + memcpy(result, obj->buffer.pointer, len); > + } else { > + dev_err(dev, "%s DSM fn %u obj->type %d obj->buffer.length %d\n", > + __func__, fn, obj->type, obj->buffer.length); > + err = -EINVAL; > + } > + This hole ACPI thing looks weird. Could perhaps the ACPI core, model this a vqmmc regulator instead? That would keep the ACPI specific part closer to ACPI and we can treat this similar to other mmc host drivers. > + ACPI_FREE(obj); > + > + return err; > +} > + [...] Kind regards Uffe ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers 2017-10-20 9:16 ` Ulf Hansson @ 2017-10-20 11:11 ` Adrian Hunter 0 siblings, 0 replies; 11+ messages in thread From: Adrian Hunter @ 2017-10-20 11:11 UTC (permalink / raw) To: Ulf Hansson; +Cc: linux-mmc On 20/10/17 12:16, Ulf Hansson wrote: > On 19 October 2017 at 12:41, Adrian Hunter <adrian.hunter@intel.com> wrote: >> Some Intel host controllers use an ACPI device-specific method to ensure >> correct voltage switching. Fix voltage switch for those, by adding a call >> to the DSM. >> >> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> >> --- >> drivers/mmc/host/sdhci-acpi.c | 108 ++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 108 insertions(+) >> >> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c >> index 5bb5880403b2..b988997a1e80 100644 >> --- a/drivers/mmc/host/sdhci-acpi.c >> +++ b/drivers/mmc/host/sdhci-acpi.c >> @@ -96,6 +96,105 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) >> return c->slot && (c->slot->flags & flag); >> } >> >> +enum { >> + INTEL_DSM_FNS = 0, >> + INTEL_DSM_V18_SWITCH = 3, >> + INTEL_DSM_V33_SWITCH = 4, >> +}; >> + >> +struct intel_host { >> + u32 dsm_fns; >> +}; >> + >> +static const guid_t intel_dsm_guid = >> + GUID_INIT(0xF6C13EA5, 0x65CD, 0x461F, >> + 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61); >> + >> +static int __intel_dsm(struct intel_host *intel_host, struct device *dev, >> + unsigned int fn, u32 *result) >> +{ >> + union acpi_object *obj; >> + int err = 0; >> + >> + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL); >> + if (!obj) >> + return -EOPNOTSUPP; >> + >> + if (obj->type == ACPI_TYPE_INTEGER) { >> + *result = obj->integer.value; >> + } else if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length > 0) { >> + size_t len = min_t(size_t, obj->buffer.length, 4); >> + >> + *result = 0; >> + memcpy(result, obj->buffer.pointer, len); >> + } else { >> + dev_err(dev, "%s DSM fn %u obj->type %d obj->buffer.length %d\n", >> + __func__, fn, obj->type, obj->buffer.length); >> + err = -EINVAL; >> + } >> + > > This hole ACPI thing looks weird. DSMs are normal. > Could perhaps the ACPI core, model > this a vqmmc regulator instead? The regulator framework does not support that. > > That would keep the ACPI specific part closer to ACPI and we can treat > this similar to other mmc host drivers. Device-specific methods (DSM) are device specific so they belong in the driver not ACPI core. So the code would all end up here anyway but be more complicated and more obfuscated. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers 2017-10-19 10:41 ` [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 2017-10-20 9:16 ` Ulf Hansson @ 2017-10-30 11:40 ` Ulf Hansson 1 sibling, 0 replies; 11+ messages in thread From: Ulf Hansson @ 2017-10-30 11:40 UTC (permalink / raw) To: Adrian Hunter; +Cc: linux-mmc On 19 October 2017 at 12:41, Adrian Hunter <adrian.hunter@intel.com> wrote: > Some Intel host controllers use an ACPI device-specific method to ensure > correct voltage switching. Fix voltage switch for those, by adding a call > to the DSM. > > Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Thanks, applied for next! Kind regards Uffe > --- > drivers/mmc/host/sdhci-acpi.c | 108 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 108 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c > index 5bb5880403b2..b988997a1e80 100644 > --- a/drivers/mmc/host/sdhci-acpi.c > +++ b/drivers/mmc/host/sdhci-acpi.c > @@ -96,6 +96,105 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) > return c->slot && (c->slot->flags & flag); > } > > +enum { > + INTEL_DSM_FNS = 0, > + INTEL_DSM_V18_SWITCH = 3, > + INTEL_DSM_V33_SWITCH = 4, > +}; > + > +struct intel_host { > + u32 dsm_fns; > +}; > + > +static const guid_t intel_dsm_guid = > + GUID_INIT(0xF6C13EA5, 0x65CD, 0x461F, > + 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61); > + > +static int __intel_dsm(struct intel_host *intel_host, struct device *dev, > + unsigned int fn, u32 *result) > +{ > + union acpi_object *obj; > + int err = 0; > + > + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL); > + if (!obj) > + return -EOPNOTSUPP; > + > + if (obj->type == ACPI_TYPE_INTEGER) { > + *result = obj->integer.value; > + } else if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length > 0) { > + size_t len = min_t(size_t, obj->buffer.length, 4); > + > + *result = 0; > + memcpy(result, obj->buffer.pointer, len); > + } else { > + dev_err(dev, "%s DSM fn %u obj->type %d obj->buffer.length %d\n", > + __func__, fn, obj->type, obj->buffer.length); > + err = -EINVAL; > + } > + > + ACPI_FREE(obj); > + > + return err; > +} > + > +static int intel_dsm(struct intel_host *intel_host, struct device *dev, > + unsigned int fn, u32 *result) > +{ > + if (fn > 31 || !(intel_host->dsm_fns & (1 << fn))) > + return -EOPNOTSUPP; > + > + return __intel_dsm(intel_host, dev, fn, result); > +} > + > +static void intel_dsm_init(struct intel_host *intel_host, struct device *dev, > + struct mmc_host *mmc) > +{ > + int err; > + > + err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns); > + if (err) { > + pr_debug("%s: DSM not supported, error %d\n", > + mmc_hostname(mmc), err); > + return; > + } > + > + pr_debug("%s: DSM function mask %#x\n", > + mmc_hostname(mmc), intel_host->dsm_fns); > +} > + > +static int intel_start_signal_voltage_switch(struct mmc_host *mmc, > + struct mmc_ios *ios) > +{ > + struct device *dev = mmc_dev(mmc); > + struct sdhci_acpi_host *c = dev_get_drvdata(dev); > + struct intel_host *intel_host = sdhci_acpi_priv(c); > + unsigned int fn; > + u32 result = 0; > + int err; > + > + err = sdhci_start_signal_voltage_switch(mmc, ios); > + if (err) > + return err; > + > + switch (ios->signal_voltage) { > + case MMC_SIGNAL_VOLTAGE_330: > + fn = INTEL_DSM_V33_SWITCH; > + break; > + case MMC_SIGNAL_VOLTAGE_180: > + fn = INTEL_DSM_V18_SWITCH; > + break; > + default: > + return 0; > + } > + > + err = intel_dsm(intel_host, dev, fn, &result); > + pr_debug("%s: %s DSM fn %u error %d result %u\n", > + mmc_hostname(mmc), __func__, fn, err, result); > + > + return 0; > +} > + > static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) > { > u8 reg; > @@ -280,6 +379,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, > const char *uid) > { > struct sdhci_acpi_host *c = platform_get_drvdata(pdev); > + struct intel_host *intel_host = sdhci_acpi_priv(c); > struct sdhci_host *host = c->host; > > if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && > @@ -290,6 +390,11 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, > if (hid && !strcmp(hid, "80865ACA")) > host->mmc_host_ops.get_cd = bxt_get_cd; > > + intel_dsm_init(intel_host, &pdev->dev, host->mmc); > + > + host->mmc_host_ops.start_signal_voltage_switch = > + intel_start_signal_voltage_switch; > + > return 0; > } > > @@ -304,6 +409,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, > SDHCI_QUIRK2_STOP_WITH_TC | > SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, > .probe_slot = intel_probe_slot, > + .priv_size = sizeof(struct intel_host), > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { > @@ -315,6 +421,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, > .flags = SDHCI_ACPI_RUNTIME_PM, > .pm_caps = MMC_PM_KEEP_POWER, > .probe_slot = intel_probe_slot, > + .priv_size = sizeof(struct intel_host), > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { > @@ -325,6 +432,7 @@ static int intel_probe_slot(struct platform_device *pdev, const char *hid, > SDHCI_QUIRK2_STOP_WITH_TC, > .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, > .probe_slot = intel_probe_slot, > + .priv_size = sizeof(struct intel_host), > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = { > -- > 1.9.1 > ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2017-10-30 11:40 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-10-19 10:41 [PATCH 0/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 2017-10-19 10:41 ` [PATCH 1/4] mmc: sdhci-acpi: Use helper function acpi_device_uid() Adrian Hunter 2017-10-20 10:03 ` Ulf Hansson 2017-10-19 10:41 ` [PATCH 2/4] mmc: sdhci-acpi: Tidy Intel slot probe functions into one Adrian Hunter 2017-10-20 10:03 ` Ulf Hansson 2017-10-19 10:41 ` [PATCH 3/4] mmc: sdhci-acpi: Let devices define their own private data Adrian Hunter 2017-10-30 11:40 ` Ulf Hansson 2017-10-19 10:41 ` [PATCH 4/4] mmc: sdhci-acpi: Fix voltage switch for some Intel host controllers Adrian Hunter 2017-10-20 9:16 ` Ulf Hansson 2017-10-20 11:11 ` Adrian Hunter 2017-10-30 11:40 ` Ulf Hansson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.