amd/stoneyridge: Create new wide IO functions

Create new generic wide IO functions in southbridge.c. These new
functions must be usable by kahlee/ec.c and amd/stoneyridge/lpc.c.

BUG=b:64033893
TEST=Just build at this stage, full boot to OS and verify serial output
at related change 14fdd03a83. Some extra outputs for testing removed
when code was committed.

Change-Id: Icd0841a1959f3e109b3c35fa35bb4b3c44099dc3
Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-on: https://review.coreboot.org/22590
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Richard Spiegel 2017-11-24 07:47:42 -07:00 committed by Martin Roth
parent 903472c3c8
commit ebf3aa8c63
2 changed files with 150 additions and 0 deletions

View File

@ -290,6 +290,9 @@
#define OC_PORT2_SHIFT 8
#define OC_PORT3_SHIFT 12
#define WIDEIO_RANGE_ERROR -1
#define TOTAL_WIDEIO_PORTS 3
static inline int sb_sata_enable(void)
{
/* True if IDE or AHCI. */
@ -343,6 +346,32 @@ uint32_t xhci_pm_read32(uint8_t reg);
int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos);
int s3_save_nvram_early(u32 dword, int size, int nvram_pos);
void bootblock_fch_early_init(void);
/**
* @brief Find the size of a particular wide IO
*
* @param index = index of desired wide IO
*
* @return size of desired wide IO
*/
uint16_t sb_wideio_size(int index);
/**
* @brief Identify if any LPC wide IO is covering the IO range
*
* @param start = start of IO range
* @param size = size of IO range
*
* @return Index of wide IO covering the range or error
*/
int sb_find_wideio_range(uint16_t start, uint16_t size);
/**
* @brief Program a LPC wide IO to support an IO range
*
* @param start = start of range to be routed through wide IO
* @param size = size of range to be routed through wide IO
*
* @return Index of wide IO register used or error
*/
int sb_set_wideio_range(uint16_t start, uint16_t size);
/*
* Call the mainboard to get the USB Over Current Map. The mainboard

View File

@ -82,12 +82,133 @@ const static struct irq_idx_name irq_association[] = {
{ PIRQ_UART1, "UART1\t" },
};
/*
* Structure to simplify code obtaining the total of used wide IO
* registers and the size assigned to each.
*/
static struct wide_io_ioport_and_bits {
uint32_t enable;
uint16_t port;
uint8_t alt;
} wio_io_en[TOTAL_WIDEIO_PORTS] = {
{
LPC_WIDEIO0_ENABLE,
LPC_WIDEIO_GENERIC_PORT,
LPC_ALT_WIDEIO0_ENABLE
},
{
LPC_WIDEIO1_ENABLE,
LPC_WIDEIO1_GENERIC_PORT,
LPC_ALT_WIDEIO1_ENABLE
},
{
LPC_WIDEIO2_ENABLE,
LPC_WIDEIO2_GENERIC_PORT,
LPC_ALT_WIDEIO2_ENABLE
}
};
const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
{
*size = ARRAY_SIZE(irq_association);
return irq_association;
}
/**
* @brief Find the size of a particular wide IO
*
* @param index = index of desired wide IO
*
* @return size of desired wide IO
*/
uint16_t sb_wideio_size(int index)
{
uint32_t enable_register;
uint16_t size = 0;
uint8_t alternate_register;
if (index >= TOTAL_WIDEIO_PORTS)
return size;
enable_register = pci_read_config32(SOC_LPC_DEV,
LPC_IO_OR_MEM_DECODE_ENABLE);
alternate_register = pci_read_config8(SOC_LPC_DEV,
LPC_ALT_WIDEIO_RANGE_ENABLE);
if (enable_register & wio_io_en[index].enable)
size = (alternate_register & wio_io_en[index].alt) ?
16 : 512;
return size;
}
/**
* @brief Identify if any LPC wide IO is covering the IO range
*
* @param start = start of IO range
* @param size = size of IO range
*
* @return Index of wide IO covering the range or error
*/
int sb_find_wideio_range(uint16_t start, uint16_t size)
{
uint32_t enable_register;
int i, index = WIDEIO_RANGE_ERROR;
uint16_t end, current_size, start_wideio, end_wideio;
end = start + size;
enable_register = pci_read_config32(SOC_LPC_DEV,
LPC_IO_OR_MEM_DECODE_ENABLE);
for (i = 0; i < TOTAL_WIDEIO_PORTS; i++) {
current_size = sb_wideio_size(i);
if (current_size == 0)
continue;
start_wideio = pci_read_config16(SOC_LPC_DEV,
wio_io_en[i].port);
end_wideio = start_wideio + current_size;
if ((start >= start_wideio) && (end <= end_wideio)) {
index = i;
break;
}
}
return index;
}
/**
* @brief Program a LPC wide IO to support an IO range
*
* @param start = start of range to be routed through wide IO
* @param size = size of range to be routed through wide IO
*
* @return Index of wide IO register used or error
*/
int sb_set_wideio_range(uint16_t start, uint16_t size)
{
int i, index = WIDEIO_RANGE_ERROR;
uint32_t enable_register;
uint8_t alternate_register;
enable_register = pci_read_config32(SOC_LPC_DEV,
LPC_IO_OR_MEM_DECODE_ENABLE);
alternate_register = pci_read_config8(SOC_LPC_DEV,
LPC_ALT_WIDEIO_RANGE_ENABLE);
for (i = 0; i < TOTAL_WIDEIO_PORTS; i++) {
if (enable_register & wio_io_en[i].enable)
continue;
index = i;
pci_write_config16(SOC_LPC_DEV, wio_io_en[i].port, start);
enable_register |= wio_io_en[i].enable;
pci_write_config32(SOC_LPC_DEV, LPC_IO_OR_MEM_DECODE_ENABLE,
enable_register);
if (size <= 16)
alternate_register |= wio_io_en[i].alt;
else
alternate_register &= ~wio_io_en[i].alt;
pci_write_config8(SOC_LPC_DEV,
LPC_ALT_WIDEIO_RANGE_ENABLE,
alternate_register);
break;
}
return index;
}
void configure_stoneyridge_uart(void)
{
u8 byte, byte2;