/* This file is part of the coreboot project. */ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include #include #include #include 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]); } }