summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/apollolake/Makefile.inc1
-rw-r--r--src/soc/intel/apollolake/acpi.c4
-rw-r--r--src/soc/intel/apollolake/acpi/globalnvs.asl1
-rw-r--r--src/soc/intel/apollolake/acpi/scs.asl38
-rw-r--r--src/soc/intel/apollolake/chip.c14
-rw-r--r--src/soc/intel/apollolake/chip.h5
-rw-r--r--src/soc/intel/apollolake/include/soc/nvs.h3
-rw-r--r--src/soc/intel/apollolake/sd.c82
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
+};