diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c index 9f57206b38..2adb76e2c4 100644 --- a/src/soc/intel/apollolake/acpi.c +++ b/src/soc/intel/apollolake/acpi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "chip.h" #define CSTATE_RES(address_space, width, offset, address) \ @@ -185,9 +186,13 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs) 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); + /* Get sdcard cd GPIO portid if GPIO is defined in devicetree. + * Get offset of sdcard cd pin. + */ + if (cfg->sdcard_cd_gpio) { + gnvs->scdp = gpio_get_pad_portid(cfg->sdcard_cd_gpio); + gnvs->scdo = gpio_acpi_pin(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 86a1a23fd6..bdba305081 100644 --- a/src/soc/intel/apollolake/acpi/globalnvs.asl +++ b/src/soc/intel/apollolake/acpi/globalnvs.asl @@ -39,8 +39,8 @@ 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 - + SCDP, 8, // 0x29 - SD_CD GPIO portid + SCDO, 8, // 0x2A - GPIO pad offset relative to the community /* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */ Offset (0x100), #include diff --git a/src/soc/intel/apollolake/acpi/gpiolib.asl b/src/soc/intel/apollolake/acpi/gpiolib.asl index cec6d36722..0acfb67016 100644 --- a/src/soc/intel/apollolake/acpi/gpiolib.asl +++ b/src/soc/intel/apollolake/acpi/gpiolib.asl @@ -64,4 +64,55 @@ Scope (\_SB) } Store (Arg1, TEMP) } + + /* Get DW0 address of a given pad */ + Method (GDW0, 0x2, Serialized) + { + /* Arg0 - GPIO portid */ + /* Arg1 - GPIO pad offset relative to the community */ + Store (0, Local1) + Or( Or (ShiftLeft (Arg0, 16), CONFIG_IOSF_BASE_ADDRESS), + Local1, Local1) + Or( Add (PAD_CFG_BASE, Multiply (Arg1, 8)), Local1, Local1) + Return (Local1) + } + + /* Calculate HOSTSW_REG address */ + Method (CHSA, 0x1, Serialized) + { + /* Arg0 - GPIO pad offset relative to the community */ + Add (HOSTSW_OWN_REG_BASE, Multiply (Divide (Arg0, 32), 4), Local1) + Return (Local1) + } + + /* Get Host ownership register of GPIO Community */ + Method (GHO, 0x2, Serialized) + { + /* Arg0 - GPIO portid */ + /* Arg1 - GPIO pad offset relative to the community */ + Store (CHSA (Arg1), Local1) + + OperationRegion (SHO0, SystemMemory, Or ( Or + (CONFIG_IOSF_BASE_ADDRESS, ShiftLeft (Arg0, 16)), Local1), 4) + Field (SHO0, AnyAcc, NoLock, Preserve) { + TEMP, 32 + } + Return (TEMP) + } + + /* Set Host ownership register of GPIO Community */ + Method (SHO, 0x3, Serialized) + { + /* Arg0 - GPIO portid */ + /* Arg1 - GPIO pad offset relative to the community */ + /* Arg2 - Value for Host own register */ + Store (CHSA (Arg1), Local1) + + OperationRegion (SHO0, SystemMemory, Or ( Or + (CONFIG_IOSF_BASE_ADDRESS, ShiftLeft (Arg0, 16)), Local1), 4) + Field (SHO0, AnyAcc, NoLock, Preserve) { + TEMP, 32 + } + Store (Arg2, TEMP) + } } diff --git a/src/soc/intel/apollolake/acpi/scs.asl b/src/soc/intel/apollolake/acpi/scs.asl index bb8b684ef3..5933d522c5 100644 --- a/src/soc/intel/apollolake/acpi/scs.asl +++ b/src/soc/intel/apollolake/acpi/scs.asl @@ -115,14 +115,32 @@ Scope (\_SB.PCI0) { Device (SDCD) { Name (_ADR, 0x001B0000) + Name (_S0W, 4) /* _S0W: S0 Device Wake State */ + Name (SCD0, 0) /* Store SD_CD DW0 address */ + + /* Set the host ownership of sdcard cd during kernel boot */ + Method (_INI, 0) + { + /* Check SDCard CD port is valid */ + If (LAnd (LNotEqual (\SCDP, 0), LNotEqual (\SCDO, 0) )) + { + /* Store DW0 address of SD_CD */ + Store (GDW0 (\SCDP, \SCDO), SCD0) + /* Get the current SD_CD ownership */ + Store (\_SB.GHO (\SCDP, \SCDO), Local0) + /* Set host ownership as GPIO in HOSTSW_OWN reg */ + Or (Local0, ShiftLeft (1, Mod (\SCDO, 32)), Local0) + \_SB.SHO (\SCDP, \SCDO, Local0) + } + } Method (_PS0, 0, NotSerialized) { - /* Check SDCard CD pin address is valid */ - If (LNotEqual (SCD0, 0)) + /* Check SDCard CD port is valid */ + If (LAnd (LNotEqual (\SCDP, 0), LNotEqual (\SCDO, 0) )) { /* Store DW0 into local0 to get rxstate of GPIO */ - Store (\_SB.GPC0 (\SCD0), Local0) + 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. diff --git a/src/soc/intel/apollolake/gpio.c b/src/soc/intel/apollolake/gpio.c index cb41925cd4..d9957726eb 100644 --- a/src/soc/intel/apollolake/gpio.c +++ b/src/soc/intel/apollolake/gpio.c @@ -186,6 +186,16 @@ void *gpio_dwx_address(const uint16_t pad) PAD_CFG_OFFSET(pad - comm->first_pad)); } +uint8_t gpio_get_pad_portid(const uint16_t pad) +{ + /* Get the port id of given pad + * pad - GPIO number + * returns - given pad port id + */ + const struct pad_community *comm = gpio_get_community(pad); + return comm->port; +} + void gpio_input_pulldown(gpio_t gpio) { struct pad_config cfg = PAD_CFG_GPI(gpio, DN_20K, DEEP); diff --git a/src/soc/intel/apollolake/include/soc/gpio.h b/src/soc/intel/apollolake/include/soc/gpio.h index bdd39944d1..f1020f630a 100644 --- a/src/soc/intel/apollolake/include/soc/gpio.h +++ b/src/soc/intel/apollolake/include/soc/gpio.h @@ -162,6 +162,10 @@ void gpio_configure_pads(const struct pad_config *cfg, size_t num_pads); /* Calculate GPIO DW0 address */ void *gpio_dwx_address(const uint16_t pad); + +/* Get the port id of given pad */ +uint8_t gpio_get_pad_portid(const uint16_t pad); + /* * Set the GPIO groups for the GPE blocks. The values from PMC register GPE_CFG * are passed which is then mapped to proper groups for MISCCFG. This basically diff --git a/src/soc/intel/apollolake/include/soc/nvs.h b/src/soc/intel/apollolake/include/soc/nvs.h index 21ac14e274..f9cc49d3ff 100644 --- a/src/soc/intel/apollolake/include/soc/nvs.h +++ b/src/soc/intel/apollolake/include/soc/nvs.h @@ -39,8 +39,9 @@ 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 */ - uint32_t scd0; /* 0x29 - 0x2D - SD_CD Address */ - uint8_t unused[211]; + uint8_t scdp; /* 0x29 - SD_CD GPIO portid */ + uint8_t scdo; /* 0x2A - GPIO pad offset relative to the community */ + uint8_t unused[213]; /* ChromeOS specific (0x100 - 0xfff) */ chromeos_acpi_t chromeos;