@@ -137,7 +137,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
@@ -5,12 +5,15 @@
*/
#include <common.h>
+#include <acpigen.h>
+#include <acpi_device.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <mapmem.h>
#include <sdhci.h>
-#include <asm/pci.h>
+#include <asm-generic/gpio.h>
+#include <dm/acpi.h>
struct pci_mmc_plat {
struct mmc_config cfg;
@@ -20,6 +23,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 +48,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 +64,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[] = {
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 at chromium.org> --- configs/sandbox_defconfig | 2 ++ drivers/mmc/pci_mmc.c | 76 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-)