Add initial host power/reset button support

parent 9519dc4b
......@@ -117,6 +117,7 @@ uint8_t hiomap_use_direct_access = 0;
uint8_t host_background_service_task_active = 0;
uint8_t host_console_service_task_active = 0;
uint8_t host_console_service_task_requested = 0;
uint8_t host_power_status = HOST_POWER_STATUS_OFFLINE;
static int configured_cpu_count = 1;
// POST codes
......@@ -2179,6 +2180,8 @@ static int disable_avsbus_pmbus(const cpu_info_t *cpu_info, int cpu_count)
void power_off_chassis(void)
{
host_power_status = HOST_POWER_STATUS_POWERING_OFF;
// Disable PMBUS
if (disable_avsbus_pmbus(g_cpu_info, configured_cpu_count))
{
......@@ -2189,6 +2192,8 @@ void power_off_chassis(void)
i2c_write_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, HOST_PLATFORM_FPGA_I2C_REG_MFR_OVR, 0x00);
run_post_shutdown_bmc_peripheral_teardown();
host_power_status = HOST_POWER_STATUS_OFFLINE;
}
static int power_on_chassis(void)
......@@ -2199,10 +2204,13 @@ static int power_on_chassis(void)
int i2c_read_retcode;
uint8_t byte;
host_power_status = HOST_POWER_STATUS_POWERING_ON;
// 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);
if (platform_fpga_identifier[0] == 0xff)
{
host_power_status = HOST_POWER_STATUS_OFFLINE;
return -1;
}
platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL);
......@@ -2211,6 +2219,7 @@ 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))
{
host_power_status = HOST_POWER_STATUS_OFFLINE;
return -1;
}
KESTREL_LOG("Platform FPGA communication verified");
......@@ -2269,6 +2278,8 @@ static int power_on_chassis(void)
return -5;
}
host_power_status = HOST_POWER_STATUS_RUNNING;
return 0;
}
......
......@@ -11,6 +11,28 @@
#define KESTREL_SERVICE_THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
#endif
#if (WITH_ZEPHYR)
#define SW0_NODE DT_ALIAS(sw0)
#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
#define KESTREL_HOST_POWER_BUTTON_GPIO DT_GPIO_LABEL(SW0_NODE, gpios)
#define KESTREL_HOST_POWER_BUTTON_PIN DT_GPIO_PIN(SW0_NODE, gpios)
#else
#error "No power button defined in device tree"
#endif
#define SW1_NODE DT_ALIAS(sw1)
#if DT_NODE_HAS_STATUS(SW1_NODE, okay)
#define KESTREL_HOST_RESET_BUTTON_GPIO DT_GPIO_LABEL(SW1_NODE, gpios)
#define KESTREL_HOST_RESET_BUTTON_PIN DT_GPIO_PIN(SW1_NODE, gpios)
#else
#error "No reset button defined in device tree"
#endif
#endif
#define HOST_POWER_STATUS_OFFLINE 0
#define HOST_POWER_STATUS_POWERING_ON 1
#define HOST_POWER_STATUS_RUNNING 2
#define HOST_POWER_STATUS_POWERING_OFF 3
struct firmware_buffer_region {
uint8_t *buffer_address;
unsigned long long buffer_length;
......@@ -24,6 +46,7 @@ extern struct firmware_buffer_region main_firmware_buffer;
extern uint8_t kestrel_basic_init_complete;
extern uint8_t host_background_service_task_active;
extern uint8_t host_console_service_task_requested;
extern uint8_t host_power_status;
#if (WITH_ZEPHYR)
extern k_tid_t kestrel_service_thread_id;
......
......@@ -10,12 +10,18 @@ LOG_MODULE_REGISTER(kestrel_init, LOG_LEVEL_DBG);
#include <stdio.h>
#include <ctype.h>
#include <zephyr.h>
#include <device.h>
#include <drivers/gpio.h>
#define WITH_ZEPHYR 1
#include "webservice.h"
#include "flash_filesystem.h"
#include "kestrel.h"
static struct gpio_callback host_power_button_callback_data;
static struct gpio_callback host_reset_button_callback_data;
#define KESTREL_INIT_THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
static K_THREAD_STACK_DEFINE(kestrel_init_thread_stack, 16384);
static struct k_thread kestrel_init_thread_data;
......@@ -52,6 +58,95 @@ static void kestrel_service_thread(void)
}
}
void host_power_button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
int want_power_on = 0;
int want_power_off = 0;
LOG_INF("Host power button pressed");
// Deactivate interrupts on entering critical section
int key = irq_lock();
if (host_power_status == HOST_POWER_STATUS_OFFLINE) {
want_power_on = 1;
}
else {
want_power_off = 1;
}
// Re-activate interupts on exiting critical section
irq_unlock(key);
if (want_power_on) {
power_on_host();
}
else if (want_power_off) {
power_off_chassis();
}
}
void host_reset_button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
// Deactivate interrupts on entering critical section
int key = irq_lock();
// FIXME
// Implement host reset functionality
// Re-activate interupts on exiting critical section
irq_unlock(key);
LOG_WRN("[FIXME] Reset button pressed, but not implemented!");
}
static int configure_gpios(void)
{
const struct device *button;
int retcode;
int ret;
retcode = 0;
// Set up power button
button = device_get_binding(KESTREL_HOST_POWER_BUTTON_GPIO);
if (button == NULL) {
printk("[ERROR] Unable to locate host power button on node %s\n", KESTREL_HOST_POWER_BUTTON_GPIO);
retcode = -1;
}
else {
ret = gpio_pin_interrupt_configure(button, KESTREL_HOST_POWER_BUTTON_PIN, GPIO_INT_EDGE_TO_ACTIVE);
if (ret != 0) {
printk("[ERROR] failed to configure interrupt on %s pin %d (returned %d)\n", KESTREL_HOST_POWER_BUTTON_GPIO, KESTREL_HOST_POWER_BUTTON_PIN, ret);
retcode = -1;
}
else {
gpio_init_callback(&host_power_button_callback_data, host_power_button_pressed, BIT(KESTREL_HOST_POWER_BUTTON_PIN));
gpio_add_callback(button, &host_power_button_callback_data);
}
}
// Set up reset button
button = device_get_binding(KESTREL_HOST_RESET_BUTTON_GPIO);
if (button == NULL) {
printk("[ERROR] Unable to locate host reset button on node %s\n", KESTREL_HOST_RESET_BUTTON_GPIO);
retcode = -1;
}
else {
ret = gpio_pin_interrupt_configure(button, KESTREL_HOST_RESET_BUTTON_PIN, GPIO_INT_EDGE_TO_ACTIVE);
if (ret != 0) {
printk("[ERROR] failed to configure interrupt on %s pin %d (returned %d)\n", KESTREL_HOST_RESET_BUTTON_GPIO, KESTREL_HOST_RESET_BUTTON_PIN, ret);
retcode = -1;
}
else {
gpio_init_callback(&host_reset_button_callback_data, host_reset_button_pressed, BIT(KESTREL_HOST_RESET_BUTTON_PIN));
gpio_add_callback(button, &host_reset_button_callback_data);
}
}
return retcode;
}
void main(void)
{
// Set root command and prompt for all shells
......@@ -86,5 +181,8 @@ void main(void)
NULL, NULL, NULL, KESTREL_SERVICE_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(kestrel_service_thread_id, "kestrel_service");
// Run late setup
configure_gpios();
LOG_INF("Kestrel system initialization complete\n");
}
\ No newline at end of file
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