soc/amd/picasso: Update UARTs

Add a function to uart.c to ensure the right IOMux settings are
programmed for the console UART.  Update Kconfig to reflect the
new addresses.

Give the user the ability to downclock the UARTs' refclock to
1.8342MHz.

Add the abiltiy to use an APU UART at a legacy I/O address.

Update the AOAC register configuration for the two additional
UARTs.

Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Change-Id: I74579674544f0edd2c0e6c4963270b442668e62f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/33767
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Marshall Dawson 2019-06-20 10:29:29 -06:00 committed by Martin Roth
parent 0d441daef6
commit c0b8d0d5b5
8 changed files with 217 additions and 19 deletions

View File

@ -157,16 +157,46 @@ config PICASSO_UART
select NO_UART_ON_SUPERIO
select UART_OVERRIDE_REFCLK
help
There are two UART controllers in Picasso.
The UART registers are memory-mapped. UART
controller 0 registers range from FEDC_6000h
to FEDC_6FFFh. UART controller 1 registers
range from FEDC_8000h to FEDC_8FFFh.
There are four memory-mapped UARTs controllers in Picasso at:
0: 0xfedc9000
1: 0xfedca000
2: 0xfedc3000
3: 0xfedcf000
choice PICASSO_UART_CLOCK_SOURCE
prompt "UART Frequency"
depends on PICASSO_UART
default PICASSO_UART_48MZ
config PICASSO_UART_48MZ
bool "48 MHz clock"
help
Select this option for the most compatibility.
config PICASSO_UART_1_8MZ
bool "1.8432 MHz clock"
help
Select this option if an old payload or Linux ttyS0 arguments
require it.
endchoice
config PICASSO_UART_LEGACY
bool "Decode legacy I/O range"
depends on PICASSO_UART
help
Assign I/O 3F8, 2F8, etc. to a Picasso UART. Only a single UART may
decode legacy addresses and this option enables the one used for the
console. A UART accessed with I/O does not allow all the features
of MMIO. The MMIO decode is still present when this option is used.
config CONSOLE_UART_BASE_ADDRESS
depends on CONSOLE_SERIAL
depends on CONSOLE_SERIAL && PICASSO_UART
hex
default 0xfedc6000
default 0xfedc9000 if UART_FOR_CONSOLE = 0
default 0xfedca000 if UART_FOR_CONSOLE = 1
default 0xfedc3000 if UART_FOR_CONSOLE = 2
default 0xfedcf000 if UART_FOR_CONSOLE = 3
config SMM_TSEG_SIZE
hex

View File

@ -55,7 +55,10 @@ Field (GNVS, ByteAcc, NoLock, Preserve)
, 1,
UT0E, 1, // UART0, 11
UT1E, 1, // UART1, 12
, 14,
, 3,
UT2E, 1, // UART2, 16
, 9,
UT23, 1, // UART3, 26
ESPI, 1, // ESPI, 27
/* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */
Offset (0x100),

View File

@ -58,7 +58,8 @@ Device (FUR0)
Name (_CRS, ResourceTemplate()
{
IRQ (Edge, ActiveHigh, Exclusive) { 10 }
Memory32Fixed (ReadWrite, 0xFEDC6000, 0x2000)
Memory32Fixed (ReadWrite, APU_UART0_BASE, 0x1000)
Memory32Fixed (ReadWrite, APU_DMAC0_BASE, 0x1000)
})
Method (_STA, 0x0, NotSerialized)
{
@ -71,12 +72,44 @@ Device (FUR1) {
Name (_UID, 0x1)
Name (_CRS, ResourceTemplate()
{
IRQ (Edge, ActiveHigh, Exclusive) { 11 }
Memory32Fixed (ReadWrite, 0xFEDC8000, 0x2000)
IRQ (Edge, ActiveHigh, Exclusive) { 11 }
Memory32Fixed (ReadWrite, APU_UART1_BASE, 0x1000)
Memory32Fixed (ReadWrite, APU_DMAC1_BASE, 0x1000)
})
Method (_STA, 0x0, NotSerialized)
{
Return (0x0F)
Return (0x0F)
}
}
Device (FUR2)
{
Name (_HID, "AMD0020")
Name (_UID, 0x0)
Name (_CRS, ResourceTemplate()
{
IRQ (Edge, ActiveHigh, Exclusive) { 15 }
Memory32Fixed (ReadWrite, APU_UART2_BASE, 0x1000)
Memory32Fixed (ReadWrite, APU_DMAC2_BASE, 0x1000)
})
Method (_STA, 0x0, NotSerialized)
{
Return (0x0F)
}
}
Device (FUR3) {
Name (_HID, "AMD0020")
Name (_UID, 0x1)
Name (_CRS, ResourceTemplate()
{
IRQ (Edge, ActiveHigh, Exclusive) { 5 }
Memory32Fixed (ReadWrite, APU_UART3_BASE, 0x1000)
Memory32Fixed (ReadWrite, APU_DMAC3_BASE, 0x1000)
})
Method (_STA, 0x0, NotSerialized)
{
Return (0x0F)
}
}

View File

@ -236,9 +236,23 @@ Field( SMIC, ByteAcc, NoLock, Preserve) {
offset (0x1e59), /* UART1 D3 State */
U1DS, 3,
offset (0x1e60), /* UART2 D3 Control */
U2TD, 2,
, 1,
U2PD, 1,
offset (0x1e61), /* UART2 D3 State */
U2DS, 3,
offset (0x1e71), /* SD D3 State */
SDDS, 3,
offset (0x1e74), /* UART3 D3 Control */
U3TD, 2,
, 1,
U3PD, 1,
offset (0x1e75), /* UART3 D3 State */
U3DS, 3,
offset (0x1e80), /* Shadow Register Request */
, 15,
RQ15, 1,
@ -375,6 +389,22 @@ Method(FDDC, 2, Serialized)
Store(U1DS, Local0)
}
}
Case(16) {
Store(0x00, U2TD)
Store(One, U2PD)
Store(U2DS, Local0)
while(LNotEqual(Local0,0x7)) {
Store(U2DS, Local0)
}
}
Case(26) {
Store(0x00, U3TD)
Store(One, U3PD)
Store(U3DS, Local0)
while(LNotEqual(Local0,0x7)) {
Store(U3DS, Local0)
}
}
}
} else {
/* put device into D3cold */
@ -427,6 +457,22 @@ Method(FDDC, 2, Serialized)
}
Store(0x03, U1TD)
}
Case(16) {
Store(Zero, U2PD)
Store(U2DS, Local0)
while(LNotEqual(Local0,0x0)) {
Store(U2DS, Local0)
}
Store(0x03, U2TD)
}
Case(26) {
Store(Zero, U3PD)
Store(U3DS, Local0)
while(LNotEqual(Local0,0x0)) {
Store(U3DS, Local0)
}
Store(0x03, U3TD)
}
}
if(LEqual(I1TD, 3)) {
if(LEqual(I2TD, 3)) {

View File

@ -28,6 +28,7 @@
* any documentation but should be considered reserved through FED8_1FFFh.
*/
#include <amdblocks/acpimmio_map.h>
#define SUPPORTS_ACPIMMIO_SM_PCI_BASE 1 /* 0xfed80000 */
#define SUPPORTS_ACPIMMIO_SMI_BASE 1 /* 0xfed80100 */
#define SUPPORTS_ACPIMMIO_PMIO_BASE 1 /* 0xfed80300 */
#define SUPPORTS_ACPIMMIO_BIOSRAM_BASE 1 /* 0xfed80500 */
@ -60,8 +61,10 @@
#endif
#define HPET_BASE_ADDRESS 0xfed00000
#define APU_UART0_BASE 0xfedc6000
#define APU_UART1_BASE 0xfedc8000
#define APU_UART0_BASE 0xfedc9000
#define APU_UART1_BASE 0xfedca000
#define APU_UART2_BASE 0xfedce000
#define APU_UART3_BASE 0xfedcf000
#define FLASH_BASE_ADDR ((0xffffffff - CONFIG_ROM_SIZE) + 1)

View File

@ -28,6 +28,14 @@
* - fixed addresses offset from 0xfed80000
*/
/* SMBus controller registers: 0xfed80000 or D14F0 */
#define SMB_UART_CONFIG 0xfc
#define SMB_UART3_1_8M BIT(31) /* defaults are 0 = 48MHz */
#define SMB_UART2_1_8M BIT(30)
#define SMB_UART1_1_8M BIT(29)
#define SMB_UART0_1_8M BIT(28)
#define SMB_UART_1_8M_SHIFT 28
/* Power management registers: 0xfed80300 or index/data at IO 0xcd6/cd7 */
#define PM_DECODE_EN 0x00
#define SMBUS_ASF_IO_EN BIT(4)
@ -209,6 +217,7 @@
#define FCH_AOAC_DEV_UART1 12
#define FCH_AOAC_DEV_UART2 16
#define FCH_AOAC_DEV_AMBA 17
#define FCH_AOAC_DEV_UART3 26
#define FCH_AOAC_DEV_ESPI 27
/* Bit definitions for Device D3 Control AOACx0000[40...7E] step 2 */
@ -230,6 +239,11 @@
#define FCH_AOAC_STAT0 BIT(6)
#define FCH_AOAC_STAT1 BIT(7)
#define FCH_UART_LEGACY_DECODE 0xfedc0020
#define FCH_LEGACY_3F8_SH 3
#define FCH_LEGACY_2F8_SH 1
#define FCH_LEGACY_3E8_SH 2
#define PM1_LIMIT 16
#define GPE0_LIMIT 28
#define TOTAL_BITS(a) (8 * sizeof(a))
@ -294,7 +308,10 @@ typedef struct aoac_devs {
unsigned int :1;
unsigned int ut0e:1; /* 11: UART0 */
unsigned int ut1e:1; /* 12: UART1 */
unsigned int :14;
unsigned int :3;
unsigned int ut2e:1; /* 16: UART2 */
unsigned int :9;
unsigned int ut3e:1; /* 26: UART3 */
unsigned int espi:1; /* 27: ESPI */
unsigned int :4;
} __packed aoac_devs_t;
@ -317,6 +334,7 @@ void sb_read_mode(u32 mode);
void sb_set_spi100(u16 norm, u16 fast, u16 alt, u16 tpm);
void fch_pre_init(void);
void fch_early_init(void);
void set_uart_config(int idx);
/**
* @brief Save the UMA bize
*

View File

@ -40,6 +40,8 @@
#define FCH_AOAC_UART_FOR_CONSOLE \
(CONFIG_UART_FOR_CONSOLE == 0 ? FCH_AOAC_DEV_UART0 \
: CONFIG_UART_FOR_CONSOLE == 1 ? FCH_AOAC_DEV_UART1 \
: CONFIG_UART_FOR_CONSOLE == 2 ? FCH_AOAC_DEV_UART2 \
: CONFIG_UART_FOR_CONSOLE == 3 ? FCH_AOAC_DEV_UART3 \
: -1)
#if FCH_AOAC_UART_FOR_CONSOLE == -1
# error Unsupported UART_FOR_CONSOLE chosen
@ -282,6 +284,8 @@ void fch_pre_init(void)
sb_enable_legacy_io();
enable_aoac_devices();
sb_reset_i2c_slaves();
if (CONFIG(PICASSO_UART))
set_uart_config(CONFIG_UART_FOR_CONSOLE);
}
static void print_num_status_bits(int num_bits, uint32_t status,
@ -463,6 +467,8 @@ static void set_sb_final_nvs(void)
gnvs->aoac.ic4e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C4);
gnvs->aoac.ut0e = is_aoac_device_enabled(FCH_AOAC_DEV_UART0);
gnvs->aoac.ut1e = is_aoac_device_enabled(FCH_AOAC_DEV_UART1);
gnvs->aoac.ut2e = is_aoac_device_enabled(FCH_AOAC_DEV_UART2);
gnvs->aoac.ut3e = is_aoac_device_enabled(FCH_AOAC_DEV_UART3);
gnvs->aoac.espi = 1;
}

View File

@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Advanced Micro Devices, Inc.
* Copyright (C) 2019 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -13,18 +13,77 @@
* GNU General Public License for more details.
*/
#include <arch/mmio.h>
#include <console/uart.h>
#include <commonlib/helpers.h>
#include <amdblocks/gpio_banks.h>
#include <amdblocks/acpimmio.h>
#include <soc/southbridge.h>
#include <soc/gpio.h>
static const struct _uart_info {
uintptr_t base;
struct soc_amd_gpio mux[2];
} uart_info[] = {
[0] = { APU_UART0_BASE, {
PAD_NF(GPIO_138, UART0_TXD, PULL_NONE),
PAD_NF(GPIO_136, UART0_RXD, PULL_NONE),
} },
[1] = { APU_UART1_BASE, {
PAD_NF(GPIO_143, UART1_TXD, PULL_NONE),
PAD_NF(GPIO_141, UART1_RXD, PULL_NONE),
} },
[2] = { APU_UART2_BASE, {
PAD_NF(GPIO_137, UART2_TXD, PULL_NONE),
PAD_NF(GPIO_135, UART2_RXD, PULL_NONE),
} },
[3] = { APU_UART3_BASE, {
PAD_NF(GPIO_140, UART3_TXD, PULL_NONE),
PAD_NF(GPIO_142, UART3_RXD, PULL_NONE),
} },
};
uintptr_t uart_platform_base(int idx)
{
if (CONFIG_UART_FOR_CONSOLE < 0 || CONFIG_UART_FOR_CONSOLE > 1)
if (idx < 0 || idx > ARRAY_SIZE(uart_info))
return 0;
return (uintptr_t)(APU_UART0_BASE + 0x2000 * (idx & 1));
return uart_info[idx].base;
}
void set_uart_config(int idx)
{
uint32_t uart_ctrl;
uint16_t uart_leg;
if (idx < 0 || idx > ARRAY_SIZE(uart_info))
return;
program_gpios(uart_info[idx].mux, 2);
if (CONFIG(PICASSO_UART_1_8MZ)) {
uart_ctrl = sm_pci_read32(SMB_UART_CONFIG);
uart_ctrl |= 1 << (SMB_UART_1_8M_SHIFT + idx);
sm_pci_write32(SMB_UART_CONFIG, uart_ctrl);
}
if (CONFIG(PICASSO_UART_LEGACY) && idx != 3) {
/* Force 3F8 if idx=0, 2F8 if idx=1, 3E8 if idx=2 */
/* TODO: make clearer once PPR is updated */
uart_leg = (idx << 8) | (idx << 10) | (idx << 12) | (idx << 14);
if (idx == 0)
uart_leg |= 1 << FCH_LEGACY_3F8_SH;
else if (idx == 1)
uart_leg |= 1 << FCH_LEGACY_2F8_SH;
else if (idx == 2)
uart_leg |= 1 << FCH_LEGACY_3E8_SH;
write16((void *)FCH_UART_LEGACY_DECODE, uart_leg);
}
}
unsigned int uart_platform_refclk(void)
{
return 48000000;
return CONFIG(PICASSO_UART_48MZ) ? 48000000 : 115200 * 16;
}