blob: ea99051fb679bbdee0974e122feab0ad9992c46e [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <commonlib/helpers.h>
#include <device/mmio.h>
#include <device/pci_ops.h>
#include <device/pci_def.h>
#include <fsp/soc_binding.h>
#include <gpio.h>
#include <soc/bootblock.h>
#include <soc/uart.h>
static uint16_t legacy_uart_ioadr_tab[] = {0x3F8, 0x2F8, 0x3E8, 0x2E8};
#define ELEM_OF_UART_TAB ARRAY_SIZE(legacy_uart_ioadr_tab)
static void pci_early_hsuart_device_probe(u8 bus, u8 dev, u8 func,
u32 mmio_base)
{
register uint16_t reg16;
pci_devfn_t uart_dev = PCI_DEV(bus, dev, func);
/* We're using MMIO for HSUARTs. This section is needed for logging
* from FSP only
*/
/* Decode IOBASE at IOBA (BAR0). */
reg16 = pci_read_config16(uart_dev, PCI_BASE_ADDRESS_0) | mmio_base;
pci_write_config16(uart_dev, PCI_BASE_ADDRESS_0, reg16);
#if (CONFIG(NON_LEGACY_UART_MODE))
/* Decode MMIO at MEMBA (BAR1) */
pci_write_config32(uart_dev, PCI_BASE_ADDRESS_1,
CONFIG_CONSOLE_UART_BASE_ADDRESS +
SIZE_OF_HSUART_RES * func);
#endif
/* Enable memory/io space and allow to initiate
* a transaction as a master
*/
pci_write_config16(uart_dev, PCI_COMMAND,
pci_read_config16(uart_dev, PCI_COMMAND) |
#if (CONFIG(NON_LEGACY_UART_MODE))
PCI_COMMAND_MEMORY |
#endif
PCI_COMMAND_MASTER | PCI_COMMAND_IO);
#if (CONFIG(CONSOLE_SERIAL_230400))
/* Change the highest speed to 230400 */
uint32_t *psr_reg =
(uint32_t *)(CONFIG_CONSOLE_UART_BASE_ADDRESS +
SIZE_OF_HSUART_RES * func + PSR_OFFSET);
*psr_reg >>= 1;
#endif
}
static void early_config_gpio(void)
{
uint32_t reg32;
// HSUART0:
// UART0_RXD
reg32 = read32(
(void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART0_RXD));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_1) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_UART0_RXD),
reg32);
}
// UART0_TXD
reg32 = read32(
(void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART0_TXD));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_1) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_UART0_TXD),
reg32);
}
// UART0_CTS
reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_SMB3_CLTT_CLK));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_2) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_2
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_SMB3_CLTT_CLK),
reg32);
}
// UART0_RTS
reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_PCIE_CLKREQ5_N));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_3) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_3
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_PCIE_CLKREQ5_N),
reg32);
}
// HSUART1:
// UART1_RXD
reg32 = read32(
(void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART1_RXD));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_1) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_UART1_RXD),
reg32);
}
// UART1_TXD
reg32 = read32(
(void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART1_TXD));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_1) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_UART1_TXD),
reg32);
}
// UART1_CTS
reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_SATA1_SDOUT));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_1) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_SATA1_SDOUT),
reg32);
}
// UART1_RTS
reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_SATA0_SDOUT));
if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
V_PCH_GPIO_PAD_MODE_NAT_1) {
reg32 &= ~B_PCH_GPIO_PAD_MODE;
reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
<< N_PCH_GPIO_PAD_MODE);
write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
R_PAD_CFG_DW0_SATA0_SDOUT),
reg32);
}
}
void early_uart_init(void)
{
register int i;
/* Check: do we have enough elements to init. ? */
BUILD_BUG_ON(DENVERTON_UARTS_TO_INI > ELEM_OF_UART_TAB);
/* HSUART(B0:D26:0-1) GPIO init. */
early_config_gpio();
for (i = DENVERTON_UARTS_TO_INI - 1; i >= 0; --i) {
pci_early_hsuart_device_probe(0, CONFIG_HSUART_DEV, i,
legacy_uart_ioadr_tab[i]);
}
}