diff options
Diffstat (limited to 'src/soc/intel/apollolake')
-rw-r--r-- | src/soc/intel/apollolake/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/intel/apollolake/acpi.c | 4 | ||||
-rw-r--r-- | src/soc/intel/apollolake/acpi/globalnvs.asl | 1 | ||||
-rw-r--r-- | src/soc/intel/apollolake/acpi/scs.asl | 38 | ||||
-rw-r--r-- | src/soc/intel/apollolake/chip.c | 14 | ||||
-rw-r--r-- | src/soc/intel/apollolake/chip.h | 5 | ||||
-rw-r--r-- | src/soc/intel/apollolake/include/soc/nvs.h | 3 | ||||
-rw-r--r-- | src/soc/intel/apollolake/sd.c | 82 |
8 files changed, 147 insertions, 1 deletions
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc index 5e1cf736fd..411bf585b4 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -85,6 +85,7 @@ ramstage-y += sram.c ramstage-y += spi.c ramstage-y += xdci.c ramstage-y += xhci.c +ramstage-y += sd.c postcar-y += flash_ctrlr.c postcar-y += memmap.c diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c index 3c1faa5cd2..bcf1420b3f 100644 --- a/src/soc/intel/apollolake/acpi.c +++ b/src/soc/intel/apollolake/acpi.c @@ -183,6 +183,10 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs) /* Assign address of PERST_0 if GPIO is defined in devicetree */ if (cfg->prt0_gpio != GPIO_PRT0_UDEF) gnvs->prt0 = (uintptr_t)gpio_dwx_address(cfg->prt0_gpio); + + /* Assign sdcard cd address if GPIO is defined in devicetree */ + if (cfg->sdcard_cd_gpio) + gnvs->scd0 = (uintptr_t)gpio_dwx_address(cfg->sdcard_cd_gpio); } /* Save wake source information for calculating ACPI _SWS values */ diff --git a/src/soc/intel/apollolake/acpi/globalnvs.asl b/src/soc/intel/apollolake/acpi/globalnvs.asl index 657c834b67..86a1a23fd6 100644 --- a/src/soc/intel/apollolake/acpi/globalnvs.asl +++ b/src/soc/intel/apollolake/acpi/globalnvs.asl @@ -39,6 +39,7 @@ Field (GNVS, ByteAcc, NoLock, Preserve) NHLA, 64, // 0x19 - 0x20 - NHLT Address NHLL, 32, // 0x21 - 0x24 - NHLT Length PRT0, 32, // 0x25 - 0x28 - PERST_0 Address + SCD0, 32, // 0x29 - 0x2D - SD_CD Address /* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */ Offset (0x100), diff --git a/src/soc/intel/apollolake/acpi/scs.asl b/src/soc/intel/apollolake/acpi/scs.asl index 4108017fe6..05aedca5a4 100644 --- a/src/soc/intel/apollolake/acpi/scs.asl +++ b/src/soc/intel/apollolake/acpi/scs.asl @@ -22,6 +22,9 @@ Scope (\_SB.PCI0) { Field (SBMM, DWordAcc, NoLock, Preserve) { GENR, 32, + Offset (0x08), + , 5, /* bit[5] represents Force Card Detect SD Card */ + GRR3, 1, /* GPPRVRW3 for SD Card detect Bypass. It's active high */ } /* SCC power gate control method, this method must be serialized as @@ -64,4 +67,39 @@ Scope (\_SB.PCI0) { ^^SCPG(1,0x00000041) } } /* Device (SDHA) */ + + /* SD CARD */ + Device (SDCD) + { + Name (_ADR, 0x001B0000) + + Method (_PS0, 0, NotSerialized) + { + /* Check SDCard CD pin address is valid */ + If (LNotEqual (SCD0, 0)) + { + /* Store DW0 into local0 to get rxstate of GPIO */ + Store (\_SB.GPC0 (\SCD0), Local0) + /* Extract rxstate [bit 1] of sdcard card detect pin */ + And (Local0, PAD_CFG0_RX_STATE, Local0) + /* If the sdcard is present, rxstate is low. + * If sdcard is not present, rxstate is High. + * Write the inverted value of rxstate to GRR3. + */ + If (LEqual (Local0, 0)) { + Store (1, ^^GRR3) + } Else { + Store (0, ^^GRR3) + } + Sleep (2) + } + } + + Method (_PS3, 0, NotSerialized) + { + /* Clear GRR3 to Power Gate SD Controller */ + Store (0, ^^GRR3) + } + + } /* Device (SDCD) */ } diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index 1de41cf59c..975d09840b 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -113,6 +113,20 @@ static const char *soc_acpi_name(struct device *dev) return NULL; } +static void pci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + if (!vendor || !device) + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + else + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + (device << 16) | vendor); +} + +struct pci_operations soc_pci_ops = { + .set_subsystem = &pci_set_subsystem +}; + static void pci_domain_set_resources(device_t dev) { assign_resources(dev->link_list); diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h index d60ffbf9f6..051816ddde 100644 --- a/src/soc/intel/apollolake/chip.h +++ b/src/soc/intel/apollolake/chip.h @@ -120,6 +120,11 @@ struct soc_intel_apollolake_config { /* USB2 eye diagram settings per port */ struct usb2_eye_per_port usb2eye[APOLLOLAKE_USB2_PORT_MAX]; + /* GPIO SD card detect pin */ + unsigned int sdcard_cd_gpio; }; +typedef struct soc_intel_apollolake_config config_t; +extern struct pci_operations soc_pci_ops; + #endif /* _SOC_APOLLOLAKE_CHIP_H_ */ diff --git a/src/soc/intel/apollolake/include/soc/nvs.h b/src/soc/intel/apollolake/include/soc/nvs.h index 21894cad51..21ac14e274 100644 --- a/src/soc/intel/apollolake/include/soc/nvs.h +++ b/src/soc/intel/apollolake/include/soc/nvs.h @@ -39,7 +39,8 @@ typedef struct global_nvs_t { uint64_t nhla; /* 0x19 - 0x20 - NHLT Address */ uint32_t nhll; /* 0x21 - 0x24 - NHLT Length */ uint32_t prt0; /* 0x25 - 0x28 - PERST_0 Address */ - uint8_t unused[215]; + uint32_t scd0; /* 0x29 - 0x2D - SD_CD Address */ + uint8_t unused[211]; /* ChromeOS specific (0x100 - 0xfff) */ chromeos_acpi_t chromeos; diff --git a/src/soc/intel/apollolake/sd.c b/src/soc/intel/apollolake/sd.c new file mode 100644 index 0000000000..2f38061b27 --- /dev/null +++ b/src/soc/intel/apollolake/sd.c @@ -0,0 +1,82 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/acpi_device.h> +#include <arch/acpigen.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <gpio.h> +#include "chip.h" + +#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) +static void sd_fill_ssdt(struct device *dev) +{ + config_t *config = dev->chip_info; + const char *path; + struct acpi_gpio default_gpio = { + .type = ACPI_GPIO_TYPE_INTERRUPT, + .pull = ACPI_GPIO_PULL_NONE, + .irq.mode = ACPI_IRQ_EDGE_TRIGGERED, + .irq.polarity = ACPI_IRQ_ACTIVE_BOTH, + .irq.shared = ACPI_IRQ_SHARED, + .irq.wake = ACPI_IRQ_WAKE, + .interrupt_debounce_timeout = 10000, /* 100ms */ + .pin_count = 1, + .pins = { config->sdcard_cd_gpio } + }; + struct acpi_dp *dp; + + if (!dev->enabled) + return; + + /* Use device path as the Scope for the SSDT */ + path = acpi_device_path(dev); + if (!path) + return; + if (!config->sdcard_cd_gpio) + return; + acpigen_write_scope(path); + acpigen_write_name("_CRS"); + + /* Write GpioInt() as default (if set) or custom from devicetree */ + acpigen_write_resourcetemplate_header(); + acpi_device_write_gpio(&default_gpio); + acpigen_write_resourcetemplate_footer(); + + /* Bind the cd-gpio name to the GpioInt() resource */ + dp = acpi_dp_new_table("_DSD"); + acpi_dp_add_gpio(dp, "cd-gpio", path, 0, 0, 1); + acpi_dp_write(dp); + + acpigen_pop_len(); +} +#endif + +static struct device_operations dev_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .ops_pci = &soc_pci_ops, +#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) + .acpi_fill_ssdt_generator = &sd_fill_ssdt, +#endif +}; + +static const struct pci_driver pch_sd __pci_driver = { + .ops = &dev_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x5aca +}; |