From b81af1233e23497ca8317f2669947398d0142e12 Mon Sep 17 00:00:00 2001 From: Jett Rink Date: Wed, 14 Oct 2020 13:58:40 -0600 Subject: zephyr: add initial gpio shim Add the gpioget and gpioset commands to zephyr build. This requires a minimum set of platform/ec gpio_ API functions. Add the minimum set of gpio_ functions. More can be added later depending on future uses BRANCH=none BUG=b:169935802 TEST=verify gpioget and gpioset console command work on volteer TEST=verify that posix-ec compiles without any named_gpios in DT Change-Id: Ie6f0b4505aa17c50c01b71fc4ea5b59393f39fce Signed-off-by: Jett Rink Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2488141 Reviewed-by: Jack Rosenthal Commit-Queue: Jack Rosenthal --- include/gpio.h | 65 ++++++++++++++----- zephyr/CMakeLists.txt | 1 + zephyr/shim/include/board.h | 9 ++- zephyr/shim/include/gpio_signal.h | 29 +++++++++ zephyr/shim/src/CMakeLists.txt | 1 + zephyr/shim/src/gpio.c | 130 ++++++++++++++++++++++++++++++++++++++ zephyr/shim/src/util.c | 13 ++++ 7 files changed, 232 insertions(+), 16 deletions(-) create mode 100644 zephyr/shim/include/gpio_signal.h create mode 100644 zephyr/shim/src/gpio.c diff --git a/include/gpio.h b/include/gpio.h index 92c851f91a..3fa091f4bd 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -11,24 +11,59 @@ #include "common.h" #include "console.h" -/* Flag definitions for gpio_info and gpio_alt_func */ + +/* + * If compiling with Zephyr, include the GPIO_ definitions to deal with name + * conflicts + */ +#ifdef CONFIG_ZEPHYR +#include + +/* Validate that Zephyr's definition are the same for overlapping defines */ +#if GPIO_OPEN_DRAIN != (BIT(1) | BIT(2)) +#error GPIO_OPEN_DRAIN values are not the same! +#elif GPIO_PULL_UP != BIT(4) +#error GPIO_PULL_UP values are not the same! +#elif GPIO_PULL_DOWN != BIT(5) +#error GPIO_PULL_DOWN values are not the same! +#elif GPIO_INPUT != BIT(8) +#error GPIO_INPUT values are not the same! +#elif GPIO_OUTPUT != BIT(9) +#error GPIO_PULL_DOWN values are not the same! +#endif + +/* Otherwise define overlapping GPIO_ flags ourselves */ +#else /* !CONFIG_ZEPHYR */ +#define GPIO_OPEN_DRAIN (BIT(1) | BIT(2)) /* Output type is open-drain */ +#define GPIO_PULL_UP BIT(4) /* Enable on-chip pullup */ +#define GPIO_PULL_DOWN BIT(5) /* Enable on-chip pulldown */ +#define GPIO_INPUT BIT(8) /* Input */ +#define GPIO_OUTPUT BIT(9) /* Output */ +#endif /* CONFIG_ZEPHYR */ + +/* + * All flags supported by gpio_info expect GPIO_ANALOG + * + * Only 4 flags are supported by gpio_alt_func: + * GPIO_OPEN_DRAIN + * GPIO_PULL_UP + * GPIO_PULL_DOWN + * GPIO_PULL_ANALOG + */ #define GPIO_FLAG_NONE 0 /* No flag needed, default setting */ -/* The following are valid for both gpio_info and gpio_alt_func: */ -#define GPIO_OPEN_DRAIN BIT(0) /* Output type is open-drain */ -#define GPIO_PULL_UP BIT(1) /* Enable on-chip pullup */ -#define GPIO_PULL_DOWN BIT(2) /* Enable on-chip pulldown */ -/* The following are valid for gpio_alt_func only */ -#define GPIO_ANALOG BIT(3) /* Set pin to analog-mode */ -/* The following are valid for gpio_info only */ -#define GPIO_INPUT BIT(4) /* Input */ -#define GPIO_OUTPUT BIT(5) /* Output */ +#define GPIO_ANALOG BIT(0) /* Set pin to analog-mode */ +/* GPIO_OPEN_DRAIN BIT(1) | BIT(2) Output type is open-drain */ +#define GPIO_DEFAULT BIT(3) /* Don't set up on boot */ +/* GPIO_PULL_UP BIT(4) Enable on-chip pullup */ +/* GPIO_PULL_DOWN BIT(5) Enable on-chip pulldown */ #define GPIO_LOW BIT(6) /* If GPIO_OUTPUT, set level low */ #define GPIO_HIGH BIT(7) /* If GPIO_OUTPUT, set level high */ -#define GPIO_INT_F_RISING BIT(8) /* Interrupt on rising edge */ -#define GPIO_INT_F_FALLING BIT(9) /* Interrupt on falling edge */ -#define GPIO_INT_F_LOW BIT(11) /* Interrupt on low level */ -#define GPIO_INT_F_HIGH BIT(12) /* Interrupt on high level */ -#define GPIO_DEFAULT BIT(13) /* Don't set up on boot */ +/* GPIO_INPUT BIT(8) Input */ +/* GPIO_OUTPUT BIT(9) Output */ +#define GPIO_INT_F_RISING BIT(10) /* Interrupt on rising edge */ +#define GPIO_INT_F_FALLING BIT(11) /* Interrupt on falling edge */ +#define GPIO_INT_F_LOW BIT(12) /* Interrupt on low level */ +#define GPIO_INT_F_HIGH BIT(13) /* Interrupt on high level */ #define GPIO_INT_DSLEEP BIT(14) /* Interrupt in deep sleep */ #define GPIO_INT_SHARED BIT(15) /* Shared among multiple pins */ #define GPIO_SEL_1P8V BIT(16) /* Support 1.8v */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 60eca34519..cac731a2bc 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -37,3 +37,4 @@ add_subdirectory_ifdef(CONFIG_PLATFORM_EC "shim/src") # Shimmed modules zephyr_sources_ifdef(CONFIG_PLATFORM_EC "${PLATFORM_EC}/common/base32.c") zephyr_sources_ifdef(CONFIG_PLATFORM_EC_TIMER "${PLATFORM_EC}/common/timer.c") +zephyr_sources_ifdef(CONFIG_SHELL "${PLATFORM_EC}/common/gpio_commands.c") diff --git a/zephyr/shim/include/board.h b/zephyr/shim/include/board.h index 01f9344a8a..62bb1b23e2 100644 --- a/zephyr/shim/include/board.h +++ b/zephyr/shim/include/board.h @@ -6,6 +6,13 @@ #ifndef __BOARD_H #define __BOARD_H -/* Intentionally empty. */ +#include + +/* Included shimed version of gpio signal. */ +#include +/* Include board specific gpio mapping/aliases if named_pgios node exists */ +#if DT_NODE_EXISTS(DT_PATH(named_gpios)) +#include +#endif #endif /* __BOARD_H */ diff --git a/zephyr/shim/include/gpio_signal.h b/zephyr/shim/include/gpio_signal.h new file mode 100644 index 0000000000..698ef126bb --- /dev/null +++ b/zephyr/shim/include/gpio_signal.h @@ -0,0 +1,29 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_GPIO_SIGNAL_H +#define __CROS_EC_GPIO_SIGNAL_H + +#include + +#define GPIO_SIGNAL(id) _CONCAT(GPIO_, id) +#define GPIO_SIGNAL_WITH_COMMA(id) GPIO_SIGNAL(id), +enum gpio_signal { +#if DT_NODE_EXISTS(DT_PATH(named_gpios)) + DT_FOREACH_CHILD(DT_PATH(named_gpios), GPIO_SIGNAL_WITH_COMMA) +#endif + GPIO_COUNT +}; +#undef GPIO_SIGNAL_WITH_COMMA + +/** @brief Converts a node identifier under named gpios to enum + * + * Converts the specified node identifier name, which should be nested under + * the named_gpios node, into the correct enum gpio_signal that can be used + * with platform/ec gpio API + */ +#define NAMED_GPIO(name) GPIO_SIGNAL(DT_PATH(named_gpios, name)) + +#endif /* __CROS_EC_GPIO_SIGNAL_H */ diff --git a/zephyr/shim/src/CMakeLists.txt b/zephyr/shim/src/CMakeLists.txt index f87b114949..b56557deb9 100644 --- a/zephyr/shim/src/CMakeLists.txt +++ b/zephyr/shim/src/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_sources(console.c) zephyr_sources(util.c) +zephyr_sources(gpio.c) zephyr_sources_ifdef(CONFIG_PLATFORM_EC_TIMER hwtimer.c) diff --git a/zephyr/shim/src/gpio.c b/zephyr/shim/src/gpio.c new file mode 100644 index 0000000000..96d982052c --- /dev/null +++ b/zephyr/shim/src/gpio.c @@ -0,0 +1,130 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(gpio_shim, LOG_LEVEL_ERR); + +/* + * Static information about each GPIO that is configured in the named_gpios + * device tree node. + */ +struct gpio_config { + const char *name; /* GPIO net name */ + const char *dev_name; /* Set at build time for lookup */ + gpio_pin_t pin; /* Bit number of pin within device */ + gpio_flags_t init_flags; /* From build time */ +}; + +#define GPIO_CONFIG(id) \ + { \ + .name = DT_LABEL(id), \ + .dev_name = DT_LABEL(DT_PHANDLE(id, gpios)), \ + .pin = DT_GPIO_PIN(id, gpios), \ + .init_flags = DT_GPIO_FLAGS(id, gpios), \ + }, +static const struct gpio_config configs[] = { +#if DT_NODE_EXISTS(DT_PATH(named_gpios)) + DT_FOREACH_CHILD(DT_PATH(named_gpios), GPIO_CONFIG) +#endif +}; + +/* Runtime information for each GPIO that is configured in named_gpios */ +struct gpio_data { + const struct device *dev; /* Set during in init function */ +}; + +#define GPIO_DATA(id) { }, +static struct gpio_data data[] = { +#if DT_NODE_EXISTS(DT_PATH(named_gpios)) + DT_FOREACH_CHILD(DT_PATH(named_gpios), GPIO_DATA) +#endif +}; + + +int gpio_is_implemented(enum gpio_signal signal) +{ + /* All GPIOs listed in Device Tree are consider implemented */ + return 1; +} + +int gpio_get_level(enum gpio_signal signal) +{ + const int l = gpio_pin_get_raw(data[signal].dev, configs[signal].pin); + + if (l < 0) { + LOG_ERR("Cannot read %s (%d)", configs[signal].name, l); + return 0; + } + return l; +} + +const char *gpio_get_name(enum gpio_signal signal) +{ + return configs[signal].name; +} + +void gpio_set_level(enum gpio_signal signal, int value) +{ + int rv; + + if (value != 0) { + rv = gpio_port_set_bits_raw(data[signal].dev, + BIT(configs[signal].pin)); + } else { + rv = gpio_port_clear_bits_raw(data[signal].dev, + BIT(configs[signal].pin)); + } + + if (rv < 0) { + LOG_ERR("Cannot write %s (%d)", configs[signal].name, rv); + } +} + +static int convert_from_zephyr_flags(const gpio_flags_t zephyr) +{ + int ec_flags = 0; + + /* + * Convert from Zephyr flags to EC flags. Note that a few flags have + * the same value in both builds environments (e.g. GPIO_OUTPUT) + */ + if (zephyr | GPIO_OUTPUT) { + ec_flags |= GPIO_OUTPUT; + } + + return ec_flags; +} + +int gpio_get_default_flags(enum gpio_signal signal) +{ + return convert_from_zephyr_flags(configs[signal].init_flags); +} + +static int init_gpios(const struct device *unused) +{ + ARG_UNUSED(unused); + + for (size_t i = 0; i < ARRAY_SIZE(configs); ++i) { + data[i].dev = device_get_binding(configs[i].dev_name); + + if (data[i].dev == NULL) { + LOG_ERR("Not found (%s)", configs[i].name); + } + + const int rv = gpio_pin_configure(data[i].dev, configs[i].pin, + configs[i].init_flags); + + if (rv < 0) { + LOG_ERR("Config failed %s (%d)", configs[i].name, rv); + } + } + return 0; +} +SYS_INIT(init_gpios, PRE_KERNEL_1, 50); diff --git a/zephyr/shim/src/util.c b/zephyr/shim/src/util.c index 998a0db01d..6cd6e0dc68 100644 --- a/zephyr/shim/src/util.c +++ b/zephyr/shim/src/util.c @@ -5,6 +5,7 @@ #include #include +#include /* Int and Long are same size, just forward to existing Long implementation */ int strtoi(const char *nptr, char **endptr, int base) @@ -12,3 +13,15 @@ int strtoi(const char *nptr, char **endptr, int base) return strtol(nptr, endptr, base); } BUILD_ASSERT(sizeof(int) == sizeof(long)); + +int strcasecmp(const char *s1, const char *s2) +{ + int diff; + + do { + diff = tolower(*s1) - tolower(*s2); + if (diff) + return diff; + } while (*(s1++) && *(s2++)); + return 0; +} -- cgit v1.2.1