acpi: mmc: Generate ACPI info for the PCI SD Card
authorSimon Glass <sjg@chromium.org>
Wed, 8 Jul 2020 03:32:12 +0000 (21:32 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Fri, 17 Jul 2020 06:32:24 +0000 (14:32 +0800)
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>
configs/sandbox_defconfig
drivers/mmc/pci_mmc.c

index d43d78d..5389885 100644 (file)
@@ -149,7 +149,9 @@ CONFIG_P2SB=y
 CONFIG_PWRSEQ=y
 CONFIG_SPL_PWRSEQ=y
 CONFIG_I2C_EEPROM=y
+CONFIG_MMC_PCI=y
 CONFIG_MMC_SANDBOX=y
+CONFIG_MMC_SDHCI=y
 CONFIG_MTD=y
 CONFIG_SPI_FLASH_SANDBOX=y
 CONFIG_SPI_FLASH_ATMEL=y
index 404264a..0c45e1b 100644 (file)
@@ -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[] = {