blob: 0dfb26036189ef552154513e3217092437ff9291 [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;
22 if (write(gpio->fd, buf, 1) != 1)
23 {
Norman James32e74e22015-09-15 21:28:06 -050024 rc = GPIO_WRITE_ERROR;
25 }
26 return rc;
Norman Jamese7594922015-08-27 14:25:24 -050027}
28
Norman James32e74e22015-09-15 21:28:06 -050029int gpio_write(GPIO* gpio, uint8_t value)
Norman Jamese7594922015-08-27 14:25:24 -050030{
Norman James65a295a2015-09-26 22:21:10 -050031 g_assert (gpio != NULL);
Norman James32e74e22015-09-15 21:28:06 -050032 int rc = GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -050033 char buf[1];
34 buf[0] = '0';
35 if (value==1)
36 {
37 buf[0]='1';
Patrick Williams3a8fa6e2016-08-24 14:04:22 -050038 }
Norman Jamese7594922015-08-27 14:25:24 -050039 if (write(gpio->fd, buf, 1) != 1)
40 {
Norman James32e74e22015-09-15 21:28:06 -050041 rc = GPIO_WRITE_ERROR;
42 }
43 return rc;
Norman Jamese7594922015-08-27 14:25:24 -050044}
45
Norman James88872672015-09-21 16:51:35 -050046int gpio_read(GPIO* gpio, uint8_t *value)
Norman Jamese7594922015-08-27 14:25:24 -050047{
Norman James65a295a2015-09-26 22:21:10 -050048 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -050049 char buf[1];
Norman James32e74e22015-09-15 21:28:06 -050050 int r = GPIO_OK;
Norman James8abb50c2015-09-16 10:58:16 -050051 if (gpio->fd <= 0)
Norman Jamese7594922015-08-27 14:25:24 -050052 {
Patrick Williams3a8fa6e2016-08-24 14:04:22 -050053 r = GPIO_ERROR;
Norman James8abb50c2015-09-16 10:58:16 -050054 }
55 else
56 {
57 if (read(gpio->fd,&buf,1) != 1)
58 {
Norman James8abb50c2015-09-16 10:58:16 -050059 r = GPIO_READ_ERROR;
Norman James32e74e22015-09-15 21:28:06 -050060 } else {
Norman James8abb50c2015-09-16 10:58:16 -050061 if (buf[0]=='1') {
62 *value = 1;
63 } else {
64 *value = 0;
65 }
Norman James32e74e22015-09-15 21:28:06 -050066 }
Norman Jamese7594922015-08-27 14:25:24 -050067 }
Norman James32e74e22015-09-15 21:28:06 -050068 return r;
Norman Jamese7594922015-08-27 14:25:24 -050069}
Norman James32e74e22015-09-15 21:28:06 -050070int gpio_clock_cycle(GPIO* gpio, int num_clks) {
Norman James65a295a2015-09-26 22:21:10 -050071 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -050072 int i=0;
Norman James32e74e22015-09-15 21:28:06 -050073 int r=GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -050074 for (i=0;i<num_clks;i++) {
Norman James32e74e22015-09-15 21:28:06 -050075 if (gpio_writec(gpio,'0') == -1) {
76 r = GPIO_WRITE_ERROR;
77 break;
78 }
79 if (gpio_writec(gpio,'1') == -1) {
80 r = GPIO_WRITE_ERROR;
81 break;
82 }
Norman Jamese7594922015-08-27 14:25:24 -050083 }
Norman James32e74e22015-09-15 21:28:06 -050084 return r;
Norman Jamese7594922015-08-27 14:25:24 -050085}
86
87// Gets the gpio device path from gpio manager object
Norman James32e74e22015-09-15 21:28:06 -050088int gpio_init(GDBusConnection *connection, GPIO* gpio)
Norman Jamese7594922015-08-27 14:25:24 -050089{
Norman James32e74e22015-09-15 21:28:06 -050090 int rc = GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -050091 GDBusProxy *proxy;
92 GError *error;
93 GVariant *result;
94
95 error = NULL;
96 g_assert_no_error (error);
97 error = NULL;
98 proxy = g_dbus_proxy_new_sync (connection,
99 G_DBUS_PROXY_FLAGS_NONE,
100 NULL, /* GDBusInterfaceInfo */
Norman Jamesddb97382015-08-27 21:31:31 -0500101 "org.openbmc.managers.System", /* name */
102 "/org/openbmc/managers/System", /* object path */
103 "org.openbmc.managers.System", /* interface */
Norman Jamese7594922015-08-27 14:25:24 -0500104 NULL, /* GCancellable */
105 &error);
Norman James32e74e22015-09-15 21:28:06 -0500106 if (error != NULL) {
107 return GPIO_LOOKUP_ERROR;
108 }
Norman Jamese7594922015-08-27 14:25:24 -0500109
110 result = g_dbus_proxy_call_sync (proxy,
Norman Jamesddb97382015-08-27 21:31:31 -0500111 "gpioInit",
Norman Jamese7594922015-08-27 14:25:24 -0500112 g_variant_new ("(s)", gpio->name),
113 G_DBUS_CALL_FLAGS_NONE,
114 -1,
115 NULL,
116 &error);
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500117
Norman James32e74e22015-09-15 21:28:06 -0500118 if (error != NULL) {
119 return GPIO_LOOKUP_ERROR;
120 }
Norman Jamese7594922015-08-27 14:25:24 -0500121 g_assert (result != NULL);
122 g_variant_get (result, "(&si&s)", &gpio->dev,&gpio->num,&gpio->direction);
123 g_print("GPIO Lookup: %s = %d,%s\n",gpio->name,gpio->num,gpio->direction);
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500124
Norman Jamese7594922015-08-27 14:25:24 -0500125 //export and set direction
126 char dev[254];
127 char data[4];
Norman James88872672015-09-21 16:51:35 -0500128 int fd;
Norman James32e74e22015-09-15 21:28:06 -0500129 do {
Norman James88872672015-09-21 16:51:35 -0500130 struct stat st;
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500131
Norman James5a7cc8d2015-10-06 12:31:06 -0500132 sprintf(dev,"%s/gpio%d/value",gpio->dev,gpio->num);
133 //check if gpio is exported, if not export
Norman James88872672015-09-21 16:51:35 -0500134 int result = stat(dev, &st);
135 if (result)
136 {
137 sprintf(dev,"%s/export",gpio->dev);
138 fd = open(dev, O_WRONLY);
139 if (fd == GPIO_ERROR) {
140 rc = GPIO_OPEN_ERROR;
141 break;
Patrick Williams3a8fa6e2016-08-24 14:04:22 -0500142 }
Norman James88872672015-09-21 16:51:35 -0500143 sprintf(data,"%d",gpio->num);
144 rc = write(fd,data,strlen(data));
145 close(fd);
146 if (rc != strlen(data)) {
147 rc = GPIO_WRITE_ERROR;
148 break;
149 }
Norman James32e74e22015-09-15 21:28:06 -0500150 }
Norman James5a7cc8d2015-10-06 12:31:06 -0500151 const char* file = "edge";
Patrick Williamsed1368d2016-08-24 14:23:45 -0500152 const char* direction = gpio->direction;
153 if (strcmp(direction, "in") == 0)
Norman James5a7cc8d2015-10-06 12:31:06 -0500154 {
155 file = "direction";
156 }
Patrick Williamsed1368d2016-08-24 14:23:45 -0500157 else if (strcmp(direction, "out") == 0)
158 {
159 file = "direction";
160
161 // Read current value, so we can set 'high' or 'low'.
162 // Setting direction directly to 'out' is the same as
163 // setting to 'low' which can change the value in the
164 // GPIO.
165 uint8_t value = 0;
166 rc = gpio_open(gpio);
167 if (rc) break;
168 rc = gpio_read(gpio, &value);
169 if (rc) break;
170 gpio_close(gpio);
171
172 direction = (value ? "high" : "low");
173 }
Norman James5a7cc8d2015-10-06 12:31:06 -0500174 sprintf(dev,"%s/gpio%d/%s",gpio->dev,gpio->num,file);
Norman James32e74e22015-09-15 21:28:06 -0500175 fd = open(dev,O_WRONLY);
176 if (fd == GPIO_ERROR) {
177 rc = GPIO_WRITE_ERROR;
178 break;
179 }
Patrick Williamsed1368d2016-08-24 14:23:45 -0500180 rc = write(fd,direction,strlen(direction));
181 if (rc != strlen(direction)) {
Norman James88872672015-09-21 16:51:35 -0500182 rc = GPIO_WRITE_ERROR;
183 break;
184 }
185
Norman James32e74e22015-09-15 21:28:06 -0500186 close(fd);
Norman James5a7cc8d2015-10-06 12:31:06 -0500187 rc = GPIO_OK;
Norman James32e74e22015-09-15 21:28:06 -0500188 } while(0);
Norman Jamese7594922015-08-27 14:25:24 -0500189
Norman James32e74e22015-09-15 21:28:06 -0500190 return rc;
Norman Jamese7594922015-08-27 14:25:24 -0500191}
Norman James5a7cc8d2015-10-06 12:31:06 -0500192
193
194
195
Norman James471ab592015-08-30 22:29:40 -0500196char* get_gpio_dev(GPIO* gpio)
197{
198 char* buf;
Patrick Williamsd6baab92016-08-24 14:05:55 -0500199 asprintf(&buf, "%s/gpio%d/value", gpio->dev, gpio->num);
Norman James471ab592015-08-30 22:29:40 -0500200 return buf;
201}
202
Norman James5a7cc8d2015-10-06 12:31:06 -0500203int gpio_open_interrupt(GPIO* gpio, GIOFunc func, gpointer user_data)
204{
205 int rc = GPIO_OK;
Norman James02b77f32015-10-28 18:59:29 -0500206 char buf[255];
Norman James5a7cc8d2015-10-06 12:31:06 -0500207 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
208 gpio->fd = open(buf, O_RDONLY | O_NONBLOCK );
Norman James02b77f32015-10-28 18:59:29 -0500209 gpio->irq_inited = false;
Norman James5a7cc8d2015-10-06 12:31:06 -0500210 if (gpio->fd == -1)
211 {
212 rc = GPIO_OPEN_ERROR;
213 }
214 else
215 {
Norman James02b77f32015-10-28 18:59:29 -0500216 GIOChannel* channel = g_io_channel_unix_new( gpio->fd);
Norman James5a7cc8d2015-10-06 12:31:06 -0500217 guint id = g_io_add_watch( channel, G_IO_PRI, func, user_data );
218 }
219 return rc;
220}
221
Norman Jamese7594922015-08-27 14:25:24 -0500222int gpio_open(GPIO* gpio)
223{
Norman James65a295a2015-09-26 22:21:10 -0500224 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -0500225 // open gpio for writing or reading
226 char buf[254];
Norman James32e74e22015-09-15 21:28:06 -0500227 int rc = 0;
Norman James5a7cc8d2015-10-06 12:31:06 -0500228 gpio->fd = -1;
Norman James65a295a2015-09-26 22:21:10 -0500229 if (gpio->direction == NULL) {
230 return GPIO_OPEN_ERROR;
231 }
Norman Jamese7594922015-08-27 14:25:24 -0500232 if (strcmp(gpio->direction,"in")==0)
233 {
234 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
235 gpio->fd = open(buf, O_RDONLY);
236 }
237 else
238 {
239 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
Norman James25571112015-12-15 09:36:28 -0600240 gpio->fd = open(buf, O_RDWR);
Norman Jamese7594922015-08-27 14:25:24 -0500241
242 }
Norman James88872672015-09-21 16:51:35 -0500243 if (gpio->fd == -1) {
244 return GPIO_OPEN_ERROR;
245 }
246 return GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -0500247}
248
249void gpio_close(GPIO* gpio)
250{
251 close(gpio->fd);
252}