blob: e48eff4498b61ea8bb21530e2fd4f4a1461468d8 [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";
152 if (strcmp(gpio->direction,"in")==0 || strcmp(gpio->direction,"out")==0)
153 {
154 file = "direction";
155 }
156 sprintf(dev,"%s/gpio%d/%s",gpio->dev,gpio->num,file);
Norman James32e74e22015-09-15 21:28:06 -0500157 fd = open(dev,O_WRONLY);
158 if (fd == GPIO_ERROR) {
159 rc = GPIO_WRITE_ERROR;
160 break;
161 }
162 rc = write(fd,gpio->direction,strlen(gpio->direction));
Norman James88872672015-09-21 16:51:35 -0500163 if (rc != strlen(gpio->direction)) {
164 rc = GPIO_WRITE_ERROR;
165 break;
166 }
167
Norman James32e74e22015-09-15 21:28:06 -0500168 close(fd);
Norman James5a7cc8d2015-10-06 12:31:06 -0500169 rc = GPIO_OK;
Norman James32e74e22015-09-15 21:28:06 -0500170 } while(0);
Norman Jamese7594922015-08-27 14:25:24 -0500171
Norman James32e74e22015-09-15 21:28:06 -0500172 return rc;
Norman Jamese7594922015-08-27 14:25:24 -0500173}
Norman James5a7cc8d2015-10-06 12:31:06 -0500174
175
176
177
Norman James471ab592015-08-30 22:29:40 -0500178char* get_gpio_dev(GPIO* gpio)
179{
180 char* buf;
Patrick Williamsd6baab92016-08-24 14:05:55 -0500181 asprintf(&buf, "%s/gpio%d/value", gpio->dev, gpio->num);
Norman James471ab592015-08-30 22:29:40 -0500182 return buf;
183}
184
Norman James5a7cc8d2015-10-06 12:31:06 -0500185int gpio_open_interrupt(GPIO* gpio, GIOFunc func, gpointer user_data)
186{
187 int rc = GPIO_OK;
Norman James02b77f32015-10-28 18:59:29 -0500188 char buf[255];
Norman James5a7cc8d2015-10-06 12:31:06 -0500189 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
190 gpio->fd = open(buf, O_RDONLY | O_NONBLOCK );
Norman James02b77f32015-10-28 18:59:29 -0500191 gpio->irq_inited = false;
Norman James5a7cc8d2015-10-06 12:31:06 -0500192 if (gpio->fd == -1)
193 {
194 rc = GPIO_OPEN_ERROR;
195 }
196 else
197 {
Norman James02b77f32015-10-28 18:59:29 -0500198 GIOChannel* channel = g_io_channel_unix_new( gpio->fd);
Norman James5a7cc8d2015-10-06 12:31:06 -0500199 guint id = g_io_add_watch( channel, G_IO_PRI, func, user_data );
200 }
201 return rc;
202}
203
Norman Jamese7594922015-08-27 14:25:24 -0500204int gpio_open(GPIO* gpio)
205{
Norman James65a295a2015-09-26 22:21:10 -0500206 g_assert (gpio != NULL);
Norman Jamese7594922015-08-27 14:25:24 -0500207 // open gpio for writing or reading
208 char buf[254];
Norman James32e74e22015-09-15 21:28:06 -0500209 int rc = 0;
Norman James5a7cc8d2015-10-06 12:31:06 -0500210 gpio->fd = -1;
Norman James65a295a2015-09-26 22:21:10 -0500211 if (gpio->direction == NULL) {
212 return GPIO_OPEN_ERROR;
213 }
Norman Jamese7594922015-08-27 14:25:24 -0500214 if (strcmp(gpio->direction,"in")==0)
215 {
216 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
217 gpio->fd = open(buf, O_RDONLY);
218 }
219 else
220 {
221 sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
Norman James25571112015-12-15 09:36:28 -0600222 gpio->fd = open(buf, O_RDWR);
Norman Jamese7594922015-08-27 14:25:24 -0500223
224 }
Norman James88872672015-09-21 16:51:35 -0500225 if (gpio->fd == -1) {
226 return GPIO_OPEN_ERROR;
227 }
228 return GPIO_OK;
Norman Jamese7594922015-08-27 14:25:24 -0500229}
230
231void gpio_close(GPIO* gpio)
232{
233 close(gpio->fd);
234}