blob: 06f83fcbefb069b317475529c5724cb7661979e3 [file] [log] [blame]
Angel Ponsaced1f02021-04-18 23:57:21 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
Angel Ponsaced1f02021-04-18 23:57:21 +02003#include <assert.h>
4#include <console/uart.h>
Elyes Haouas8823ba12022-12-05 08:48:50 +01005#include <device/mmio.h>
Angel Ponsaced1f02021-04-18 23:57:21 +02006#include <device/pci_def.h>
7#include <device/pci_ops.h>
8#include <southbridge/intel/lynxpoint/iobp.h>
9#include <southbridge/intel/lynxpoint/lp_gpio.h>
10#include <southbridge/intel/lynxpoint/pch.h>
11#include <types.h>
12
13static pci_devfn_t get_uart_pci_device(void)
14{
15 switch (CONFIG_UART_FOR_CONSOLE) {
16 case 0: return PCI_DEV(0, 0x15, 5);
17 case 1: return PCI_DEV(0, 0x15, 6);
18 default: return dead_code_t(pci_devfn_t);
19 }
20}
21
22/* TODO: Figure out if all steps are actually necessary */
23void uart_bootblock_init(void)
24{
25 const pci_devfn_t dev = get_uart_pci_device();
26
27 /* Program IOBP GPIODF */
28 pch_iobp_update(SIO_IOBP_GPIODF, ~0x131f, 0x131f);
29
30 /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
31 pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
32
33 /* Set and enable MMIO BAR */
34 pci_write_config32(dev, PCI_BASE_ADDRESS_0, CONFIG_CONSOLE_UART_BASE_ADDRESS);
35 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
36
37 void *const bar = (void *)(uintptr_t)CONFIG_CONSOLE_UART_BASE_ADDRESS;
38
39 /* Initialize LTR */
40 clrbits32(bar + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_LTR_MODE_MASK);
41 clrbits32(bar + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
42
43 /* Take UART out of reset */
44 setbits32(bar + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
45
46 /* Set M and N divisor inputs and enable clock */
47 uint32_t ppr_clock = 0;
48 ppr_clock |= SIO_REG_PPR_CLOCK_EN;
49 ppr_clock |= SIO_REG_PPR_CLOCK_UPDATE;
50 ppr_clock |= SIO_REG_PPR_CLOCK_N_DIV << 16;
51 ppr_clock |= SIO_REG_PPR_CLOCK_M_DIV << 1;
52 write32(bar + SIO_REG_PPR_CLOCK, ppr_clock);
53}