mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-20 22:55:36 +08:00
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.
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user