summaryrefslogtreecommitdiffstats
path: root/common/ratp/gpio.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2018-09-12 15:45:46 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2018-09-17 09:50:41 +0200
commitec9a3703fbd2b80c48c7dce92f97c40fe39f4929 (patch)
tree90c672896cfc930517c65e54905d0aecc25dd0bf /common/ratp/gpio.c
parentde6d3aeec9a590c4eb53a953c8758f183ffeba1e (diff)
downloadbarebox-ec9a3703fbd2b80c48c7dce92f97c40fe39f4929.tar.gz
barebox-ec9a3703fbd2b80c48c7dce92f97c40fe39f4929.tar.xz
ratp: implement support for GPIO commands
Introduce three new RATP commands that allow getting and setting GPIO values as well as configuring the direction of the GPIO pins. Signed-off-by: Aleksander Morgado <aleksander@aleksander.es> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common/ratp/gpio.c')
-rw-r--r--common/ratp/gpio.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/common/ratp/gpio.c b/common/ratp/gpio.c
new file mode 100644
index 0000000000..d2c527a40c
--- /dev/null
+++ b/common/ratp/gpio.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2018 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright (c) 2018 Zodiac Inflight Innovations
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "barebox-ratp: gpio: " fmt
+
+#include <common.h>
+#include <ratp_bb.h>
+#include <malloc.h>
+#include <environment.h>
+#include <gpio.h>
+#include <errno.h>
+
+struct ratp_bb_gpio_get_value_request {
+ struct ratp_bb header;
+ uint32_t gpio;
+} __packed;
+
+struct ratp_bb_gpio_get_value_response {
+ struct ratp_bb header;
+ uint8_t value;
+} __packed;
+
+static int ratp_cmd_gpio_get_value(const struct ratp_bb *req, int req_len,
+ struct ratp_bb **rsp, int *rsp_len)
+{
+ struct ratp_bb_gpio_get_value_request *gpio_req = (struct ratp_bb_gpio_get_value_request *)req;
+ struct ratp_bb_gpio_get_value_response *gpio_rsp;
+ int gpio_rsp_len;
+
+ if (req_len < sizeof(*gpio_req)) {
+ pr_err("get value request ignored: size mismatch (%d < %zu)\n", req_len, sizeof(*gpio_req));
+ return 2;
+ }
+
+ gpio_rsp_len = sizeof(struct ratp_bb_gpio_get_value_response);
+ gpio_rsp = xzalloc(gpio_rsp_len);
+ gpio_rsp->header.type = cpu_to_be16(BB_RATP_TYPE_GPIO_GET_VALUE_RETURN);
+ gpio_rsp->value = !!gpio_get_value(be32_to_cpu(gpio_req->gpio));
+
+ *rsp_len = gpio_rsp_len;
+ *rsp = (struct ratp_bb *)gpio_rsp;
+ return 0;
+}
+
+BAREBOX_RATP_CMD_START(GPIO_GET_VALUE)
+ .request_id = BB_RATP_TYPE_GPIO_GET_VALUE,
+ .response_id = BB_RATP_TYPE_GPIO_GET_VALUE_RETURN,
+ .cmd = ratp_cmd_gpio_get_value
+BAREBOX_RATP_CMD_END
+
+
+struct ratp_bb_gpio_set_value_request {
+ struct ratp_bb header;
+ uint32_t gpio;
+ uint8_t value;
+} __packed;
+
+static int ratp_cmd_gpio_set_value(const struct ratp_bb *req, int req_len,
+ struct ratp_bb **rsp, int *rsp_len)
+{
+ struct ratp_bb_gpio_set_value_request *gpio_req = (struct ratp_bb_gpio_set_value_request *)req;
+
+ if (req_len < sizeof(*gpio_req)) {
+ pr_err("set value request ignored: size mismatch (%d < %zu)\n", req_len, sizeof(*gpio_req));
+ return 2;
+ }
+
+ gpio_set_value(be32_to_cpu(gpio_req->gpio), gpio_req->value);
+
+ *rsp_len = sizeof(struct ratp_bb);
+ *rsp = xzalloc(*rsp_len);
+ (*rsp)->type = cpu_to_be16(BB_RATP_TYPE_GPIO_SET_VALUE_RETURN);
+ return 0;
+}
+
+BAREBOX_RATP_CMD_START(GPIO_SET_VALUE)
+ .request_id = BB_RATP_TYPE_GPIO_SET_VALUE,
+ .response_id = BB_RATP_TYPE_GPIO_SET_VALUE_RETURN,
+ .cmd = ratp_cmd_gpio_set_value
+BAREBOX_RATP_CMD_END
+
+
+struct ratp_bb_gpio_set_direction_request {
+ struct ratp_bb header;
+ uint32_t gpio;
+ uint8_t direction; /* 0: input, 1: output */
+ uint8_t value; /* applicable only if direction output */
+} __packed;
+
+struct ratp_bb_gpio_set_direction_response {
+ struct ratp_bb header;
+ uint32_t errno;
+} __packed;
+
+static int ratp_cmd_gpio_set_direction(const struct ratp_bb *req, int req_len,
+ struct ratp_bb **rsp, int *rsp_len)
+{
+ struct ratp_bb_gpio_set_direction_request *gpio_req = (struct ratp_bb_gpio_set_direction_request *)req;
+ struct ratp_bb_gpio_set_direction_response *gpio_rsp;
+ int gpio_rsp_len;
+ uint32_t gpio;
+ int ret;
+
+ if (req_len < sizeof(*gpio_req)) {
+ pr_err("set direction request ignored: size mismatch (%d < %zu)\n", req_len, sizeof(*gpio_req));
+ return 2;
+ }
+
+ gpio = be32_to_cpu(gpio_req->gpio);
+ if (gpio_req->direction)
+ ret = gpio_direction_output(gpio, gpio_req->value);
+ else
+ ret = gpio_direction_input(gpio);
+
+ gpio_rsp_len = sizeof(struct ratp_bb_gpio_set_direction_response);
+ gpio_rsp = xzalloc(gpio_rsp_len);
+ gpio_rsp->header.type = cpu_to_be16(BB_RATP_TYPE_GPIO_SET_DIRECTION_RETURN);
+ gpio_rsp->errno = (ret == 0 ? 0 : EIO);
+
+ *rsp_len = gpio_rsp_len;
+ *rsp = (struct ratp_bb *)gpio_rsp;
+ return 0;
+}
+
+BAREBOX_RATP_CMD_START(GPIO_SET_DIRECTION)
+ .request_id = BB_RATP_TYPE_GPIO_SET_DIRECTION,
+ .response_id = BB_RATP_TYPE_GPIO_SET_DIRECTION_RETURN,
+ .cmd = ratp_cmd_gpio_set_direction
+BAREBOX_RATP_CMD_END