Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
Bare Metal Firmware
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
3
Issues
3
List
Boards
Labels
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kestrel Collaboration
Kestrel Firmware
Bare Metal Firmware
Commits
ed8d2d65
Commit
ed8d2d65
authored
Sep 30, 2021
by
Raptor Engineering Development Team
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for RCS Arctic Tern and Sparrowhawk platforms
parent
3c4cfe74
Pipeline
#247
failed with stage
in 13 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
321 additions
and
37 deletions
+321
-37
CMakeLists.txt
CMakeLists.txt
+1
-1
linker.ld
linker.ld
+1
-1
main.c
main.c
+319
-35
No files found.
CMakeLists.txt
View file @
ed8d2d65
...
...
@@ -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
}
)
...
...
linker.ld
View file @
ed8d2d65
...
...
@@ -63,7 +63,7 @@ SECTIONS
. = ALIGN(8);
_ebss = .;
_end = .;
} >
s
ram
} >
main_
ram
.stack ALIGN(8) (NOLOAD):
{
...
...
main.c
View file @
ed8d2d65
// © 2020 - 202
1
Raptor Engineering, LLC
// © 2020 - 202
2
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 0
#endif
#ifndef PLATFORM_SPARROWHAWK
#define PLATFORM_SPARROWHAWK 0
#endif
#ifndef PLATFORM_ARCTIC_TERN
#define PLATFORM_ARCTIC_TERN 1
#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 HDMI_I2C_MASTER_BASE_ADDR I2CMASTER6_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 +85,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 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 +98,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 +176,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 +191,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 +320,14 @@ static void reboot(void)
ctrl_reset_write
(
1
);
}
#if (PLATFORM_VERSA_ECP5)
static
void
gpio_init
(
void
)
{
// Set up discrete LED bank
set_led_bank_display
(
0x0000
);
gpio1_oe_write
(
0xff
);
}
static
void
display_character
(
char
character
,
int
dp
)
{
uint16_t
value
;
...
...
@@ -307,24 +373,142 @@ static void display_character(char character, int dp)
gpio3_out_write
(
~
(
value
|
((
dp
==
0
)
?
0x0000
:
0x4000
)));
}
static
void
set_led_bank_display
(
uint
8_t
bitfield
)
static
void
set_led_bank_display
(
uint
16_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
);
}
#endif
#if (PLATFORM_SPARROWHAWK)
static
void
gpio_init
(
void
)
{
// Set up discrete LED bank
set_led_bank_display
(
0x00
);
gpio1_oe_write
(
0xff
);
// 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
);
}
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
}
#endif
#if (PLATFORM_ARCTIC_TERN)
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
));
}
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
));
}
#endif
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
"
);
}
#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 +523,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 +573,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 +774,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 +805,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 +831,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 +865,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 +910,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 +948,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 +1000,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 +1014,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 +1308,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 +1495,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 +1504,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 +1586,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 +1596,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
(
0x00
00
);
// Deactivate interrupts on entering critical section
irq_setie
(
0
);
...
...
@@ -1394,6 +1612,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 +1641,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 +1652,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 +1669,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 +1689,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 +1722,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 +1735,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
(
0x00
00
);
}
static
int
apply_avsbus_workarounds_cpu
(
const
cpu_info_t
*
cpu
)
...
...
@@ -1656,50 +1880,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 +1945,7 @@ 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 +1964,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 +1982,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 +2007,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 +2052,7 @@ static void print_chassis_status(void)
{
printf
(
"
\t
Background host services inactive
\n
"
);
}
#endif
}
static
void
host_background_service_task_event_loop
(
void
)
...
...
@@ -1838,6 +2081,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 +2100,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 +2266,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
&
0x
f
));
set_led_bank_display
(((
post_code_high
&
0xf
f
)
<<
8
)
|
(
post_code_low
&
0xf
f
));
if
(
enable_post_code_console_output
)
{
...
...
@@ -2061,6 +2308,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 +2336,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 +2462,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 +2592,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 +2628,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 +2736,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 +2747,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 +2764,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 +2787,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 +2921,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 +3025,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