summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-07-07 21:32:12 -0600
committerBin Meng <bmeng.cn@gmail.com>2020-07-17 14:32:24 +0800
commitdba7ee419d9d8c433f35f693f7d145de71d715c5 (patch)
tree2fc0403043618848143f15de986ae3ddce5ddb7d /drivers/mmc
parentd7d631df2d4f32710dbecb020e375b9c0d986225 (diff)
acpi: mmc: Generate ACPI info for the PCI SD Card
Write required information into the SSDT to describe the SD card card-detect pin. Since the required GPIO properties are not present in the device-tree binding, set them manually for now. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/pci_mmc.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index 404264a697..0c45e1b893 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -7,10 +7,15 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <log.h>
#include <malloc.h>
#include <mapmem.h>
#include <sdhci.h>
-#include <asm/pci.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_device.h>
+#include <acpi/acpi_dp.h>
+#include <asm-generic/gpio.h>
+#include <dm/acpi.h>
struct pci_mmc_plat {
struct mmc_config cfg;
@@ -20,6 +25,7 @@ struct pci_mmc_plat {
struct pci_mmc_priv {
struct sdhci_host host;
void *base;
+ struct gpio_desc cd_gpio;
};
static int pci_mmc_probe(struct udevice *dev)
@@ -44,6 +50,15 @@ static int pci_mmc_probe(struct udevice *dev)
return sdhci_probe(dev);
}
+static int pci_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct pci_mmc_priv *priv = dev_get_priv(dev);
+
+ gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+
+ return 0;
+}
+
static int pci_mmc_bind(struct udevice *dev)
{
struct pci_mmc_plat *plat = dev_get_platdata(dev);
@@ -51,14 +66,75 @@ static int pci_mmc_bind(struct udevice *dev)
return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
+static int pci_mmc_acpi_fill_ssdt(const struct udevice *dev,
+ struct acpi_ctx *ctx)
+{
+ struct pci_mmc_priv *priv = dev_get_priv(dev);
+ char path[ACPI_PATH_MAX];
+ struct acpi_gpio gpio;
+ struct acpi_dp *dp;
+ int ret;
+
+ if (!dev_of_valid(dev))
+ return 0;
+
+ ret = gpio_get_acpi(&priv->cd_gpio, &gpio);
+ if (ret)
+ return log_msg_ret("gpio", ret);
+ gpio.type = ACPI_GPIO_TYPE_INTERRUPT;
+ gpio.pull = ACPI_GPIO_PULL_NONE;
+ gpio.irq.mode = ACPI_IRQ_EDGE_TRIGGERED;
+ gpio.irq.polarity = ACPI_IRQ_ACTIVE_BOTH;
+ gpio.irq.shared = ACPI_IRQ_SHARED;
+ gpio.irq.wake = ACPI_IRQ_WAKE;
+ gpio.interrupt_debounce_timeout = 10000; /* 100ms */
+
+ /* Use device path as the Scope for the SSDT */
+ ret = acpi_device_path(dev, path, sizeof(path));
+ if (ret)
+ return log_msg_ret("path", ret);
+ acpigen_write_scope(ctx, path);
+ acpigen_write_name(ctx, "_CRS");
+
+ /* Write GpioInt() as default (if set) or custom from devicetree */
+ acpigen_write_resourcetemplate_header(ctx);
+ acpi_device_write_gpio(ctx, &gpio);
+ acpigen_write_resourcetemplate_footer(ctx);
+
+ /* Bind the cd-gpio name to the GpioInt() resource */
+ dp = acpi_dp_new_table("_DSD");
+ if (!dp)
+ return -ENOMEM;
+ acpi_dp_add_gpio(dp, "cd-gpio", path, 0, 0, 1);
+ ret = acpi_dp_write(ctx, dp);
+ if (ret)
+ return log_msg_ret("cd", ret);
+
+ acpigen_pop_len(ctx);
+
+ return 0;
+}
+
+struct acpi_ops pci_mmc_acpi_ops = {
+ .fill_ssdt = pci_mmc_acpi_fill_ssdt,
+};
+
+static const struct udevice_id pci_mmc_match[] = {
+ { .compatible = "intel,apl-sd" },
+ { }
+};
+
U_BOOT_DRIVER(pci_mmc) = {
.name = "pci_mmc",
.id = UCLASS_MMC,
+ .of_match = pci_mmc_match,
.bind = pci_mmc_bind,
+ .ofdata_to_platdata = pci_mmc_ofdata_to_platdata,
.probe = pci_mmc_probe,
.ops = &sdhci_ops,
.priv_auto_alloc_size = sizeof(struct pci_mmc_priv),
.platdata_auto_alloc_size = sizeof(struct pci_mmc_plat),
+ ACPI_OPS_PTR(&pci_mmc_acpi_ops)
};
static struct pci_device_id mmc_supported[] = {