summaryrefslogtreecommitdiff
path: root/src/southbridge/intel/lynxpoint/uart_init.c
blob: 5048e5d5455f5107e6f88834c1b8f65106ec2b58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/* SPDX-License-Identifier: GPL-2.0-only */

#include <arch/io.h>
#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);
}