From a38f9c57f94d1689f3ab44244268d8d5472ecf3b Mon Sep 17 00:00:00 2001 From: Christian Mauderer Date: Tue, 21 Nov 2023 15:54:33 +0100 Subject: bsps/imx*: imx_gpio from pointer to fdt property Device trees allow mixing different kinds of GPIOs in one property. For that it is usefull to only provide a pointer to an arbitrary location in the property and initialize a GPIO from that. --- bsps/arm/include/bsp/imx-gpio.h | 26 +++++++++++++++++++ bsps/arm/shared/pins/imx-gpio.c | 55 ++++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/bsps/arm/include/bsp/imx-gpio.h b/bsps/arm/include/bsp/imx-gpio.h index 148f62a56e..5cda22972f 100644 --- a/bsps/arm/include/bsp/imx-gpio.h +++ b/bsps/arm/include/bsp/imx-gpio.h @@ -76,6 +76,32 @@ struct imx_gpio_pin { */ void imx_gpio_init (struct imx_gpio_pin *pin); +/** + * Initialize a GPIO pin from the fields in an FDT property. + * + * If you have for example the following property in an FDT node: + * + * some-node { + * mixed-stuff = <0>, <&some_node 1>, <&gpio4 22 GPIO_ACTIVE_LOW>, <17>; + * }; + * + * You can get the property using fdt_getprop(...) in your code, somehow find + * the right start position (the phandle &gpio4) and then pass it to this + * function. + * + * If you pass something != NULL to @a next_prop_pointer, you will get a pointer + * to the next part in the attribute. In the example above, that will be a + * pointer to the <17>. + * + * NOTE: The information from the third parameter in the FDT (GPIO_ACTIVE_LOW in + * the example) is currently ignored. + */ +rtems_status_code imx_gpio_init_from_fdt_property_pointer( + struct imx_gpio_pin *pin, + const uint32_t *prop_pointer, + enum imx_gpio_mode mode, + const uint32_t **next_prop_pointer); + /** * Initialize a GPIO pin from a FDT property. * diff --git a/bsps/arm/shared/pins/imx-gpio.c b/bsps/arm/shared/pins/imx-gpio.c index 8b7d09e864..1e39822b93 100644 --- a/bsps/arm/shared/pins/imx-gpio.c +++ b/bsps/arm/shared/pins/imx-gpio.c @@ -191,12 +191,11 @@ static void imx_gpio_set_interrupt_mode(struct imx_gpio_pin *pin, uint32_t mode) } } -rtems_status_code imx_gpio_init_from_fdt_property ( +rtems_status_code imx_gpio_init_from_fdt_property_pointer ( struct imx_gpio_pin *pin, - int node_offset, - const char *property, + const uint32_t *prop_pointer, enum imx_gpio_mode mode, - size_t index + const uint32_t **next_prop_pointer ) { int len; @@ -205,7 +204,6 @@ rtems_status_code imx_gpio_init_from_fdt_property ( const void *fdt; uint32_t gpio_regs; const unsigned pin_length_dwords = 3; - const unsigned pin_length_bytes = (pin_length_dwords * sizeof(uint32_t)); uint32_t gpio_phandle; uint32_t pin_nr; int cfgnode; @@ -213,16 +211,12 @@ rtems_status_code imx_gpio_init_from_fdt_property ( memset(pin, 0, sizeof(*pin)); fdt = bsp_fdt_get(); - val = fdt_getprop(fdt, node_offset, property, &len); - if (val == NULL || (len % pin_length_bytes != 0) || - (index >= len / pin_length_bytes)) { - sc = RTEMS_UNSATISFIED; - } if (sc == RTEMS_SUCCESSFUL) { - pin_nr = fdt32_to_cpu(val[1 + index * pin_length_dwords]); - gpio_phandle = fdt32_to_cpu(val[0 + index * pin_length_dwords]); + pin_nr = fdt32_to_cpu(prop_pointer[1]); + gpio_phandle = fdt32_to_cpu(prop_pointer[0]); cfgnode = fdt_node_offset_by_phandle(fdt, gpio_phandle); + /* FIXME: Check compatible strings here. */ val = fdt_getprop(fdt, cfgnode, "reg", &len); if (len > 0) { gpio_regs = fdt32_to_cpu(val[0]); @@ -239,6 +233,43 @@ rtems_status_code imx_gpio_init_from_fdt_property ( if (sc == RTEMS_SUCCESSFUL) { imx_gpio_init(pin); } + if (sc == RTEMS_SUCCESSFUL && next_prop_pointer != NULL) { + *next_prop_pointer = prop_pointer + pin_length_dwords; + } + + return sc; +} + +rtems_status_code imx_gpio_init_from_fdt_property ( + struct imx_gpio_pin *pin, + int node_offset, + const char *property, + enum imx_gpio_mode mode, + size_t index +) +{ + int len; + const uint32_t *val; + rtems_status_code sc = RTEMS_SUCCESSFUL; + const void *fdt; + const unsigned pin_length_dwords = 3; + const unsigned pin_length_bytes = pin_length_dwords * 4; + + memset(pin, 0, sizeof(*pin)); + + fdt = bsp_fdt_get(); + val = fdt_getprop(fdt, node_offset, property, &len); + if (val == NULL || (len % pin_length_bytes != 0) || + (index >= len / pin_length_bytes)) { + sc = RTEMS_UNSATISFIED; + } + if (sc == RTEMS_SUCCESSFUL) { + sc = imx_gpio_init_from_fdt_property_pointer( + pin, + val + index * pin_length_dwords, + mode, + NULL); + } return sc; } -- cgit v1.2.3