blob: 291f9c3ffaa05d88db7ce60f9d6bc9753af9c442 [file] [log] [blame]
Patrick Williamsd6baab92016-08-24 14:05:55 -05001#define _GNU_SOURCE
2
Norman Jamese7594922015-08-27 14:25:24 -05003#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <fcntl.h>
8#include <unistd.h>
9#include <argp.h>
10#include <sys/stat.h>
11#include <sys/mman.h>
Brad Bishopf6c85682016-06-27 11:56:39 -040012#include "openbmc_intf.h"
Norman Jamese7594922015-08-27 14:25:24 -050013#include "gpio.h"
14
15
Norman James32e74e22015-09-15 21:28:06 -050016int gpio_writec(GPIO* gpio, char value)
Norman Jamese7594922015-08-27 14:25:24 -050017{
Norman James65a295a2015-09-26 22:21:10 -050018 g_assert (gpio != NULL);
Norman James32e74e22015-09-15 21:28:06 -050019 int rc = GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -050020 char buf[1];
21 buf[0] = value;
Yong Li86101ea2017-11-17 14:34:18 +080022
23 if (lseek(gpio->fd, 0, SEEK_SET) == -1)
24 {
25 return GPIO_ERROR;
26 }
27
Norman Jamese7594922015-08-27 14:25:24 -050028 if (write(gpio->fd, buf, 1) != 1)
29 {
Norman James32e74e22015-09-15 21:28:06 -050030 rc = GPIO_WRITE_ERROR;
31 }
32 return rc;
Norman Jamese7594922015-08-27 14:25:24 -050033}
34
Norman James32e74e22015-09-15 21:28:06 -050035int gpio_write(GPIO* gpio, uint8_t value)
Norman Jamese7594922015-08-27 14:25:24 -050036{
Norman James65a295a2015-09-26 22:21:10 -050037 g_assert (gpio != NULL);
Norman James32e74e22015-09-15 21:28:06 -050038 int rc = GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -050039 char buf[1];
40 buf[0] = '0';
41 if (value==1)
42 {
43 buf[0]='1';
Patrick Williams3a8fa6e2016-08-24 14:04:22 -050044 }
Yong Li86101ea2017-11-17 14:34:18 +080045
46 if (lseek(gpio->fd, 0, SEEK_SET) == -1)
47 {
48 return GPIO_ERROR;
49 }
50
Norman Jamese7594922015-08-27 14:25:24 -050051 if (write(gpio->fd, buf, 1) != 1)
52 {
Norman James32e74e22015-09-15 21:28:06 -050053 rc = GPIO_WRITE_ERROR;
54 }
55 return rc;
Norman Jamese7594922015-08-27 14:25:24 -050056}
57
Norman James88872672015-09-21 16:51:35 -050058int gpio_read(GPIO* gpio, uint8_t *value)
Norman Jamese7594922015-08-27 14:25:24 -050059{
Norman James65a295a2015-09-26 22:21:10 -050060 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -050061 char buf[1];
Norman James32e74e22015-09-15 21:28:06 -050062 int r = GPIO_OK;
Norman James8abb50c2015-09-16 10:58:16 -050063 if (gpio->fd <= 0)
Norman Jamese7594922015-08-27 14:25:24 -050064 {
Patrick Williams3a8fa6e2016-08-24 14:04:22 -050065 r = GPIO_ERROR;
Norman James8abb50c2015-09-16 10:58:16 -050066 }
67 else
68 {
Yong Li86101ea2017-11-17 14:34:18 +080069 if (lseek(gpio->fd, 0, SEEK_SET) == -1)
70 {
71 return GPIO_ERROR;
72 }
73
Norman James8abb50c2015-09-16 10:58:16 -050074 if (read(gpio->fd,&buf,1) != 1)
75 {
Norman James8abb50c2015-09-16 10:58:16 -050076 r = GPIO_READ_ERROR;
Norman James32e74e22015-09-15 21:28:06 -050077 } else {
Norman James8abb50c2015-09-16 10:58:16 -050078 if (buf[0]=='1') {
79 *value = 1;
80 } else {
81 *value = 0;
82 }
Norman James32e74e22015-09-15 21:28:06 -050083 }
Norman Jamese7594922015-08-27 14:25:24 -050084 }
Norman James32e74e22015-09-15 21:28:06 -050085 return r;
Norman Jamese7594922015-08-27 14:25:24 -050086}
Norman James32e74e22015-09-15 21:28:06 -050087int gpio_clock_cycle(GPIO* gpio, int num_clks) {
Norman James65a295a2015-09-26 22:21:10 -050088 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -050089 int i=0;
Norman James32e74e22015-09-15 21:28:06 -050090 int r=GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -050091 for (i=0;i<num_clks;i++) {
Norman James32e74e22015-09-15 21:28:06 -050092 if (gpio_writec(gpio,'0') == -1) {
93 r = GPIO_WRITE_ERROR;
94 break;
95 }
96 if (gpio_writec(gpio,'1') == -1) {
97 r = GPIO_WRITE_ERROR;
98 break;
99 }
Norman Jamese7594922015-08-27 14:25:24 -0500100 }
Norman James32e74e22015-09-15 21:28:06 -0500101 return r;
Norman Jamese7594922015-08-27 14:25:24 -0500102}
103
104// Gets the gpio device path from gpio manager object
Norman James32e74e22015-09-15 21:28:06 -0500105int gpio_init(GDBusConnection *connection, GPIO* gpio)
Norman Jamese7594922015-08-27 14:25:24 -0500106{
Norman James32e74e22015-09-15 21:28:06 -0500107 int rc = GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -0500108 GDBusProxy *proxy;
109 GError *error;
110 GVariant *result;
111
112 error = NULL;
113 g_assert_no_error (error);
114 error = NULL;
115 proxy = g_dbus_proxy_new_sync (connection,
116 G_DBUS_PROXY_FLAGS_NONE,
117 NULL, /* GDBusInterfaceInfo */
Norman Jamesddb97382015-08-27 21:31:31 -0500118 "org.openbmc.managers.System", /* name */
119 "/org/openbmc/managers/System", /* object path */
120 "org.openbmc.managers.System", /* interface */
Norman Jamese7594922015-08-27 14:25:24 -0500121 NULL, /* GCancellable */
122 &error);
Norman James32e74e22015-09-15 21:28:06 -0500123 if (error != NULL) {
124 return GPIO_LOOKUP_ERROR;
125 }
Norman Jamese7594922015-08-27 14:25:24 -0500126
127 result = g_dbus_proxy_call_sync (proxy,
Norman Jamesddb97382015-08-27 21:31:31 -0500128 "gpioInit",
Norman Jamese7594922015-08-27 14:25:24 -0500129 g_variant_new ("(s)", gpio->name),
130 G_DBUS_CALL_FLAGS_NONE,
131 -1,
132 NULL,
133 &error);
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500134
Norman James32e74e22015-09-15 21:28:06 -0500135 if (error != NULL) {
136 return GPIO_LOOKUP_ERROR;
137 }
Norman Jamese7594922015-08-27 14:25:24 -0500138 g_assert (result != NULL);
139 g_variant_get (result, "(&si&s)", &gpio->dev,&gpio->num,&gpio->direction);
140 g_print("GPIO Lookup: %s = %d,%s\n",gpio->name,gpio->num,gpio->direction);
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500141
Norman Jamese7594922015-08-27 14:25:24 -0500142 //export and set direction
143 char dev[254];
144 char data[4];
Norman James88872672015-09-21 16:51:35 -0500145 int fd;
Norman James32e74e22015-09-15 21:28:06 -0500146 do {
Norman James88872672015-09-21 16:51:35 -0500147 struct stat st;
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500148
Norman James5a7cc8d2015-10-06 12:31:06 -0500149 sprintf(dev,"%s/gpio%d/value",gpio->dev,gpio->num);
150 //check if gpio is exported, if not export
Norman James88872672015-09-21 16:51:35 -0500151 int result = stat(dev, &st);
152 if (result)
153 {
154 sprintf(dev,"%s/export",gpio->dev);
155 fd = open(dev, O_WRONLY);
156 if (fd == GPIO_ERROR) {
157 rc = GPIO_OPEN_ERROR;
158 break;
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500159 }
Norman James88872672015-09-21 16:51:35 -0500160 sprintf(data,"%d",gpio->num);
161 rc = write(fd,data,strlen(data));
162 close(fd);
163 if (rc != strlen(data)) {
164 rc = GPIO_WRITE_ERROR;
165 break;
166 }
Norman James32e74e22015-09-15 21:28:06 -0500167 }
Norman James5a7cc8d2015-10-06 12:31:06 -0500168 const char* file = "edge";
Patrick Williamsed1368d2016-08-24 14:23:45 -0500169 const char* direction = gpio->direction;
170 if (strcmp(direction, "in") == 0)
Norman James5a7cc8d2015-10-06 12:31:06 -0500171 {
172 file = "direction";
173 }
Patrick Williamsed1368d2016-08-24 14:23:45 -0500174 else if (strcmp(direction, "out") == 0)
175 {
176 file = "direction";
177
178 // Read current value, so we can set 'high' or 'low'.
179 // Setting direction directly to 'out' is the same as
180 // setting to 'low' which can change the value in the
181 // GPIO.
182 uint8_t value = 0;
183 rc = gpio_open(gpio);
184 if (rc) break;
185 rc = gpio_read(gpio, &value);
186 if (rc) break;
187 gpio_close(gpio);
188
189 direction = (value ? "high" : "low");
190 }
Norman James5a7cc8d2015-10-06 12:31:06 -0500191 sprintf(dev,"%s/gpio%d/%s",gpio->dev,gpio->num,file);
Norman James32e74e22015-09-15 21:28:06 -0500192 fd = open(dev,O_WRONLY);
193 if (fd == GPIO_ERROR) {
194 rc = GPIO_WRITE_ERROR;
195 break;
196 }
Patrick Williamsed1368d2016-08-24 14:23:45 -0500197 rc = write(fd,direction,strlen(direction));
198 if (rc != strlen(direction)) {
Norman James88872672015-09-21 16:51:35 -0500199 rc = GPIO_WRITE_ERROR;
200 break;
201 }
202
Norman James32e74e22015-09-15 21:28:06 -0500203 close(fd);
Norman James5a7cc8d2015-10-06 12:31:06 -0500204 rc = GPIO_OK;
Norman James32e74e22015-09-15 21:28:06 -0500205 } while(0);
Norman Jamese7594922015-08-27 14:25:24 -0500206
Norman James32e74e22015-09-15 21:28:06 -0500207 return rc;
Norman Jamese7594922015-08-27 14:25:24 -0500208}
Norman James5a7cc8d2015-10-06 12:31:06 -0500209
210
211
212
Norman James471ab592015-08-30 22:29:40 -0500213char* get_gpio_dev(GPIO* gpio)
214{
215 char* buf;
Patrick Williamsd6baab92016-08-24 14:05:55 -0500216 asprintf(&buf, "%s/gpio%d/value", gpio->dev, gpio->num);
Norman James471ab592015-08-30 22:29:40 -0500217 return buf;
218}
219
Norman James5a7cc8d2015-10-06 12:31:06 -0500220int gpio_open_interrupt(GPIO* gpio, GIOFunc func, gpointer user_data)
221{
222 int rc = GPIO_OK;
Norman James02b77f32015-10-28 18:59:29 -0500223 char buf[255];
Norman James5a7cc8d2015-10-06 12:31:06 -0500224 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
225 gpio->fd = open(buf, O_RDONLY | O_NONBLOCK );
Norman James02b77f32015-10-28 18:59:29 -0500226 gpio->irq_inited = false;
Norman James5a7cc8d2015-10-06 12:31:06 -0500227 if (gpio->fd == -1)
228 {
229 rc = GPIO_OPEN_ERROR;
230 }
231 else
232 {
Norman James02b77f32015-10-28 18:59:29 -0500233 GIOChannel* channel = g_io_channel_unix_new( gpio->fd);
Norman James5a7cc8d2015-10-06 12:31:06 -0500234 guint id = g_io_add_watch( channel, G_IO_PRI, func, user_data );
235 }
236 return rc;
237}
238
Norman Jamese7594922015-08-27 14:25:24 -0500239int gpio_open(GPIO* gpio)
240{
Norman James65a295a2015-09-26 22:21:10 -0500241 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -0500242 // open gpio for writing or reading
243 char buf[254];
Norman James32e74e22015-09-15 21:28:06 -0500244 int rc = 0;
Norman James5a7cc8d2015-10-06 12:31:06 -0500245 gpio->fd = -1;
Norman James65a295a2015-09-26 22:21:10 -0500246 if (gpio->direction == NULL) {
247 return GPIO_OPEN_ERROR;
248 }
Norman Jamese7594922015-08-27 14:25:24 -0500249 if (strcmp(gpio->direction,"in")==0)
250 {
251 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
252 gpio->fd = open(buf, O_RDONLY);
253 }
254 else
255 {
256 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
Norman James25571112015-12-15 09:36:28 -0600257 gpio->fd = open(buf, O_RDWR);
Norman Jamese7594922015-08-27 14:25:24 -0500258
259 }
Norman James88872672015-09-21 16:51:35 -0500260 if (gpio->fd == -1) {
261 return GPIO_OPEN_ERROR;
262 }
263 return GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -0500264}
265
266void gpio_close(GPIO* gpio)
267{
268 close(gpio->fd);
269}