xref: /aosp_15_r20/external/coreboot/src/southbridge/intel/lynxpoint/uart_init.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/uart.h>
5 #include <device/mmio.h>
6 #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 
get_uart_pci_device(void)13 static 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 */
uart_bootblock_init(void)23 void 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 }
54