diff --git a/src/soc/intel/skylake/include/soc/gpio.h b/src/soc/intel/skylake/include/soc/gpio.h index efc666f4cd..03ed11988d 100644 --- a/src/soc/intel/skylake/include/soc/gpio.h +++ b/src/soc/intel/skylake/include/soc/gpio.h @@ -257,6 +257,18 @@ typedef struct { .owner = GPIO_OWNER_GPIO, \ .conf1 = GPIO_SENSE_DISABLE } +/* Number of pins used by SerialIo controllers */ +#define PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER 4 +#define PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL 2 + +/* Below defines are based on GPIO_CONFIG structure fields */ +#define GPIO_CONF_PAD_MODE_MASK 0xF +#define GPIO_CONF_PAD_MODE_BIT_POS 0 + +/* GPIO Pad Mode */ +#define B_PCH_GPIO_PAD_MODE (0x1000 | 0x800 | 0x400) +#define N_PCH_GPIO_PAD_MODE 10 + struct gpio_config { u8 gpio; u32 conf0; diff --git a/src/soc/intel/skylake/romstage/uart.c b/src/soc/intel/skylake/romstage/uart.c index 8aa1053150..c53643abc6 100644 --- a/src/soc/intel/skylake/romstage/uart.c +++ b/src/soc/intel/skylake/romstage/uart.c @@ -25,6 +25,9 @@ #include #include #include +#include + +static void uartgpioinit(u8 hwflowcontrol); void pch_uart_init(void) { @@ -32,7 +35,7 @@ void pch_uart_init(void) u32 tmp; u8 *base = (u8 *)CONFIG_TTYS0_BASE; - /* Set configured UART base address */ + /* Set configured UART2 base address */ pci_write_config32(dev, PCI_BASE_ADDRESS_0, (u32)base); /* Enable memory access and bus master */ @@ -40,7 +43,7 @@ void pch_uart_init(void) tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config32(dev, PCI_COMMAND, tmp); - /* Take UART out of reset */ + /* Take UART2 out of reset */ tmp = read32(base + SIO_REG_PPR_RESETS); tmp |= SIO_REG_PPR_RESETS_FUNC | SIO_REG_PPR_RESETS_APB | SIO_REG_PPR_RESETS_IDMA; @@ -56,4 +59,61 @@ void pch_uart_init(void) /* Put UART2 in byte access mode for 16550 compatibility */ pcr_andthenor32(PID_SERIALIO, R_PCH_PCR_SERIAL_IO_GPPRVRW7, 0, SIO_PCH_LEGACY_UART2); + + /* Configure GPIO for UART2 in native mode*/ + uartgpioinit(FALSE); +} + +/* + * GPIO modes + */ +typedef struct { + GPIO_PAD pad; + GPIO_PAD_MODE mode; +} GPIO_PAD_NATIVE_FUNCTION; + +/* + * GPP_C Community for UART2 GPIO + * pin order RXD/TXD/RTSB/CTSB + */ +static const GPIO_PAD_NATIVE_FUNCTION uartgpio[] = { + {GPIO_LP_GPP_C20, GpioPadModeNative1}, + {GPIO_LP_GPP_C21, GpioPadModeNative1}, + {GPIO_LP_GPP_C22, GpioPadModeNative1}, + {GPIO_LP_GPP_C23, GpioPadModeNative1} +}; + +/* + * GPIO config registers + */ +static const GPIO_GROUP_INFO gpio_group_info = { + PID_GPIOCOM1, + R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET, + V_PCH_GPIO_GPP_C_PAD_MAX, + R_PCH_PCR_GPIO_GPP_C_SMI_STS, + R_PCH_PCR_GPIO_GPP_C_SMI_EN +}; + +static void uartgpioinit(u8 hwflowcontrol) +{ + u32 index, pinsused, dw0reg, dw0regmask, padcfgreg, padnumber; + + if (hwflowcontrol) + pinsused = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER; + else + pinsused = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL; + + for (index = 0; index < pinsused; index++) { + padnumber = GPIO_GET_PAD_NUMBER(uartgpio[index].pad); + padcfgreg = 0x8 * padnumber + gpio_group_info.padcfgoffset; + dw0regmask = (uartgpio[index].mode & GPIO_CONF_PAD_MODE_MASK) + >> GPIO_CONF_PAD_MODE_BIT_POS; + dw0regmask = (GpioHardwareDefault == dw0regmask) ? + 0x0 : B_PCH_GPIO_PAD_MODE; + dw0reg = (((uartgpio[index].mode & GPIO_CONF_PAD_MODE_MASK) >> + (GPIO_CONF_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE); + + pcr_andthenor32(gpio_group_info.community, padcfgreg, + ~(u32)dw0regmask, (u32)dw0reg); + } }