summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/build.mk2
-rw-r--r--common/gpio.c207
-rw-r--r--common/gpio_commands.c208
-rw-r--r--include/gpio.h19
4 files changed, 235 insertions, 201 deletions
diff --git a/common/build.mk b/common/build.mk
index ba7c1a38b1..4995cfe6e8 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -33,7 +33,7 @@ common-$(CONFIG_CHARGER)+=charger.o
common-$(CONFIG_CHARGER_V1)+=charge_state_v1.o
common-$(CONFIG_CHARGER_V2)+=charge_state_v2.o
common-$(CONFIG_CMD_I2CWEDGE)+=i2c_wedge.o
-common-$(CONFIG_COMMON_GPIO)+=gpio.o
+common-$(CONFIG_COMMON_GPIO)+=gpio.o gpio_commands.o
common-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic_output.o
common-$(CONFIG_COMMON_RUNTIME)+=hooks.o main.o system.o shared_mem.o
common-$(CONFIG_COMMON_TIMER)+=timer.o
diff --git a/common/gpio.c b/common/gpio.c
index e8652e7e9e..817662f743 100644
--- a/common/gpio.c
+++ b/common/gpio.c
@@ -6,59 +6,10 @@
/* GPIO common functionality for Chrome EC */
#include "common.h"
-#include "console.h"
#include "gpio.h"
-#include "host_command.h"
#include "registers.h"
-#include "system.h"
#include "util.h"
-static uint8_t last_val[(GPIO_COUNT + 7) / 8];
-
-/**
- * Find a GPIO signal by name.
- *
- * @param name Signal name to find
- *
- * @return the signal index, or GPIO_COUNT if no match.
- */
-static enum gpio_signal find_signal_by_name(const char *name)
-{
- const struct gpio_info *g = gpio_list;
- int i;
-
- if (!name || !*name)
- return GPIO_COUNT;
-
- for (i = 0; i < GPIO_COUNT; i++, g++) {
- if (g->mask && !strcasecmp(name, g->name))
- return i;
- }
-
- return GPIO_COUNT;
-}
-
-/**
- * Update last_val
- *
- * @param i Index of last_val[] to update
- * @param v New value for last_val[i]
- *
- * @return 1 if last_val[i] was updated, 0 if last_val[i]==v.
- */
-static int last_val_changed(int i, int v)
-{
- if (v && !(last_val[i / 8] & (1 << (i % 8)))) {
- last_val[i / 8] |= 1 << (i % 8);
- return 1;
- } else if (!v && last_val[i / 8] & (1 << (i % 8))) {
- last_val[i / 8] &= ~(1 << (i % 8));
- return 1;
- } else {
- return 0;
- }
-}
-
/* GPIO alternate function structure */
struct gpio_alt_func {
/* Port base address */
@@ -162,6 +113,11 @@ void gpio_set_flags(enum gpio_signal signal, int flags)
gpio_set_flags_by_mask(g->port, g->mask, flags);
}
+int gpio_get_default_flags(enum gpio_signal signal)
+{
+ return gpio_list[signal].flags;
+}
+
void gpio_reset(enum gpio_signal signal)
{
const struct gpio_info *g = gpio_list + signal;
@@ -175,158 +131,9 @@ const char *gpio_get_name(enum gpio_signal signal)
return gpio_list[signal].name;
}
-/*****************************************************************************/
-/* Console commands */
-
-static int command_gpio_get(int argc, char **argv)
-{
- const struct gpio_info *g = gpio_list;
- int changed, v, i;
-
- /* If a signal is specified, print only that one */
- if (argc == 2) {
- i = find_signal_by_name(argv[1]);
- if (i == GPIO_COUNT)
- return EC_ERROR_PARAM1;
- g = gpio_list + i;
- v = gpio_get_level(i);
- changed = last_val_changed(i, v);
- ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '), g->name);
-
- return EC_SUCCESS;
- }
-
- /* Otherwise print them all */
- for (i = 0; i < GPIO_COUNT; i++, g++) {
- if (!g->mask)
- continue; /* Skip unsupported signals */
-
- v = gpio_get_level(i);
- changed = last_val_changed(i, v);
- ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '), g->name);
-
- /* Flush console to avoid truncating output */
- cflush();
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(gpioget, command_gpio_get,
- "[name]",
- "Read GPIO value(s)",
- NULL);
-
-static int command_gpio_set(int argc, char **argv)
+int gpio_is_implemented(enum gpio_signal signal)
{
- const struct gpio_info *g;
- char *e;
- int v, i;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- i = find_signal_by_name(argv[1]);
- if (i == GPIO_COUNT)
- return EC_ERROR_PARAM1;
- g = gpio_list + i;
-
- if (!g->mask)
- return EC_ERROR_PARAM1;
-
- if (!(g->flags & GPIO_OUTPUT))
- return EC_ERROR_PARAM1;
-
- v = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- gpio_set_level(i, v);
-
- return EC_SUCCESS;
+ return !!gpio_list[signal].mask;
}
-DECLARE_CONSOLE_COMMAND(gpioset, command_gpio_set,
- "name <0 | 1>",
- "Set a GPIO",
- NULL);
/*****************************************************************************/
-/* Host commands */
-
-static int gpio_command_get(struct host_cmd_handler_args *args)
-{
- const struct gpio_info *g = gpio_list;
- const struct ec_params_gpio_get_v1 *p_v1 = args->params;
- struct ec_response_gpio_get_v1 *r_v1 = args->response;
- int i, len;
-
- if (args->version == 0) {
- const struct ec_params_gpio_get *p = args->params;
- struct ec_response_gpio_get *r = args->response;
- i = find_signal_by_name(p->name);
- if (i == GPIO_COUNT)
- return EC_RES_ERROR;
-
- r->val = gpio_get_level(i);
- args->response_size = sizeof(struct ec_response_gpio_get);
- return EC_RES_SUCCESS;
- }
-
- switch (p_v1->subcmd) {
- case EC_GPIO_GET_BY_NAME:
- i = find_signal_by_name(p_v1->get_value_by_name.name);
- if (i == GPIO_COUNT)
- return EC_RES_ERROR;
-
- r_v1->get_value_by_name.val = gpio_get_level(i);
- args->response_size = sizeof(r_v1->get_value_by_name);
- break;
- case EC_GPIO_GET_COUNT:
- r_v1->get_count.val = GPIO_COUNT;
- args->response_size = sizeof(r_v1->get_count);
- break;
- case EC_GPIO_GET_INFO:
- if (p_v1->get_info.index >= GPIO_COUNT)
- return EC_RES_ERROR;
-
- i = p_v1->get_info.index;
- len = strlen(g[i].name);
- memcpy(r_v1->get_info.name, g[i].name, len+1);
- r_v1->get_info.val = gpio_get_level(i);
- r_v1->get_info.flags = g[i].flags;
- args->response_size = sizeof(r_v1->get_info);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- return EC_RES_SUCCESS;
-
-}
-DECLARE_HOST_COMMAND(EC_CMD_GPIO_GET, gpio_command_get,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static int gpio_command_set(struct host_cmd_handler_args *args)
-{
- const struct ec_params_gpio_set *p = args->params;
- const struct gpio_info *g;
- int i;
-
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
-
- i = find_signal_by_name(p->name);
- if (i == GPIO_COUNT)
- return EC_RES_ERROR;
- g = gpio_list + i;
-
- if (!g->mask)
- return EC_RES_ERROR;
-
- if (!(g->flags & GPIO_OUTPUT))
- return EC_RES_ERROR;
-
- gpio_set_level(i, p->val);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GPIO_SET, gpio_command_set, EC_VER_MASK(0));
diff --git a/common/gpio_commands.c b/common/gpio_commands.c
new file mode 100644
index 0000000000..25185597ea
--- /dev/null
+++ b/common/gpio_commands.c
@@ -0,0 +1,208 @@
+/* Copyright (c) 2013 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.
+ */
+
+/* GPIO common functionality for Chrome EC */
+
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "host_command.h"
+#include "system.h"
+#include "util.h"
+
+static uint8_t last_val[(GPIO_COUNT + 7) / 8];
+
+/**
+ * Find a GPIO signal by name.
+ *
+ * @param name Signal name to find
+ *
+ * @return the signal index, or GPIO_COUNT if no match.
+ */
+static enum gpio_signal find_signal_by_name(const char *name)
+{
+ int i;
+
+ if (!name || !*name)
+ return GPIO_COUNT;
+
+ for (i = 0; i < GPIO_COUNT; i++)
+ if (gpio_is_implemented(i) &&
+ !strcasecmp(name, gpio_get_name(i)))
+ return i;
+
+ return GPIO_COUNT;
+}
+
+/**
+ * Update last_val
+ *
+ * @param i Index of last_val[] to update
+ * @param v New value for last_val[i]
+ *
+ * @return 1 if last_val[i] was updated, 0 if last_val[i]==v.
+ */
+static int last_val_changed(int i, int v)
+{
+ if (v && !(last_val[i / 8] & (1 << (i % 8)))) {
+ last_val[i / 8] |= 1 << (i % 8);
+ return 1;
+ } else if (!v && last_val[i / 8] & (1 << (i % 8))) {
+ last_val[i / 8] &= ~(1 << (i % 8));
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static enum ec_error_list set(const char *name, int value)
+{
+ enum gpio_signal signal = find_signal_by_name(name);
+
+ if (signal == GPIO_COUNT)
+ return EC_ERROR_INVAL;
+
+ if (!gpio_is_implemented(signal))
+ return EC_ERROR_INVAL;
+
+ if (!(gpio_get_default_flags(signal) & GPIO_OUTPUT))
+ return EC_ERROR_INVAL;
+
+ gpio_set_level(signal, value);
+
+ return EC_SUCCESS;
+}
+/*****************************************************************************/
+/* Console commands */
+
+static int command_gpio_get(int argc, char **argv)
+{
+ int changed, v, i;
+
+ /* If a signal is specified, print only that one */
+ if (argc == 2) {
+ i = find_signal_by_name(argv[1]);
+ if (i == GPIO_COUNT)
+ return EC_ERROR_PARAM1;
+ v = gpio_get_level(i);
+ changed = last_val_changed(i, v);
+ ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '),
+ gpio_get_name(i));
+
+ return EC_SUCCESS;
+ }
+
+ /* Otherwise print them all */
+ for (i = 0; i < GPIO_COUNT; i++) {
+ if (!gpio_is_implemented(i))
+ continue; /* Skip unsupported signals */
+
+ v = gpio_get_level(i);
+ changed = last_val_changed(i, v);
+ ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '),
+ gpio_get_name(i));
+
+ /* Flush console to avoid truncating output */
+ cflush();
+ }
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(gpioget, command_gpio_get,
+ "[name]",
+ "Read GPIO value(s)",
+ NULL);
+
+static int command_gpio_set(int argc, char **argv)
+{
+ char *e;
+ int v;
+
+ if (argc < 3)
+ return EC_ERROR_PARAM_COUNT;
+
+ v = strtoi(argv[2], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM2;
+
+ if (set(argv[1], v) != EC_SUCCESS)
+ return EC_ERROR_PARAM1;
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(gpioset, command_gpio_set,
+ "name <0 | 1>",
+ "Set a GPIO",
+ NULL);
+
+/*****************************************************************************/
+/* Host commands */
+
+static int gpio_command_get(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_gpio_get_v1 *p_v1 = args->params;
+ struct ec_response_gpio_get_v1 *r_v1 = args->response;
+ int i, len;
+
+ if (args->version == 0) {
+ const struct ec_params_gpio_get *p = args->params;
+ struct ec_response_gpio_get *r = args->response;
+
+ i = find_signal_by_name(p->name);
+ if (i == GPIO_COUNT)
+ return EC_RES_ERROR;
+
+ r->val = gpio_get_level(i);
+ args->response_size = sizeof(struct ec_response_gpio_get);
+ return EC_RES_SUCCESS;
+ }
+
+ switch (p_v1->subcmd) {
+ case EC_GPIO_GET_BY_NAME:
+ i = find_signal_by_name(p_v1->get_value_by_name.name);
+ if (i == GPIO_COUNT)
+ return EC_RES_ERROR;
+
+ r_v1->get_value_by_name.val = gpio_get_level(i);
+ args->response_size = sizeof(r_v1->get_value_by_name);
+ break;
+ case EC_GPIO_GET_COUNT:
+ r_v1->get_count.val = GPIO_COUNT;
+ args->response_size = sizeof(r_v1->get_count);
+ break;
+ case EC_GPIO_GET_INFO:
+ if (p_v1->get_info.index >= GPIO_COUNT)
+ return EC_RES_ERROR;
+
+ i = p_v1->get_info.index;
+ len = strlen(gpio_get_name(i));
+ memcpy(r_v1->get_info.name, gpio_get_name(i), len+1);
+ r_v1->get_info.val = gpio_get_level(i);
+ r_v1->get_info.flags = gpio_get_default_flags(i);
+ args->response_size = sizeof(r_v1->get_info);
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
+ return EC_RES_SUCCESS;
+
+}
+DECLARE_HOST_COMMAND(EC_CMD_GPIO_GET, gpio_command_get,
+ EC_VER_MASK(0) | EC_VER_MASK(1));
+
+static int gpio_command_set(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_gpio_set *p = args->params;
+
+ if (system_is_locked())
+ return EC_RES_ACCESS_DENIED;
+
+ if (set(p->name, p->val) != EC_SUCCESS)
+ return EC_RES_ERROR;
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_GPIO_SET, gpio_command_set, EC_VER_MASK(0));
diff --git a/include/gpio.h b/include/gpio.h
index d7dcd9d3ca..7c0a4cad22 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -128,6 +128,17 @@ int gpio_get_level(enum gpio_signal signal);
const char *gpio_get_name(enum gpio_signal signal);
/**
+ * Determine if a GPIO is implemented.
+ *
+ * Some well known GPIO signal names may not be implemented on a particular
+ * board. This function can be used to determine if a GPIO is implemented.
+ *
+ * @param signal Signal to query
+ * @returns 0 if the GPIO is not implemented, 1 if it is.
+ */
+int gpio_is_implemented(enum gpio_signal signal);
+
+/**
* Set the flags for a signal.
*
* @param signal Signal to set flags for
@@ -136,6 +147,14 @@ const char *gpio_get_name(enum gpio_signal signal);
void gpio_set_flags(enum gpio_signal signal, int flags);
/**
+ * Get the default flags for a signal.
+ *
+ * @param signal Signal to set flags for
+ * @returns The flags that were originally defined for this signal
+ */
+int gpio_get_default_flags(enum gpio_signal signal);
+
+/**
* Set the value of a signal.
*
* @param signal Signal to set