Add support for RCS Arctic Tern and Sparrowhawk platforms

parent 3c4cfe74
Pipeline #251 passed with stage
in 19 seconds
......@@ -98,7 +98,7 @@ ppc64le_add_executable(${PROJECT_NAME}
)
ppc64le_linker_script(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld")
target_link_libraries(${PROJECT_NAME} PRIVATE libbase)
target_link_libraries(${PROJECT_NAME} PRIVATE "--defsym=STACK_SIZE=4096")
target_link_libraries(${PROJECT_NAME} PRIVATE "--defsym=STACK_SIZE=3072")
target_compile_definitions(${PROJECT_NAME} PRIVATE "-DNO_FLINT") # Disable linting
format_target_sources(${PROJECT_NAME})
......
......@@ -63,7 +63,7 @@ SECTIONS
. = ALIGN(8);
_ebss = .;
_end = .;
} > sram
} > main_ram
.stack ALIGN(8) (NOLOAD):
{
......
// © 2020 - 2021 Raptor Engineering, LLC
// © 2020 - 2022 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
#ifndef PLATFORM_VERSA_ECP5
#define PLATFORM_VERSA_ECP5 1
#endif
#ifndef PLATFORM_SPARROWHAWK
#define PLATFORM_SPARROWHAWK 0
#endif
#ifndef PLATFORM_ARCTIC_TERN
#define PLATFORM_ARCTIC_TERN 0
#endif
// Configuration sanity checks
#if (PLATFORM_VERSA_ECP5)
#if (PLATFORM_SPARROWHAWK || PLATFORM_ARCTIC_TERN)
#error Invalid platform configuration
#endif
#endif
#if (PLATFORM_SPARROWHAWK)
#if (PLATFORM_VERSA_ECP5 || PLATFORM_ARCTIC_TERN)
#error Invalid platform configuration
#endif
#endif
#if (PLATFORM_ARCTIC_TERN)
#if (PLATFORM_VERSA_ECP5 || PLATFORM_SPARROWHAWK)
#error Invalid platform configuration
#endif
#endif
// Platform specific global configuration
#if (PLATFORM_VERSA_ECP5)
#define CPU0_I2C_MASTER_BASE_ADDR I2CMASTER1_BASE
#define CPU1_I2C_MASTER_BASE_ADDR I2CMASTER2_BASE
#define P9PS_I2C_MASTER_BASE_ADDR I2CMASTER4_BASE
#define WITH_DRAM 1
#endif
#if (PLATFORM_SPARROWHAWK)
#define CPU0_I2C_MASTER_BASE_ADDR I2CMASTER1_BASE
#define CPU1_I2C_MASTER_BASE_ADDR I2CMASTER2_BASE
#define P9PS_I2C_MASTER_BASE_ADDR I2CMASTER4_BASE
#define HDMI_I2C_MASTER_BASE_ADDR I2CMASTER6_BASE
#define WITH_DRAM 0 // Sparrowhawk EC 1.00 does not have functional DDR3 DRAM
#endif
#if (PLATFORM_ARCTIC_TERN)
#define CPU0_I2C_MASTER_BASE_ADDR I2CMASTER0_BASE
#define CPU1_I2C_MASTER_BASE_ADDR I2CMASTER1_BASE
#define P9PS_I2C_MASTER_BASE_ADDR I2CMASTER4_BASE
#define HDMI_I2C_MASTER_BASE_ADDR I2CMASTER4_BASE
#define WITH_DRAM 1
#endif
#define WITH_SPI 1
#include "fsi.h"
......@@ -31,11 +84,12 @@
#define ENABLE_LPC_FW_CYCLE_IRQ_HANDLER 1 // Set to 1 to enable LPC master transfer interrupts to the BMC soft core
#define ENABLE_LPC_FW_CYCLE_DMA 1 // Set to 1 to allow the LPC master to DMA data to/from the Wishbone bus (not compatible with direct SPI access)
#define ALLOW_SPI_QUAD_MODE 1 // Set to 1 to allow quad-mode SPI transfers if the hardware supports them
#define WITH_DRAM 1 // Set to 1 to enable the use of attached external DRAM (fast IPL, needs a minimum of 64MB DRAM)
#define ALLOW_FLASH_WRITES 0 // Allow writes to PNOR Flash device
// Debug knobs
#define DEBUG_HOST_SPI_FLASH_READ 0 // Set to 1 to enable verbose logging of SPI flash read process
#define SPI_FLASH_TRIPLE_READ 0 // Set to 1 to enable triple-read data checks (slow)
#define ENABLE_LPC_FW_CYCLE_NONCONTIGUOUS_DEBUG 0 // Set to 1 to print a message whenever a non-sequential LPC read is detected
// General RCS platform registers
#define HOST_PLATFORM_FPGA_I2C_REG_STATUS 0x7
......@@ -43,6 +97,7 @@
// Host platform configuration
#define HOST_PLATFORM_FPGA_I2C_ADDRESS 0x31
#define HDMI_TRANSCEIVER_I2C_ADDRESS 0x4c
uint8_t host_flash_write_buffer[FLASH_MAX_WR_WINDOW_BYTES];
......@@ -120,9 +175,10 @@ typedef struct
uint8_t vdn_smbus_addr;
} cpu_info_t;
static const cpu_info_t g_cpu_info[] = {
#ifdef CPU0_I2C_MASTER_BASE_ADDR
{
.index = 0,
.i2c_master = (uint8_t *)I2CMASTER1_BASE,
.i2c_master = (uint8_t *)CPU0_I2C_MASTER_BASE_ADDR,
.i2c_frequency = 100000,
.vdd_regulator_addr = 0x70,
.vdd_regulator_page = 0x00,
......@@ -134,10 +190,11 @@ static const cpu_info_t g_cpu_info[] = {
.vdn_smbus_addr = 0x2b,
},
#ifdef I2CMASTER2_BASE
#endif
#ifdef CPU1_I2C_MASTER_BASE_ADDR
{
.index = 1,
.i2c_master = (uint8_t *)I2CMASTER2_BASE,
.i2c_master = (uint8_t *)CPU1_I2C_MASTER_BASE_ADDR,
.i2c_frequency = 100000,
.vdd_regulator_addr = 0x70,
.vdd_regulator_page = 0x00,
......@@ -262,6 +319,7 @@ static void reboot(void)
ctrl_reset_write(1);
}
#if (PLATFORM_VERSA_ECP5)
static void display_character(char character, int dp)
{
uint16_t value;
......@@ -307,24 +365,151 @@ static void display_character(char character, int dp)
gpio3_out_write(~(value | ((dp == 0) ? 0x0000 : 0x4000)));
}
static void set_led_bank_display(uint8_t bitfield)
static void set_led_bank_display(uint16_t value)
{
uint8_t bitfield;
// Convert POST code to 8 bit value
bitfield = 0;
bitfield |= ((value >> 8) & 0xf) << 4;
bitfield |= value & 0xf;
gpio1_out_write(~bitfield);
}
static void gpio_init(void)
{
// Set up discrete LED bank
set_led_bank_display(0x00);
set_led_bank_display(0x0000);
gpio1_oe_write(0xff);
}
#endif
#if (PLATFORM_SPARROWHAWK)
static void display_character(char character, int dp)
{
// Not available on Sparrowhawk
}
static void set_led_bank_display(uint16_t value)
{
// FIXME
// Display value on LEDs attached to platform control FPGA
}
static void gpio_init(void)
{
// Set up GPIO 1
// BMC_FP_ID_BTN | PM_CP0_ATTENTION_B | BMC_INTRUDER_N | SYS_PWROK_BUF | DBG_FSI0_EN | BP_SYSRESET_N | BMC_BOOT_PHASE | BMC_POWER_UP
gpio1_out_write(gpio1_out_read() & ~0x01); // Set platform power request to 0
gpio1_out_write(gpio1_out_read() | 0x08); // Disable FSI secure mode
gpio1_out_write(gpio1_out_read() | 0x02); // Set BMC boot phase to 1
gpio1_oe_write(0x0b);
}
#endif
#if (PLATFORM_ARCTIC_TERN)
static void display_character(char character, int dp)
{
uint8_t value;
// Convert digit to hex value
value = ((uint8_t)character) - 0x30;
// Display value on the upper segment of the alphanumeric LED display
gpio2_out_write((gpio2_out_read() & ~(0xf << 12)) | ((value & 0xf) << 12));
}
static void set_led_bank_display(uint16_t value)
{
uint16_t display_value;
// Convert POST code to 12 bit value
display_value = 0;
display_value |= ((value >> 8) & 0xff) << 4;
display_value |= value & 0xf;
// Display value on the lower three segments of the alphanumeric LED display
gpio2_out_write((gpio2_out_read() & ~0xfff) | (display_value & 0xfff));
}
static void gpio_init(void)
{
// Disable LPC clock buffer
gpio1_out_write(gpio1_out_read() & ~(0x01 << 12));
gpio1_oe_write(gpio1_oe_read() | (0x01 << 12));
}
#endif
#if (PLATFORM_SPARROWHAWK || PLATFORM_ARCTIC_TERN)
static void configure_hdmi_transceiver(uint8_t *i2c_master_base_addr)
{
// ***** Set up the ITE HDMI transceiver *****
printf("Setting up HDMI transceiver...");
// ***** GENERAL *****
// Reset device
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x4, 0x1c);
// ***** VIDEO *****
// Set bank 0
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x0f, 0x08); // 0x0f[1:0] = 0
// AVMute output
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0xc1, 0x01); // 0xc1[0] = 1
// Take device out of reset
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x04, 0x00);
// Enable HDMI transmitter reset
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x61, 0x10);
// Configure input signal
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x70,
0x00); // RGB mode, I/O latch at TxClk, non-CCIR656, non-embedded sync, single edge, no PCLK delay
i2c_write_register_byte(
i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x90,
0x00); // PG horizontal total = 0, H/V sync provided by external driver, active low VSYNC, active low HSYNC, Data Enable provided by external driver
// Enable DVI mode (works for HDMI as well, host should configure HDMI later in the boot process)
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0xc0, 0x00); // 0xc0[0] = 0
// Release HDMI transmitter reset
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0x61, 0x00); // 0x61[4] = 0
// Un-AVMute output
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0xc1, 0x00); // 0xc1[0] = 0
// ***** AUDIO *****
// Disable audio channel
i2c_write_register_byte(i2c_master_base_addr, HDMI_TRANSCEIVER_I2C_ADDRESS, 0xe0, 0x08); // 0xe0[3:0] = 0
printf("done!\n");
}
#endif
#if (PLATFORM_SPARROWHAWK)
static void sparrowhawk_base_platform_init(void)
{
#ifdef P9PS_I2C_MASTER_BASE_ADDR
uint8_t byte;
// ***** Set up the platform control FPGA *****
// Set up alphanumeric display
gpio3_out_write(0xefff);
gpio3_oe_write(0xefff);
printf("Setting up platform control FPGA...");
// Set HDD LED to inverted mode for NVMe drives
byte = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x11, NULL);
byte |= 0x03;
i2c_write_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x11, byte);
printf("done!\n");
#endif
}
#endif
static void set_lpc_slave_irq_enable(uint8_t enabled)
{
#ifdef HOSTLPCSLAVE_BASE
if (!enabled)
{
hostlpcslave_ev_enable_write(0);
......@@ -339,10 +524,12 @@ static void set_lpc_slave_irq_enable(uint8_t enabled)
hostlpcslave_ev_enable_write(AQUILA_EV_MASTER_IRQ);
irq_setmask(irq_getmask() | (1 << HOSTLPCSLAVE_INTERRUPT));
}
#endif
}
void lpc_slave_isr(void)
{
#ifdef HOSTLPCSLAVE_BASE
#if (ENABLE_LPC_FW_CYCLE_IRQ_HANDLER)
int byte;
int word;
......@@ -387,6 +574,9 @@ void lpc_slave_isr(void)
// Limit firmware address to 64MB (wrap around)
address &= 0x3ffffff;
// Show address lower bytes on display for debugging
// gpio2_out_write((address >> 8) & 0xffff);
physical_flash_address = address;
if ((address >= hiomap_config.window_start_address) && ((address - hiomap_config.window_start_address) < hiomap_config.window_length_bytes))
{
......@@ -585,14 +775,17 @@ void lpc_slave_isr(void)
}
hostlpcslave_ev_pending_write(AQUILA_EV_MASTER_IRQ);
#endif
}
uint8_t uart_register_bank[8];
static uint8_t ipmi_bt_transaction_state;
#if (WITH_SPI)
static void configure_flash_write_enable(uint8_t enable_writes)
{
#ifdef HOSTSPIFLASHCFG_BASE
// Set user mode
write_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1,
read_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1) |
......@@ -613,10 +806,13 @@ static void configure_flash_write_enable(uint8_t enable_writes)
write_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1,
read_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1) &
~(TERCEL_SPI_ENABLE_USER_MODE_MASK << TERCEL_SPI_ENABLE_USER_MODE_SHIFT));
#endif
}
#if (ALLOW_FLASH_WRITES)
static uint8_t read_flash_flag_status_register(void)
{
#ifdef HOSTSPIFLASHCFG_BASE
uint8_t flag_status = 0;
// Set user mode
......@@ -636,10 +832,15 @@ static uint8_t read_flash_flag_status_register(void)
~(TERCEL_SPI_ENABLE_USER_MODE_MASK << TERCEL_SPI_ENABLE_USER_MODE_SHIFT));
return flag_status;
#else
return 0;
#endif
}
#endif
static void reset_flash_device(void)
{
#ifdef HOSTSPIFLASHCFG_BASE
// Set user mode
write_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1,
read_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1) |
......@@ -665,10 +866,12 @@ static void reset_flash_device(void)
write_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1,
read_tercel_register(HOSTSPIFLASHCFG_BASE, TERCEL_SPI_REG_SYS_CORE_CTL1) &
~(TERCEL_SPI_ENABLE_USER_MODE_MASK << TERCEL_SPI_ENABLE_USER_MODE_SHIFT));
#endif
}
static void configure_flash_device(void)
{
#ifdef HOSTSPIFLASHCFG_BASE
uint8_t config_byte;
// Set user mode
......@@ -708,10 +911,13 @@ static void configure_flash_device(void)
~(TERCEL_SPI_ENABLE_USER_MODE_MASK << TERCEL_SPI_ENABLE_USER_MODE_SHIFT));
configure_flash_write_enable(0);
#endif
}
#if (ALLOW_FLASH_WRITES)
static void erase_flash_subsector(uint32_t address)
{
#ifdef HOSTSPIFLASHCFG_BASE
// Limit Flash address to active memory
address = address & 0x0fffffff;
......@@ -743,10 +949,14 @@ static void erase_flash_subsector(uint32_t address)
{
// Wait for pending operation to complete
}
#endif
}
#endif
#endif
static int write_data_to_flash(uint8_t *write_buffer, uint32_t bytes, uint32_t flash_offset, uint8_t erase_before_write)
{
#if defined(HOSTSPIFLASHCFG_BASE) && (ALLOW_FLASH_WRITES)
uint32_t flash_address;
uint32_t bytes_remaining;
......@@ -791,6 +1001,9 @@ static int write_data_to_flash(uint8_t *write_buffer, uint32_t bytes, uint32_t f
{
return 0;
}
#else
return -1;
#endif
}
// NOTE
......@@ -802,6 +1015,7 @@ static int write_data_to_flash(uint8_t *write_buffer, uint32_t bytes, uint32_t f
// timeframe, e.g. 10ms
static void process_host_to_bmc_ipmi_bt_transactions(void)
{
#ifdef HOSTLPCSLAVE_BASE
uint32_t dword;
static uint8_t unhandled_ipmi_command;
......@@ -1095,9 +1309,11 @@ static void process_host_to_bmc_ipmi_bt_transactions(void)
}
hiomap_config.dirty_range_count = 0;
#ifdef HOSTSPIFLASH_BASE
// Copy data from Flash into cache buffer
memcpy(host_flash_write_buffer, (uint8_t *)(HOSTSPIFLASH_BASE + hiomap_config.window_start_address),
FLASH_MAX_WR_WINDOW_BYTES);
#endif
}
// Generate response
......@@ -1280,6 +1496,7 @@ static void process_host_to_bmc_ipmi_bt_transactions(void)
ipmi_bt_transaction_state = 0;
break;
}
#endif
}
#if !(ENABLE_LPC_FW_CYCLE_IRQ_HANDLER)
......@@ -1288,6 +1505,7 @@ static uint32_t previous_fw_read_address = 0xdeadbeef;
static void process_interrupts_stage2(void)
{
#ifdef HOSTLPCSLAVE_BASE
uint32_t dword;
int read_position;
......@@ -1369,6 +1587,7 @@ static void process_interrupts_stage2(void)
// Re-activate interupts on exiting critical section
irq_setie(1);
#endif
}
static void run_pre_ipl_bmc_peripheral_setup(void)
......@@ -1378,7 +1597,7 @@ static void run_pre_ipl_bmc_peripheral_setup(void)
// Reset POST codes and display
post_code_high = 0;
post_code_low = 0;
set_led_bank_display(0x00);
set_led_bank_display(0x0000);
// Deactivate interrupts on entering critical section
irq_setie(0);
......@@ -1394,6 +1613,7 @@ static void run_pre_ipl_bmc_peripheral_setup(void)
// Re-activate interupts on exiting critical section
irq_setie(1);
#ifdef HOSTLPCSLAVE_BASE
// Configure VUART1
dword = 0;
dword |= (1 & AQUILA_LPC_VUART_FIFO_TRIG_LVL_MASK) << AQUILA_LPC_VUART_FIFO_TRIG_LVL_SHIFT;
......@@ -1422,6 +1642,7 @@ static void run_pre_ipl_bmc_peripheral_setup(void)
dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1);
dword |= ((1 & AQUILA_LPC_CTL_EN_FW_CYCLE_IRQ_MASK) << AQUILA_LPC_CTL_EN_FW_CYCLE_IRQ_SHIFT);
write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1, dword);
#endif
#endif
// Reset HIOMAP windows
......@@ -1432,6 +1653,7 @@ static void run_pre_ipl_bmc_peripheral_setup(void)
hiomap_config.window_type = HIOMAP_WINDOW_TYPE_READ;
hiomap_config.dirty_range_count = 0;
#ifdef HOSTLPCSLAVE_BASE
if (ENABLE_LPC_FW_CYCLE_DMA)
{
// Configure and enable LPC firmware cycle DMA
......@@ -1448,6 +1670,7 @@ static void run_pre_ipl_bmc_peripheral_setup(void)
dword &= ~((1 & AQUILA_LPC_CTL_EN_FW_DMA_W_MASK) << AQUILA_LPC_CTL_EN_FW_DMA_W_SHIFT);
write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_DMA_CONFIG1, dword);
}
#endif
// Enable host background service task
host_background_service_task_active = 1;
......@@ -1467,6 +1690,7 @@ static void run_post_shutdown_bmc_peripheral_teardown(void)
// Reset internal state variables
ipmi_bt_transaction_state = 0;
#ifdef HOSTLPCSLAVE_BASE
// Set IPMI BT B_BUSY flag
dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_IPMI_BT_STATUS) & (1 << IPMI_BT_CTL_B_BUSY_SHIFT);
if (!(dword & (1 << IPMI_BT_CTL_B_BUSY_SHIFT)))
......@@ -1499,6 +1723,7 @@ static void run_post_shutdown_bmc_peripheral_teardown(void)
// Disable LPC slave IRQs
set_lpc_slave_irq_enable(0);
#endif
// Reset HIOMAP windows
hiomap_config.protocol_version = 0;
......@@ -1511,7 +1736,7 @@ static void run_post_shutdown_bmc_peripheral_teardown(void)
// Reset POST codes and display
post_code_high = 0;
post_code_low = 0;
set_led_bank_display(0x00);
set_led_bank_display(0x0000);
}
static int apply_avsbus_workarounds_cpu(const cpu_info_t *cpu)
......@@ -1656,50 +1881,61 @@ static int disable_avsbus_pmbus(const cpu_info_t *cpu_info, int cpu_count)
static void power_off_chassis(void)
{
#if (PLATFORM_ARCTIC_TERN)
// Disable LPC clock buffer
gpio1_out_write(gpio1_out_read() & ~(0x01 << 12));
#endif
// Disable PMBUS
if (disable_avsbus_pmbus(g_cpu_info, configured_cpu_count))
{
printf("PMBUS disable failed!\n");
}
#ifdef P9PS_I2C_MASTER_BASE_ADDR
// Power off host via platform FPGA commands
i2c_write_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_MFR_OVR, 0x00);
i2c_write_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_MFR_OVR, 0x00);
#endif
run_post_shutdown_bmc_peripheral_teardown();
}
static int power_on_chassis(void)
{
int cpu_count = 1;
#ifdef P9PS_I2C_MASTER_BASE_ADDR
uint8_t platform_fpga_identifier[4];
int platform_power_on_timeout_counter;
int cpu_count = 1;
int i2c_read_retcode;
uint8_t byte;
// Verify communication with platform control FPGA
platform_fpga_identifier[0] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0c, NULL);
platform_fpga_identifier[0] = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0c, NULL);
if (platform_fpga_identifier[0] == 0xff)
{
return -1;
}
platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL);
platform_fpga_identifier[2] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0e, NULL);
platform_fpga_identifier[3] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0f, NULL);
platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL);
platform_fpga_identifier[2] = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0e, NULL);
platform_fpga_identifier[3] = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0f, NULL);
if ((platform_fpga_identifier[0] != 0x52) || (platform_fpga_identifier[1] != 0x43) || (platform_fpga_identifier[2] != 0x53) ||
(platform_fpga_identifier[3] != 0x20))
{
return -1;
}
printf("Platform FPGA communication verified\n");
#endif
// Enable BMC runtime support tasks
run_pre_ipl_bmc_peripheral_setup();
#ifdef P9PS_I2C_MASTER_BASE_ADDR
// Power on host via platform FPGA commands
printf("Commanding chassis power ON...\n");
i2c_write_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_MFR_OVR, 0x01);
i2c_write_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_MFR_OVR, 0x01);
platform_power_on_timeout_counter = 0;
byte = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_STATUS, &i2c_read_retcode);
byte = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_STATUS, &i2c_read_retcode);
while (i2c_read_retcode || (((byte)&0x03) != 0x03))
{
if (platform_power_on_timeout_counter > 20000)
......@@ -1710,7 +1946,8 @@ static int power_on_chassis(void)
}
usleep(100);
platform_power_on_timeout_counter++;
byte = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_STATUS, &i2c_read_retcode);
byte =
i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_STATUS, &i2c_read_retcode);
}
if (i2c_read_retcode)
{
......@@ -1729,6 +1966,7 @@ static int power_on_chassis(void)
printf("Limiting number of CPUs to %d\n", MAX_CPUS_SUPPORTED);
}
printf("%d CPU(s) installed\n", cpu_count);
#endif
// Apply AVSBus workarounds
if (apply_avsbus_workarounds(g_cpu_info, cpu_count))
......@@ -1746,6 +1984,11 @@ static int power_on_chassis(void)
return -5;
}
#if (PLATFORM_ARCTIC_TERN)
// Enable LPC clock buffer
gpio1_out_write(gpio1_out_read() | (0x01 << 12));
#endif
return 0;
}
......@@ -1766,10 +2009,11 @@ static int power_on_host(void)
static void print_chassis_status(void)
{
#ifdef P9PS_I2C_MASTER_BASE_ADDR
int i2c_read_retcode;
uint8_t byte;
byte = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_STATUS, &i2c_read_retcode);
byte = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_STATUS, &i2c_read_retcode);
if (i2c_read_retcode)
{
printf("Unable to communicate with platform control FPGA!\n");
......@@ -1810,6 +2054,7 @@ static void print_chassis_status(void)
{
printf("\tBackground host services inactive\n");
}
#endif
}
static void host_background_service_task_event_loop(void)
......@@ -1838,6 +2083,7 @@ static void host_background_service_task_event_loop(void)
irq_unhandled_vector_valid = 0;
}
#ifdef HOSTLPCSLAVE_BASE
if (read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_STATUS1) & (AQUILA_LPC_STATUS_ATTN_REQ_MASK << AQUILA_LPC_STATUS_ATTN_REQ_SHIFT))
{
// Store / retrieve data
......@@ -1856,11 +2102,14 @@ static void host_background_service_task_event_loop(void)
// Limit firmware address to 64MB (wrap around)
address &= 0x3ffffff;
// Show address lower bytes on display for debugging
// gpio2_out_write((address >> 8) & 0xffff);
#if (ENABLE_LPC_FW_CYCLE_NONCONTIGUOUS_DEBUG)
if ((previous_fw_read_address + 4) != address)
{
noncontiguous_access = 1;
printf("[DEBG] Non-contiguous firmware access to address 0x%08x\n", address);
printf("[DEBG] Non-contiguous firmware access to address 0x%08x (prev 0x%08x)\n", address, previous_fw_read_address);
}
else
{
......@@ -2019,7 +2268,7 @@ static void host_background_service_task_event_loop(void)
else if (address == 0x82)
{
post_code_low = post_code;
set_led_bank_display(((post_code_high & 0xf) << 4) | (post_code_low & 0xf));
set_led_bank_display(((post_code_high & 0xff) << 8) | (post_code_low & 0xff));
if (enable_post_code_console_output)
{
......@@ -2061,6 +2310,7 @@ static void host_background_service_task_event_loop(void)
write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL2, dword);
}
}
#endif
}
void primary_service_event_loop(void)
......@@ -2088,6 +2338,7 @@ void primary_service_event_loop(void)
static void attach_to_host_console(void)
{
#ifdef HOSTLPCSLAVE_BASE
uint8_t escape_sequence_state;
uint8_t character;
uint8_t character_read;
......@@ -2213,6 +2464,7 @@ static void attach_to_host_console(void)
// Signal host console service is now inactive
host_console_service_task_active = 0;
#endif
}
static uint64_t parse_user_provided_number(const char *string)
......@@ -2342,7 +2594,7 @@ static void console_service(void)
{
token = get_token(&str);
reg = parse_user_provided_number(token);
data = i2c_read_register_byte((uint8_t *)(I2CMASTER1_BASE + (0x20 * (bus - 1))), address, reg, NULL);
data = i2c_read_register_byte((uint8_t *)(CPU0_I2C_MASTER_BASE_ADDR + (0x20 * (bus - 1))), address, reg, NULL);
printf("I2C device %d:0x%02x<0x%02x>: 0x%02x\n", bus, address, reg, data);
}
else
......@@ -2378,7 +2630,7 @@ static void console_service(void)
{
token = get_token(&str);
data = parse_user_provided_number(token);
i2c_write_register_byte((uint8_t *)(I2CMASTER1_BASE + (0x20 * (bus - 1))), address, reg, data);
i2c_write_register_byte((uint8_t *)(CPU0_I2C_MASTER_BASE_ADDR + (0x20 * (bus - 1))), address, reg, data);
printf("I2C device %d:0x%02x<0x%02x> set to 0x%02x\n", bus, address, reg, data);
}
else
......@@ -2486,6 +2738,7 @@ static void console_service(void)
prompt();
}
#if (WITH_SPI)
static void memcpy32(uint32_t *destination, uint32_t *source, int words)
{
int word;
......@@ -2496,6 +2749,7 @@ static void memcpy32(uint32_t *destination, uint32_t *source, int words)
source++;
}
}
#endif
#if (WITH_DRAM)
static void memset32(uint32_t *destination, uint32_t value, int words)
......@@ -2512,6 +2766,7 @@ static void memset32(uint32_t *destination, uint32_t value, int words)
#if (WITH_SPI)
static uint32_t read_host_spi_flash_id(void)
{
#ifdef HOSTSPIFLASHCFG_BASE
uint32_t flash_id = 0;
// Set user mode
......@@ -2534,10 +2789,14 @@ static uint32_t read_host_spi_flash_id(void)
~(TERCEL_SPI_ENABLE_USER_MODE_MASK << TERCEL_SPI_ENABLE_USER_MODE_SHIFT));
return flash_id;
#else
return 0xffff;
#endif
}
static int host_spi_flash_init(void)
{
#ifdef HOSTSPIFLASHCFG_BASE
int i;
uint32_t dword;
uint32_t flash_device_id;
......@@ -2664,6 +2923,7 @@ static int host_spi_flash_init(void)
(TERCEL_SPI_FLASH_EN_MULTCYC_WRITE_MASK << TERCEL_SPI_FLASH_EN_MULTCYC_WRITE_SHIFT));
return 0;
#endif
}
#endif
......@@ -2767,10 +3027,16 @@ int main(void)
display_character('0', 0); // STATUS CODE: 0
for (int i = 0; i < MAX_CPUS_SUPPORTED; i++)
{
initialize_i2c_master(g_cpu_info[i].i2c_master, g_cpu_info[i].i2c_frequency);
}
// Baseline I2C controller initialization
#ifdef I2CMASTER0_BASE
initialize_i2c_master((uint8_t *)I2CMASTER0_BASE, 100000);
#endif
#ifdef I2CMASTER1_BASE
initialize_i2c_master((uint8_t *)I2CMASTER1_BASE, 100000);