mirror of
https://gitlab.com/mobian1/eg25-manager.git
synced 2025-08-28 23:03:24 +02:00
gpio: make more generic
Instead of assuming we're running on the PinePhone (and therefore hardcoding gpiochip labels and line numbers), make all of those configurable. Legacy config files will still be parsed as long as they lack the `chips` key. Existing config files are also updated to match the new config format.
This commit is contained in:
@@ -13,11 +13,12 @@ poweron_delay = 100000
|
||||
#recovery_timeout = 9
|
||||
|
||||
[gpio]
|
||||
dtr = 358
|
||||
pwrkey = 35
|
||||
reset = 68
|
||||
apready = 231
|
||||
disable = 232
|
||||
chips = [ "1c20800.pinctrl", "1f02c00.pinctrl" ]
|
||||
dtr = { chip = 1, line = 6 }
|
||||
pwrkey = { chip = 0, line = 35 }
|
||||
reset = { chip = 0, line = 68 }
|
||||
apready = { chip = 0, line = 231 }
|
||||
disable = { chip = 0, line = 232 }
|
||||
|
||||
[at]
|
||||
uart = "/dev/ttyS2"
|
||||
|
@@ -13,11 +13,12 @@ poweron_delay = 100000
|
||||
#recovery_timeout = 9
|
||||
|
||||
[gpio]
|
||||
dtr = 358
|
||||
pwrkey = 35
|
||||
reset = 68
|
||||
apready = 231
|
||||
disable = 232
|
||||
chips = [ "1c20800.pinctrl", "1f02c00.pinctrl" ]
|
||||
dtr = { chip = 1, line = 6 }
|
||||
pwrkey = { chip = 0, line = 35 }
|
||||
reset = { chip = 0, line = 68 }
|
||||
apready = { chip = 0, line = 231 }
|
||||
disable = { chip = 0, line = 232 }
|
||||
|
||||
[at]
|
||||
uart = "/dev/ttyS2"
|
||||
|
@@ -9,12 +9,13 @@ poweron_delay = 100000
|
||||
#recovery_timeout = 9
|
||||
|
||||
[gpio]
|
||||
dtr = 34
|
||||
pwrkey = 35
|
||||
reset = 68
|
||||
apready = 231
|
||||
disable = 232
|
||||
status = 233
|
||||
chips = [ "1c20800.pinctrl" ]
|
||||
dtr = { chip = 0, line = 34 }
|
||||
pwrkey = { chip = 0, line = 35 }
|
||||
reset = { chip = 0, line = 68 }
|
||||
apready = { chip = 0, line = 231 }
|
||||
disable = { chip = 0, line = 232 }
|
||||
status = { chip = 0, line = 233 }
|
||||
|
||||
[at]
|
||||
uart = "/dev/ttyS2"
|
||||
|
181
src/gpio.c
181
src/gpio.c
@@ -9,9 +9,9 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/* Those defines are used for legacy config files only */
|
||||
#define GPIO_CHIP1_LABEL "1c20800.pinctrl"
|
||||
#define GPIO_CHIP2_LABEL "1f02c00.pinctrl"
|
||||
|
||||
#define MAX_GPIOCHIP_LINES 352
|
||||
|
||||
enum {
|
||||
@@ -101,10 +101,41 @@ int gpio_sequence_sleep(struct EG25Manager *manager)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct gpiod_line *gpio_get_output_line(struct EG25Manager *manager, int chip, int line)
|
||||
{
|
||||
struct gpiod_line *gpio_line;
|
||||
|
||||
gpio_line = gpiod_chip_get_line(manager->gpiochip[chip], line);
|
||||
if (!gpio_line)
|
||||
return NULL;
|
||||
|
||||
if (gpiod_line_request_output(gpio_line, "eg25manager", 0) < 0) {
|
||||
gpiod_line_release(gpio_line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gpio_line;
|
||||
}
|
||||
|
||||
struct gpiod_line *gpio_get_input_line(struct EG25Manager *manager, int chip, int line)
|
||||
{
|
||||
struct gpiod_line *gpio_line;
|
||||
|
||||
gpio_line = gpiod_chip_get_line(manager->gpiochip[chip], line);
|
||||
if (!gpio_line)
|
||||
return NULL;
|
||||
|
||||
if (gpiod_line_request_input(gpio_line, "eg25manager") < 0) {
|
||||
gpiod_line_release(gpio_line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gpio_line;
|
||||
}
|
||||
|
||||
int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
|
||||
{
|
||||
int i, ret;
|
||||
guint offset, chipidx, gpio_idx;
|
||||
int i;
|
||||
toml_table_t *gpio_config[EG25_CONFIG_COUNT];
|
||||
|
||||
for (i = 0; i < EG25_CONFIG_COUNT; i++)
|
||||
@@ -113,65 +144,119 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
|
||||
if (!gpio_config[EG25_CONFIG_SYS])
|
||||
g_error("Default config file lacks the 'gpio' section!");
|
||||
|
||||
manager->gpiochip[0] = gpiod_chip_open_by_label(GPIO_CHIP1_LABEL);
|
||||
if (!manager->gpiochip[0]) {
|
||||
g_critical("Unable to open GPIO chip " GPIO_CHIP1_LABEL);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* The system config could have the `chips` key, but the user one
|
||||
* could still use the old format! In order to avoid problems, we
|
||||
* should use the new format only if:
|
||||
* - there's no user config file
|
||||
or
|
||||
* - the user config file contains the `chips` key
|
||||
* Otherwise we might start parsing the system config with the new
|
||||
* format, but error out if user config overrides gpios using the
|
||||
* old format
|
||||
*/
|
||||
if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips"))
|
||||
{
|
||||
int numchips;
|
||||
toml_array_t *chipslist = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
config_get_array(gpio_config, "chips", &chipslist);
|
||||
numchips = toml_array_nelem(chipslist);
|
||||
if (numchips > 2)
|
||||
g_error("Requesting too many GPIO chips!");
|
||||
|
||||
for (i = 0; i < GPIO_OUT_COUNT; i++) {
|
||||
if (!config_get_uint(gpio_config, gpio_out_names[i], &gpio_idx))
|
||||
g_error("Unable to get config for output GPIO '%s'", gpio_out_names[i]);
|
||||
|
||||
if (gpio_idx < MAX_GPIOCHIP_LINES) {
|
||||
offset = gpio_idx;
|
||||
chipidx = 0;
|
||||
} else {
|
||||
offset = gpio_idx - MAX_GPIOCHIP_LINES;
|
||||
chipidx = 1;
|
||||
for (i = 0; i < numchips; i++) {
|
||||
toml_datum_t data = toml_string_at(chipslist, i);
|
||||
if (!data.ok)
|
||||
continue;
|
||||
manager->gpiochip[i] = gpiod_chip_open_by_label(data.u.s);
|
||||
}
|
||||
|
||||
manager->gpio_out[i] = gpiod_chip_get_line(manager->gpiochip[chipidx], offset);
|
||||
if (!manager->gpio_out[i]) {
|
||||
g_error("Unable to get output GPIO %d", i);
|
||||
for (i = 0; i < GPIO_OUT_COUNT; i++) {
|
||||
toml_table_t *table;
|
||||
toml_datum_t chip, line;
|
||||
if (!config_get_table(gpio_config, gpio_out_names[i], &table))
|
||||
g_error("Unable to get config for output GPIO '%s'", gpio_out_names[i]);
|
||||
|
||||
chip = toml_int_in(table, "chip");
|
||||
if (!chip.ok || chip.u.i < 0 || chip.u.i > 2)
|
||||
g_error("Wrong chip ID for output GPIO '%s'", gpio_out_names[i]);
|
||||
|
||||
line = toml_int_in(table, "line");
|
||||
if (!line.ok || line.u.i < 0 || line.u.i > gpiod_chip_num_lines(manager->gpiochip[chip.u.i]))
|
||||
g_error("Wrong chip ID for output GPIO '%s'", gpio_out_names[i]);
|
||||
|
||||
manager->gpio_out[i] = gpio_get_output_line(manager, chip.u.i, line.u.i);
|
||||
if (!manager->gpio_out[i])
|
||||
g_error("Unable to get output GPIO %d", i);
|
||||
}
|
||||
|
||||
for (i = 0; i < GPIO_IN_COUNT; i++) {
|
||||
toml_table_t *table;
|
||||
toml_datum_t chip, line;
|
||||
if (!config_get_table(gpio_config, gpio_in_names[i], &table))
|
||||
g_error("Unable to get config for input GPIO '%s'", gpio_in_names[i]);
|
||||
|
||||
chip = toml_int_in(table, "chip");
|
||||
if (!chip.ok || chip.u.i < 0 || chip.u.i > 2)
|
||||
g_error("Wrong chip ID for input GPIO '%s'", gpio_in_names[i]);
|
||||
|
||||
line = toml_int_in(table, "line");
|
||||
if (!line.ok || line.u.i < 0 || line.u.i > gpiod_chip_num_lines(manager->gpiochip[chip.u.i]))
|
||||
g_error("Wrong chip ID for input GPIO '%s'", gpio_in_names[i]);
|
||||
|
||||
manager->gpio_in[i] = gpio_get_input_line(manager, chip.u.i, line.u.i);
|
||||
if (!manager->gpio_in[i])
|
||||
g_error("Unable to get input GPIO %d", i);
|
||||
}
|
||||
} else {
|
||||
guint offset, chipidx, gpio_idx;
|
||||
|
||||
/* Legacy config file, only used on the OG PinePhone */
|
||||
manager->gpiochip[0] = gpiod_chip_open_by_label(GPIO_CHIP1_LABEL);
|
||||
if (!manager->gpiochip[0]) {
|
||||
g_critical("Unable to open GPIO chip " GPIO_CHIP1_LABEL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = gpiod_line_request_output(manager->gpio_out[i], "eg25manager", 0);
|
||||
if (ret < 0) {
|
||||
g_error("Unable to request output GPIO %d", i);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < GPIO_IN_COUNT; i++) {
|
||||
if (!config_get_uint(gpio_config, gpio_in_names[i], &gpio_idx))
|
||||
continue;
|
||||
for (i = 0; i < GPIO_OUT_COUNT; i++) {
|
||||
if (!config_get_uint(gpio_config, gpio_out_names[i], &gpio_idx))
|
||||
g_error("Unable to get config for output GPIO '%s'", gpio_out_names[i]);
|
||||
|
||||
if (gpio_idx < MAX_GPIOCHIP_LINES) {
|
||||
offset = gpio_idx;
|
||||
chipidx = 0;
|
||||
} else {
|
||||
offset = gpio_idx - MAX_GPIOCHIP_LINES;
|
||||
chipidx = 1;
|
||||
if (gpio_idx < MAX_GPIOCHIP_LINES) {
|
||||
offset = gpio_idx;
|
||||
chipidx = 0;
|
||||
} else {
|
||||
offset = gpio_idx - MAX_GPIOCHIP_LINES;
|
||||
chipidx = 1;
|
||||
}
|
||||
|
||||
manager->gpio_out[i] = gpio_get_input_line(manager, chipidx, offset);
|
||||
if (!manager->gpio_out[i])
|
||||
g_error("Unable to get output GPIO %d", i);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
for (i = 0; i < GPIO_IN_COUNT; i++) {
|
||||
if (!config_get_uint(gpio_config, gpio_in_names[i], &gpio_idx))
|
||||
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;
|
||||
if (gpio_idx < MAX_GPIOCHIP_LINES) {
|
||||
offset = gpio_idx;
|
||||
chipidx = 0;
|
||||
} else {
|
||||
offset = gpio_idx - MAX_GPIOCHIP_LINES;
|
||||
chipidx = 1;
|
||||
}
|
||||
|
||||
manager->gpio_in[i] = gpio_get_input_line(manager, chipidx, offset);
|
||||
if (!manager->gpio_in[i])
|
||||
g_error("Unable to get input GPIO %d", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user