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>
This commit is contained in:
		
							parent
							
								
									d7d631df2d
								
							
						
					
					
						commit
						dba7ee419d
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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[] = { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue