aboutsummaryrefslogtreecommitdiffstats
path: root/src/linux
diff options
context:
space:
mode:
authorLucio Tarantino <lucio.tarantino@gmail.com>2020-06-06 18:47:11 +0200
committerGitHub <noreply@github.com>2020-06-06 12:47:11 -0400
commitb7699d374ab17e6054d0d83a9deb7be9e70dcdc8 (patch)
treec5f27d9402cdaf124814ab71891c70e6cd730c8b /src/linux
parent7912c39f9ed1601d3fcd230d3216ee8f1750c31a (diff)
downloadkutter-b7699d374ab17e6054d0d83a9deb7be9e70dcdc8.tar.gz
kutter-b7699d374ab17e6054d0d83a9deb7be9e70dcdc8.tar.xz
kutter-b7699d374ab17e6054d0d83a9deb7be9e70dcdc8.zip
linux: Ability to use multiple GPIO chips (#2935)
Signed-off-by: Lucio Tarantino <lucio.tarantino@gmail.com>
Diffstat (limited to 'src/linux')
-rw-r--r--src/linux/analog.c2
-rw-r--r--src/linux/gpio.c60
-rw-r--r--src/linux/internal.h6
3 files changed, 48 insertions, 20 deletions
diff --git a/src/linux/analog.c b/src/linux/analog.c
index aa8fb701..55420ce6 100644
--- a/src/linux/analog.c
+++ b/src/linux/analog.c
@@ -15,7 +15,7 @@
DECL_CONSTANT("ADC_MAX", 4095); // Assume 12bit adc
-#define ANALOG_START (1<<8)
+#define ANALOG_START (1<<12)
DECL_ENUMERATION_RANGE("pin", "analog0", ANALOG_START, 8);
diff --git a/src/linux/gpio.c b/src/linux/gpio.c
index d8990581..a858b259 100644
--- a/src/linux/gpio.c
+++ b/src/linux/gpio.c
@@ -19,45 +19,65 @@
#include <sys/ioctl.h>
#include <unistd.h>
-#define CHIP_FILE_NAME "/dev/gpiochip0"
+#define CHIP_FILE_NAME "/dev/gpiochip%u"
#define GPIO_CONSUMER "klipper"
-#define NUM_LINES 40
-DECL_ENUMERATION_RANGE("pin", "P0", 0, NUM_LINES);
+
+DECL_ENUMERATION_RANGE("pin", "gpio0", GPIO(0, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip0/gpio0", GPIO(0, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip1/gpio0", GPIO(1, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip2/gpio0", GPIO(2, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip3/gpio0", GPIO(3, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip4/gpio0", GPIO(4, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip5/gpio0", GPIO(5, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip6/gpio0", GPIO(6, 0), MAX_GPIO_LINES);
+DECL_ENUMERATION_RANGE("pin", "gpiochip7/gpio0", GPIO(7, 0), MAX_GPIO_LINES);
struct gpio_line {
+ int chipid;
int offset;
int fd;
int state;
};
-static struct gpio_line lines[NUM_LINES];
+static struct gpio_line lines[8*MAX_GPIO_LINES];
-static int gpio_chip_fd = -1;
+static int gpio_chip_fd[8] = { -1 };
static int
-get_chip_fd(void) {
+get_chip_fd(uint8_t chipId) {
+ char chipFilename[64],errorMessage[256];
int i = 0;
- if (gpio_chip_fd <= 0) {
- gpio_chip_fd = open(CHIP_FILE_NAME,O_RDWR | O_CLOEXEC);
- if (gpio_chip_fd < 0) {
- report_errno("open " CHIP_FILE_NAME,-1);
+ if (gpio_chip_fd[chipId] <= 0) {
+ snprintf(chipFilename,sizeof(chipFilename), CHIP_FILE_NAME, chipId);
+ if(access(chipFilename, F_OK) < 0){
+ snprintf(errorMessage,sizeof(errorMessage),
+ "%s not found!",chipFilename);
+ report_errno(errorMessage,-1);
+ shutdown("GPIO chip device not found");
+ }
+ gpio_chip_fd[chipId] = open(chipFilename,O_RDWR | O_CLOEXEC);
+ if (gpio_chip_fd[chipId] < 0) {
+ snprintf(errorMessage,sizeof(errorMessage),
+ "Unable to open GPIO %s",chipFilename);
+ report_errno(errorMessage,-1);
shutdown("Unable to open GPIO chip device");
}
- for (i=0; i<NUM_LINES; ++i) {
- lines[i].offset = i;
- lines[i].fd = -1;
+ for (i=0; i<MAX_GPIO_LINES; ++i) {
+ lines[GPIO(chipId,i)].offset = i;
+ lines[GPIO(chipId,i)].fd = -1;
+ lines[GPIO(chipId,i)].chipid = chipId;
}
}
- return gpio_chip_fd;
+ return gpio_chip_fd[chipId];
}
-// Dummy versions of gpio_out functions
struct gpio_out
gpio_out_setup(uint32_t pin, uint8_t val)
{
struct gpio_line* line = &lines[pin];
- line->offset = pin;
+ line->offset = GPIO2PIN(pin);
+ line->chipid = GPIO2PORT(pin);
struct gpio_out g = { .line = line };
gpio_out_reset(g,val);
return g;
@@ -84,7 +104,7 @@ gpio_out_reset(struct gpio_out g, uint8_t val)
req.lineoffsets[0] = g.line->offset;
req.default_values[0] = !!val;
strncpy(req.consumer_label,GPIO_CONSUMER,sizeof(req.consumer_label) - 1);
- rv = ioctl(get_chip_fd(), GPIO_GET_LINEHANDLE_IOCTL, &req);
+ rv = ioctl(get_chip_fd(g.line->chipid), GPIO_GET_LINEHANDLE_IOCTL, &req);
if (rv < 0) {
report_errno("gpio_out_reset get line",rv);
shutdown("Unable to open out GPIO chip line");
@@ -120,7 +140,8 @@ struct gpio_in
gpio_in_setup(uint32_t pin, int8_t pull_up)
{
struct gpio_line* line = &lines[pin];
- line->offset = pin;
+ line->offset = GPIO2PIN(pin);
+ line->chipid = GPIO2PORT(pin);
struct gpio_in g = { .line = line };
gpio_in_reset(g,pull_up);
return g;
@@ -144,7 +165,8 @@ gpio_in_reset(struct gpio_in g, int8_t pull_up)
#endif
req.lineoffsets[0] = g.line->offset;
strncpy(req.consumer_label,GPIO_CONSUMER,sizeof(req.consumer_label) - 1);
- rv = ioctl(get_chip_fd(), GPIO_GET_LINEHANDLE_IOCTL, &req);
+ rv = ioctl(
+ get_chip_fd(g.line->chipid),GPIO_GET_LINEHANDLE_IOCTL,&req);
if (rv < 0) {
report_errno("gpio_in_reset get line",rv);
shutdown("Unable to open in GPIO chip line");
diff --git a/src/linux/internal.h b/src/linux/internal.h
index 592c4588..ac4f3f13 100644
--- a/src/linux/internal.h
+++ b/src/linux/internal.h
@@ -5,6 +5,12 @@
#include <time.h> // struct timespec
#include "autoconf.h" // CONFIG_CLOCK_FREQ
+#define MAX_GPIO_LINES 256
+#define GPIO(PORT, NUM) ((PORT) * MAX_GPIO_LINES + (NUM))
+#define GPIO2PORT(PIN) ((PIN) / MAX_GPIO_LINES)
+#define GPIO2PIN(PIN) ((PIN) % MAX_GPIO_LINES)
+
+
#define NSECS 1000000000
#define NSECS_PER_TICK (NSECS / CONFIG_CLOCK_FREQ)