summaryrefslogtreecommitdiff
path: root/zephyr/shim/src/gpio.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /zephyr/shim/src/gpio.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-firmware-cherry-14454.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'zephyr/shim/src/gpio.c')
-rw-r--r--zephyr/shim/src/gpio.c441
1 files changed, 0 insertions, 441 deletions
diff --git a/zephyr/shim/src/gpio.c b/zephyr/shim/src/gpio.c
deleted file mode 100644
index 2bae272361..0000000000
--- a/zephyr/shim/src/gpio.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/* 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 <device.h>
-#include <init.h>
-#include <kernel.h>
-#include <logging/log.h>
-
-#include "gpio.h"
-#include "gpio/gpio.h"
-#include "sysjump.h"
-#include "cros_version.h"
-
-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 {
- /* GPIO net name */
- const char *name;
- /* Set at build time for lookup */
- const struct device *dev;
- /* Bit number of pin within device */
- gpio_pin_t pin;
- /* From DTS, excludes interrupts flags */
- gpio_flags_t init_flags;
-};
-
-#define GPIO_CONFIG(id) \
- COND_CODE_1( \
- DT_NODE_HAS_PROP(id, enum_name), \
- ( \
- { \
- .name = DT_LABEL(id), \
- .dev = DEVICE_DT_GET(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 {
- /* Runtime device for gpio port. Set during in init function */
- const struct device *dev;
-};
-
-#define GPIO_DATA(id) COND_CODE_1(DT_NODE_HAS_PROP(id, enum_name), ({}, ), ())
-static struct gpio_data data[] = {
-#if DT_NODE_EXISTS(DT_PATH(named_gpios))
- DT_FOREACH_CHILD(DT_PATH(named_gpios), GPIO_DATA)
-#endif
-};
-
-/* Maps platform/ec gpio callback information */
-struct gpio_signal_callback {
- /* The platform/ec gpio_signal */
- const enum gpio_signal signal;
- /* IRQ handler from platform/ec code */
- void (*const irq_handler)(enum gpio_signal signal);
- /* Interrupt-related gpio flags */
- const gpio_flags_t flags;
-};
-
-/*
- * Each zephyr project should define EC_CROS_GPIO_INTERRUPTS in their gpio_map.h
- * file if there are any interrupts that should be registered. The
- * corresponding handler will be declared here, which will prevent
- * needing to include headers with complex dependencies in gpio_map.h.
- *
- * EC_CROS_GPIO_INTERRUPTS is a space-separated list of GPIO_INT items.
- */
-
-/*
- * Validate interrupt flags are valid for the Zephyr GPIO driver.
- */
-#define IS_GPIO_INTERRUPT_FLAG(flag, mask) ((flag & mask) == mask)
-#define VALID_GPIO_INTERRUPT_FLAG(flag) \
- (IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_EDGE_RISING) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_EDGE_FALLING) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_EDGE_BOTH) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_LEVEL_LOW) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_LEVEL_HIGH) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_EDGE_TO_INACTIVE) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_EDGE_TO_ACTIVE) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_LEVEL_INACTIVE) || \
- IS_GPIO_INTERRUPT_FLAG(flag, GPIO_INT_LEVEL_ACTIVE))
-
-#define GPIO_INT(sig, f, cb) \
- BUILD_ASSERT(VALID_GPIO_INTERRUPT_FLAG(f), \
- STRINGIFY(sig) " is not using Zephyr interrupt flags");
-#ifdef EC_CROS_GPIO_INTERRUPTS
-EC_CROS_GPIO_INTERRUPTS
-#endif
-#undef GPIO_INT
-
-/*
- * Create unique enum values for each GPIO_INT entry, which also sets
- * the ZEPHYR_GPIO_INT_COUNT value.
- */
-#define ZEPHYR_GPIO_INT_ID(sig) INT_##sig
-#define GPIO_INT(sig, f, cb) ZEPHYR_GPIO_INT_ID(sig),
-enum zephyr_gpio_int_id {
-#ifdef EC_CROS_GPIO_INTERRUPTS
- EC_CROS_GPIO_INTERRUPTS
-#endif
- ZEPHYR_GPIO_INT_COUNT,
-};
-#undef GPIO_INT
-
-/* Create prototypes for each GPIO IRQ handler */
-#define GPIO_INT(sig, f, cb) void cb(enum gpio_signal signal);
-#ifdef EC_CROS_GPIO_INTERRUPTS
-EC_CROS_GPIO_INTERRUPTS
-#endif
-#undef GPIO_INT
-
-/*
- * The Zephyr gpio_callback data needs to be updated at runtime, so allocate
- * into uninitialized data (BSS). The constant data pulled from
- * EC_CROS_GPIO_INTERRUPTS is stored separately in the gpio_interrupts[] array.
- */
-static struct gpio_callback zephyr_gpio_callbacks[ZEPHYR_GPIO_INT_COUNT];
-
-#define ZEPHYR_GPIO_CALLBACK_TO_INDEX(cb) \
- (int)(((int)(cb) - (int)&zephyr_gpio_callbacks) / \
- sizeof(struct gpio_callback))
-
-#define GPIO_INT(sig, f, cb) \
- { \
- .signal = sig, \
- .flags = f, \
- .irq_handler = cb, \
- },
-const static struct gpio_signal_callback
- gpio_interrupts[ZEPHYR_GPIO_INT_COUNT] = {
-#ifdef EC_CROS_GPIO_INTERRUPTS
- EC_CROS_GPIO_INTERRUPTS
-#endif
-#undef GPIO_INT
- };
-
-/* The single zephyr gpio handler that routes to appropriate platform/ec cb */
-static void gpio_handler_shim(const struct device *port,
- struct gpio_callback *cb, gpio_port_pins_t pins)
-{
- int callback_index = ZEPHYR_GPIO_CALLBACK_TO_INDEX(cb);
- const struct gpio_signal_callback *const gpio =
- &gpio_interrupts[callback_index];
-
- /* Call the platform/ec gpio interrupt handler */
- gpio->irq_handler(gpio->signal);
-}
-
-/**
- * get_interrupt_from_signal() - Translate a gpio_signal to the
- * corresponding gpio_signal_callback
- *
- * @signal The signal to convert.
- *
- * Return: A pointer to the corresponding entry in gpio_interrupts, or
- * NULL if one does not exist.
- */
-const static struct gpio_signal_callback *
-get_interrupt_from_signal(enum gpio_signal signal)
-{
- if (!gpio_is_implemented(signal))
- return NULL;
-
- for (size_t i = 0; i < ARRAY_SIZE(gpio_interrupts); i++) {
- if (gpio_interrupts[i].signal == signal)
- return &gpio_interrupts[i];
- }
-
- LOG_ERR("No interrupt defined for GPIO %s", configs[signal].name);
- return NULL;
-}
-
-int gpio_is_implemented(enum gpio_signal signal)
-{
- return signal >= 0 && signal < ARRAY_SIZE(configs);
-}
-
-int gpio_get_level(enum gpio_signal signal)
-{
- if (!gpio_is_implemented(signal))
- return 0;
-
- 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;
-}
-
-int gpio_get_ternary(enum gpio_signal signal)
-{
- int pd, pu;
- int flags = gpio_get_default_flags(signal);
-
- /* Read GPIO with internal pull-down */
- gpio_set_flags(signal, GPIO_INPUT | GPIO_PULL_DOWN);
- pd = gpio_get_level(signal);
- udelay(100);
-
- /* Read GPIO with internal pull-up */
- gpio_set_flags(signal, GPIO_INPUT | GPIO_PULL_UP);
- pu = gpio_get_level(signal);
- udelay(100);
-
- /* Reset GPIO flags */
- gpio_set_flags(signal, flags);
-
- /* Check PU and PD readings to determine tristate */
- return pu && !pd ? 2 : pd;
-}
-
-const char *gpio_get_name(enum gpio_signal signal)
-{
- if (!gpio_is_implemented(signal))
- return "UNIMPLEMENTED";
-
- return configs[signal].name;
-}
-
-void gpio_set_level(enum gpio_signal signal, int value)
-{
- if (!gpio_is_implemented(signal))
- return;
-
- int rv = gpio_pin_set_raw(data[signal].dev, configs[signal].pin, value);
-
- if (rv < 0) {
- LOG_ERR("Cannot write %s (%d)", configs[signal].name, rv);
- }
-}
-
-void gpio_set_level_verbose(enum console_channel channel,
- enum gpio_signal signal, int value)
-{
- cprints(channel, "Set %s: %d", gpio_get_name(signal), value);
- gpio_set_level(signal, value);
-}
-
-/* GPIO flags which are the same in Zephyr and this codebase */
-#define GPIO_CONVERSION_SAME_BITS \
- (GPIO_OPEN_DRAIN | GPIO_PULL_UP | GPIO_PULL_DOWN | GPIO_INPUT | \
- GPIO_OUTPUT)
-
-static int convert_from_zephyr_flags(const gpio_flags_t zephyr)
-{
- /* Start out with the bits that are the same. */
- int ec_flags = zephyr & GPIO_CONVERSION_SAME_BITS;
- gpio_flags_t unhandled_flags = zephyr & ~GPIO_CONVERSION_SAME_BITS;
-
- /* TODO(b/173789980): handle conversion of more bits? */
- if (unhandled_flags) {
- LOG_WRN("Unhandled GPIO bits in zephyr->ec conversion: 0x%08X",
- unhandled_flags);
- }
-
- return ec_flags;
-}
-
-static gpio_flags_t convert_to_zephyr_flags(int ec_flags)
-{
- /* Start out with the bits that are the same. */
- gpio_flags_t zephyr_flags = ec_flags & GPIO_CONVERSION_SAME_BITS;
- int unhandled_flags = ec_flags & ~GPIO_CONVERSION_SAME_BITS;
-
- /* TODO(b/173789980): handle conversion of more bits? */
- if (unhandled_flags) {
- LOG_WRN("Unhandled GPIO bits in ec->zephyr conversion: 0x%08X",
- unhandled_flags);
- }
-
- return zephyr_flags;
-}
-
-int gpio_get_default_flags(enum gpio_signal signal)
-{
- if (!gpio_is_implemented(signal))
- return 0;
-
- return convert_from_zephyr_flags(configs[signal].init_flags);
-}
-
-static int init_gpios(const struct device *unused)
-{
- gpio_flags_t flags;
- struct jump_data *jdata;
- bool is_sys_jumped;
-
- ARG_UNUSED(unused);
-
- jdata = get_jump_data();
-
- if (jdata && jdata->magic == JUMP_DATA_MAGIC)
- is_sys_jumped = true;
- else
- is_sys_jumped = false;
-
- /* Loop through all GPIOs in device tree to set initial configuration */
- for (size_t i = 0; i < ARRAY_SIZE(configs); ++i) {
- data[i].dev = configs[i].dev;
- int rv;
-
- if (!device_is_ready(data[i].dev))
- LOG_ERR("Not found (%s)", configs[i].name);
-
- /*
- * The configs[i].init_flags variable is read-only, so the
- * following assignment is needed because the flags need
- * adjusting on a warm reboot.
- */
- flags = configs[i].init_flags;
-
- if (is_sys_jumped) {
- flags &=
- ~(GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH);
- }
-
- rv = gpio_pin_configure(data[i].dev, configs[i].pin, flags);
- if (rv < 0) {
- LOG_ERR("Config failed %s (%d)", configs[i].name, rv);
- }
- }
-
- /*
- * Loop through all interrupt pins and set their callback.
- */
- for (size_t i = 0; i < ARRAY_SIZE(gpio_interrupts); ++i) {
- const enum gpio_signal signal = gpio_interrupts[i].signal;
- int rv;
-
- if (signal == GPIO_UNIMPLEMENTED)
- continue;
-
- gpio_init_callback(&zephyr_gpio_callbacks[i], gpio_handler_shim,
- BIT(configs[signal].pin));
- rv = gpio_add_callback(data[signal].dev,
- &zephyr_gpio_callbacks[i]);
-
- if (rv < 0) {
- LOG_ERR("Callback reg failed %s (%d)",
- configs[signal].name, rv);
- continue;
- }
- }
-
- /* Configure unused pins in chip driver for better power consumption */
- if (gpio_config_unused_pins) {
- int rv;
-
- rv = gpio_config_unused_pins();
- if (rv < 0) {
- return rv;
- }
- }
-
- return 0;
-}
-#if CONFIG_PLATFORM_EC_GPIO_INIT_PRIORITY <= CONFIG_KERNEL_INIT_PRIORITY_DEFAULT
-#error "GPIOs must initialize after the kernel default initialization"
-#endif
-SYS_INIT(init_gpios, POST_KERNEL, CONFIG_PLATFORM_EC_GPIO_INIT_PRIORITY);
-
-int gpio_enable_interrupt(enum gpio_signal signal)
-{
- int rv;
- const struct gpio_signal_callback *interrupt;
-
- interrupt = get_interrupt_from_signal(signal);
-
- if (!interrupt)
- return -1;
-
- /*
- * Config interrupt flags (e.g. INT_EDGE_BOTH) & enable interrupt
- * together.
- */
- rv = gpio_pin_interrupt_configure(data[signal].dev, configs[signal].pin,
- (interrupt->flags | GPIO_INT_ENABLE) &
- ~GPIO_INT_DISABLE);
- if (rv < 0) {
- LOG_ERR("Failed to enable interrupt on %s (%d)",
- configs[signal].name, rv);
- }
-
- return rv;
-}
-
-int gpio_disable_interrupt(enum gpio_signal signal)
-{
- int rv;
-
- if (!gpio_is_implemented(signal))
- return -1;
-
- rv = gpio_pin_interrupt_configure(data[signal].dev, configs[signal].pin,
- GPIO_INT_DISABLE);
- if (rv < 0) {
- LOG_ERR("Failed to disable interrupt on %s (%d)",
- configs[signal].name, rv);
- }
-
- return rv;
-}
-
-void gpio_reset(enum gpio_signal signal)
-{
- if (!gpio_is_implemented(signal))
- return;
-
- gpio_pin_configure(data[signal].dev, configs[signal].pin,
- configs[signal].init_flags);
-}
-
-void gpio_set_flags(enum gpio_signal signal, int flags)
-{
- if (!gpio_is_implemented(signal))
- return;
-
- gpio_pin_configure(data[signal].dev, configs[signal].pin,
- convert_to_zephyr_flags(flags));
-}
-
-int signal_is_gpio(int signal)
-{
- return true;
-}