From 1170a2c7f7d74016e5068f5dd290076feb4d617f Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 10 Dec 2020 17:03:11 +0100 Subject: [PATCH] gpio: configure STATUS input gpio RI won't be accessible due to it being used by the kernel as an interrupt source, so we can check the STATUS pin (CE only) which will allow us to know precisely when the modem is shut down. --- src/gpio.c | 77 ++++++++++++++++++++++++++++++++++++++++----------- src/manager.h | 1 + 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/gpio.c b/src/gpio.c index bfe505c..d424b6e 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -11,6 +11,8 @@ #define MAX_GPIOCHIP_LINES 352 +#define GPIO_IDX_INVAL 0xffff + enum { GPIO_OUT_DTR = 0, GPIO_OUT_PWRKEY, @@ -20,7 +22,7 @@ enum { GPIO_OUT_COUNT }; -static unsigned gpio_idx_bh[] = { +static unsigned gpio_out_idx_bh[] = { 358, 35, 68, @@ -28,7 +30,7 @@ static unsigned gpio_idx_bh[] = { 232 }; -static unsigned gpio_idx_ce[] = { +static unsigned gpio_out_idx_ce[] = { 34, 35, 68, @@ -36,6 +38,19 @@ static unsigned gpio_idx_ce[] = { 232 }; +enum { + GPIO_IN_STATUS = 0, + GPIO_IN_COUNT +}; + +static unsigned gpio_in_idx_bh[] = { + GPIO_IDX_INVAL, +}; + +static unsigned gpio_in_idx_ce[] = { + 233, +}; + int gpio_sequence_poweron(struct EG25Manager *manager) { gpiod_line_set_value(manager->gpio_out[GPIO_OUT_PWRKEY], 1); @@ -83,7 +98,8 @@ int gpio_sequence_resume(struct EG25Manager *manager) int gpio_init(struct EG25Manager *manager) { int i, ret; - unsigned *gpio_idx; + unsigned *gpio_in_idx; + unsigned *gpio_out_idx; manager->gpiochip[0] = gpiod_chip_open_by_label(GPIO_CHIP1_LABEL); if (!manager->gpiochip[0]) { @@ -91,42 +107,71 @@ int gpio_init(struct EG25Manager *manager) return 1; } + manager->gpiochip[1] = gpiod_chip_open_by_label(GPIO_CHIP2_LABEL); + if (!manager->gpiochip[1]) { + g_critical("Unable to open GPIO chip " GPIO_CHIP2_LABEL); + return 1; + } + if (manager->braveheart) { - // BH have DTR on the 2nd gpiochip - manager->gpiochip[1] = gpiod_chip_open_by_label(GPIO_CHIP2_LABEL); - if (!manager->gpiochip[1]) { - g_critical("Unable to open GPIO chip " GPIO_CHIP2_LABEL); - return 1; - } - gpio_idx = gpio_idx_bh; + gpio_in_idx = gpio_in_idx_bh; + gpio_out_idx = gpio_out_idx_bh; } else { - gpio_idx = gpio_idx_ce; + gpio_in_idx = gpio_in_idx_ce; + gpio_out_idx = gpio_out_idx_ce; } for (i = 0; i < GPIO_OUT_COUNT; i++) { unsigned int offset, chipidx; - if (gpio_idx[i] < MAX_GPIOCHIP_LINES) { - offset = gpio_idx[i]; + if (gpio_out_idx[i] < MAX_GPIOCHIP_LINES) { + offset = gpio_out_idx[i]; chipidx = 0; } else { - offset = gpio_idx[i] - MAX_GPIOCHIP_LINES; + offset = gpio_out_idx[i] - MAX_GPIOCHIP_LINES; chipidx = 1; } manager->gpio_out[i] = gpiod_chip_get_line(manager->gpiochip[chipidx], offset); if (!manager->gpio_out[i]) { - g_critical("Unable to get line %d", i); + g_critical("Unable to get output GPIO %d", i); return 1; } ret = gpiod_line_request_output(manager->gpio_out[i], "eg25manager", 0); if (ret < 0) { - g_critical("Unable to request line %d", i); + g_critical("Unable to request output GPIO %d", i); return 1; } } + for (i = 0; i < GPIO_IN_COUNT; i++) { + unsigned int offset, chipidx; + + if (gpio_in_idx[i] == GPIO_IDX_INVAL) + continue; + + if (gpio_in_idx[i] < MAX_GPIOCHIP_LINES) { + offset = gpio_in_idx[i]; + chipidx = 0; + } else { + offset = gpio_in_idx[i] - MAX_GPIOCHIP_LINES; + chipidx = 1; + } + + manager->gpio_in[i] = gpiod_chip_get_line(manager->gpiochip[chipidx], offset); + if (!manager->gpio_in[i]) { + g_warning("Unable to get input GPIO %d", i); + continue; + } + + ret = gpiod_line_request_input(manager->gpio_in[i], "eg25manager"); + if (ret < 0) { + g_warning("Unable to request input GPIO %d", i); + manager->gpio_in[i] = NULL; + } + } + return 0; } diff --git a/src/manager.h b/src/manager.h index e44e6a0..714a812 100644 --- a/src/manager.h +++ b/src/manager.h @@ -46,6 +46,7 @@ struct EG25Manager { struct gpiod_chip *gpiochip[2]; struct gpiod_line *gpio_out[5]; + struct gpiod_line *gpio_in[2]; }; void modem_configure(struct EG25Manager *data);