Add front panel support

Add basic 1ms system timer service
parent 128bbbee
Pipeline #263 passed with stage
in 18 seconds
......@@ -10,9 +10,15 @@ uint32_t irq_unhandled_source = 0;
uint8_t irq_unhandled_vector_valid = 0;
uint8_t irq_unhandled_source_valid = 0;
uint64_t uptime_counter_ms = 0;
void isr(uint64_t vec);
void isr_dec(void);
#ifdef GPIO1_INTERRUPT
void gpio1_isr(void);
#endif
#ifdef CONFIG_CPU_HAS_INTERRUPT
void isr(uint64_t vec)
......@@ -61,6 +67,13 @@ void isr(uint64_t vec)
lpc_slave_isr();
}
#ifdef GPIO1_INTERRUPT
if (irqs & (1 << GPIO1_INTERRUPT))
{
gpio1_isr();
}
#endif
if (!irqs)
{
irq_unhandled_source = irq_source;
......@@ -83,9 +96,10 @@ void isr(uint64_t vec)
void isr_dec(void)
{
// For now, just set DEC back to a large enough value to slow the flood of
// DEC-initiated timer interrupts
mtdec(0x000000000ffffff);
// Fire decrementer interrupt every 1ms
mtdec(CONFIG_CLOCK_FREQUENCY / 1000);
uptime_counter_ms++;
}
#else
......
......@@ -54,6 +54,13 @@
#define P9PS_I2C_MASTER_BASE_ADDR I2CMASTER4_BASE
#define HDMI_I2C_MASTER_BASE_ADDR I2CMASTER4_BASE
#define WITH_DRAM 1
// Front panel interface
#define POWER_BUTTON_IN_GPIO 6
#define POWER_BUTTON_PWR_GPIO 7
#define RESET_BUTTON_IN_GPIO 8
#define RESET_BUTTON_PWR_GPIO 9
#define POWER_LED_OUT_GPIO 10
#endif
#define WITH_SPI 1
......@@ -99,13 +106,24 @@
#define HOST_PLATFORM_FPGA_I2C_ADDRESS 0x31
#define HDMI_TRANSCEIVER_I2C_ADDRESS 0x4c
// General configuration
#define BUTTON_LONG_PRESS_MS 3000
uint8_t host_flash_write_buffer[FLASH_MAX_WR_WINDOW_BYTES];
extern uint64_t uptime_counter_ms;
extern uint32_t irq_unhandled_vector;
extern uint32_t irq_unhandled_source;
extern uint8_t irq_unhandled_vector_valid;
extern uint8_t irq_unhandled_source_valid;
uint64_t power_button_press_timestamp;
uint8_t power_button_long_press_request = 0;
uint8_t power_button_short_press_request = 0;
uint8_t chassis_power_on = 0;
#define VUART_INTERRUPT_TRANSIENT_BUFFER_SIZE 32
// Interrupt transient VUART1 buffer
......@@ -383,6 +401,12 @@ static void gpio_init(void)
set_led_bank_display(0x0000);
gpio1_oe_write(0xff);
}
static void set_power_led(uint8_t on)
{
// Not implemented
(void)on;
}
#endif
#if (PLATFORM_SPARROWHAWK)
......@@ -408,6 +432,12 @@ static void gpio_init(void)
gpio1_oe_write(0x0b);
}
static void set_power_led(uint8_t on)
{
// Not implemented
(void)on;
}
#endif
#if (PLATFORM_ARCTIC_TERN)
......@@ -440,6 +470,30 @@ 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));
// Set up and turn off power LED
gpio1_out_write(gpio1_out_read() & ~(0x01 << POWER_LED_OUT_GPIO));
gpio1_oe_write(gpio1_oe_read() | (0x01 << POWER_LED_OUT_GPIO));
// Set up power and reset switches
gpio1_oe_write(gpio1_oe_read() & ~((0x01 << POWER_BUTTON_IN_GPIO) | ((0x01 << RESET_BUTTON_IN_GPIO))));
gpio1_mode_write(gpio1_mode_read() | ((0x01 << POWER_BUTTON_IN_GPIO) | ((0x01 << POWER_BUTTON_IN_GPIO))));
gpio1_oe_write(gpio1_oe_read() | ((0x01 << POWER_BUTTON_PWR_GPIO) | (0x01 << RESET_BUTTON_PWR_GPIO)));
gpio1_out_write(gpio1_out_read() | ((0x01 << POWER_BUTTON_PWR_GPIO) | ((0x01 << RESET_BUTTON_PWR_GPIO))));
}
static void set_power_led(uint8_t on)
{
if (on)
{
// Turn power LED on
gpio1_out_write(gpio1_out_read() | (0x01 << POWER_LED_OUT_GPIO));
}
else
{
// Turn power LED off
gpio1_out_write(gpio1_out_read() & ~(0x01 << POWER_LED_OUT_GPIO));
}
}
#endif
......@@ -507,6 +561,67 @@ static void sparrowhawk_base_platform_init(void)
}
#endif
#ifdef GPIO1_INTERRUPT
static void set_discrete_gpio_irq_enable(uint8_t enable, uint32_t enabled_pins)
{
if (!enable)
{
gpio1_ev_enable_write(0);
irq_setmask(irq_getmask() & ~(1 << GPIO1_INTERRUPT));
}
// Clear pending interrupts
gpio1_ev_pending_write(gpio1_ev_pending_read());
if (enable)
{
gpio1_ev_enable_write(enabled_pins);
irq_setmask(irq_getmask() | (1 << GPIO1_INTERRUPT));
}
}
#endif
void power_button_pressed(void)
{
power_button_press_timestamp = uptime_counter_ms;
}
void power_button_released(void)
{
uint64_t current_timestamp = uptime_counter_ms;
if ((current_timestamp - power_button_press_timestamp) > BUTTON_LONG_PRESS_MS)
{
power_button_long_press_request = 1;
}
else
{
power_button_short_press_request = 1;
}
}
#ifdef GPIO1_INTERRUPT
void gpio1_isr(void)
{
uint32_t pending_irqs = gpio1_ev_pending_read();
uint32_t current_values = gpio1_in_read();
// Clear pending interrupts
gpio1_ev_pending_write(pending_irqs);
if (pending_irqs & (0x1 << POWER_BUTTON_IN_GPIO))
{
if (current_values & (0x1 << POWER_BUTTON_IN_GPIO))
{
power_button_pressed();
}
else
{
power_button_released();
}
}
}
#endif
static void set_lpc_slave_irq_enable(uint8_t enabled)
{
#ifdef HOSTLPCSLAVE_BASE
......@@ -1898,6 +2013,9 @@ static void power_off_chassis(void)
#endif
run_post_shutdown_bmc_peripheral_teardown();
chassis_power_on = 0;
set_power_led(chassis_power_on);
}
static int power_on_chassis(void)
......@@ -1910,10 +2028,15 @@ static int power_on_chassis(void)
int i2c_read_retcode;
uint8_t byte;
// Turn on power LED as soon as possible to provide early visual feedback
set_power_led(1);
// Verify communication with platform control FPGA
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)
{
chassis_power_on = 0;
set_power_led(chassis_power_on);
return -1;
}
platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)P9PS_I2C_MASTER_BASE_ADDR, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL);
......@@ -1922,6 +2045,8 @@ static int power_on_chassis(void)
if ((platform_fpga_identifier[0] != 0x52) || (platform_fpga_identifier[1] != 0x43) || (platform_fpga_identifier[2] != 0x53) ||
(platform_fpga_identifier[3] != 0x20))
{
chassis_power_on = 0;
set_power_led(chassis_power_on);
return -1;
}
printf("Platform FPGA communication verified\n");
......@@ -1952,6 +2077,7 @@ static int power_on_chassis(void)
if (i2c_read_retcode)
{
printf("FPGA communication failure during poweron!\n");
chassis_power_on = 0;
return -3;
}
if (byte & 0x20)
......@@ -1989,6 +2115,8 @@ static int power_on_chassis(void)
gpio1_out_write(gpio1_out_read() | (0x01 << 12));
#endif
chassis_power_on = 1;
return 0;
}
......@@ -2057,6 +2185,32 @@ static void print_chassis_status(void)
#endif
}
static void external_control_service(void)
{
// Power button handler
if (power_button_long_press_request)
{
power_button_long_press_request = 0;
power_button_short_press_request = 0;
if (chassis_power_on)
{
power_off_chassis();
}
}
if (power_button_short_press_request)
{
power_button_short_press_request = 0;
if (!chassis_power_on)
{
power_on_host();
}
}
set_power_led(chassis_power_on);
}
static void host_background_service_task_event_loop(void)
{
uint32_t address;
......@@ -2334,6 +2488,9 @@ void primary_service_event_loop(void)
// Process cooperative multitasking threads
process_host_to_bmc_ipmi_bt_transactions();
}
// Continually run the external control service thread
external_control_service();
}
static void attach_to_host_console(void)
......@@ -3174,6 +3331,12 @@ int main(void)
configure_hdmi_transceiver((uint8_t *)HDMI_I2C_MASTER_BASE_ADDR);
#endif
// Enable button IRQs, if present
#if (PLATFORM_ARCTIC_TERN)
uint32_t gpio_irq_pins = (1 << POWER_BUTTON_IN_GPIO) | (1 << RESET_BUTTON_IN_GPIO);
set_discrete_gpio_irq_enable(1, gpio_irq_pins);
#endif
if (PLATFORM_SPARROWHAWK)
{
gpio1_out_write(gpio1_out_read() & ~0x02); // Set BMC boot phase to 2
......@@ -3188,6 +3351,7 @@ int main(void)
while (1)
{
// Console handler
console_service();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment