/* SPDX-License-Identifier: GPL-2.0-only */ #include <assert.h> #include <console/uart.h> #include <device/mmio.h> #include <device/pci_def.h> #include <device/pci_ops.h> #include <southbridge/intel/lynxpoint/iobp.h> #include <southbridge/intel/lynxpoint/lp_gpio.h> #include <southbridge/intel/lynxpoint/pch.h> #include <types.h> static pci_devfn_t get_uart_pci_device(void) { switch (CONFIG_UART_FOR_CONSOLE) { case 0: return PCI_DEV(0, 0x15, 5); case 1: return PCI_DEV(0, 0x15, 6); default: return dead_code_t(pci_devfn_t); } } /* TODO: Figure out if all steps are actually necessary */ void uart_bootblock_init(void) { const pci_devfn_t dev = get_uart_pci_device(); /* Program IOBP GPIODF */ pch_iobp_update(SIO_IOBP_GPIODF, ~0x131f, 0x131f); /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */ pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f); /* Set and enable MMIO BAR */ pci_write_config32(dev, PCI_BASE_ADDRESS_0, CONFIG_CONSOLE_UART_BASE_ADDRESS); pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); void *const bar = (void *)(uintptr_t)CONFIG_CONSOLE_UART_BASE_ADDRESS; /* Initialize LTR */ clrbits32(bar + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_LTR_MODE_MASK); clrbits32(bar + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT); /* Take UART out of reset */ setbits32(bar + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT); /* Set M and N divisor inputs and enable clock */ uint32_t ppr_clock = 0; ppr_clock |= SIO_REG_PPR_CLOCK_EN; ppr_clock |= SIO_REG_PPR_CLOCK_UPDATE; ppr_clock |= SIO_REG_PPR_CLOCK_N_DIV << 16; ppr_clock |= SIO_REG_PPR_CLOCK_M_DIV << 1; write32(bar + SIO_REG_PPR_CLOCK, ppr_clock); }