From patchwork Mon Jan 13 10:35:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 239562 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Mon, 13 Jan 2020 11:35:08 +0100 Subject: [PATCH v3 14/21] gpio: add ops to get dir flags In-Reply-To: <20200113103515.20879-1-patrick.delaunay@st.com> References: <20200113103515.20879-1-patrick.delaunay@st.com> Message-ID: <20200113103515.20879-15-patrick.delaunay@st.com> Add the ops for GPIO driver get_dir_flags(), allows to get dynamically the current gpio configuration; it is used by the API function dm_gpio_get_dir_flags(). When these optional ops are absent, the gpio uclass continues to use the mandatory ops (direction_output, direction_input, get_value) and value of desc->flags to manage only the main dir flags: - GPIOD_IS_IN - GPIOD_IS_OUT - GPIOD_IS_OUT_ACTIVE - GPIOD_ACTIVE_LOW Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- This patch was part of v2 08/14 = gpio: add ops for configuration with dir flags Changes in v3: - Split the previous patch [PATCH v2 08/14] to help review Changes in v2: - change the proposed ops for pin config to set_dir_flags/get_dir_flags - reused the existing API dm_gpio_set_dir_flags/dm_gpio_set_dir - add a new API dm_gpio_get_dir_flags drivers/gpio/gpio-uclass.c | 31 +++++++++++++++++++++++++------ include/asm-generic/gpio.h | 15 +++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index e02ef29fed..89af37a4ea 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -613,19 +613,36 @@ int dm_gpio_set_dir(struct gpio_desc *desc) int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags) { - int ret; + struct udevice *dev = desc->dev; + int ret, value; + struct dm_gpio_ops *ops = gpio_get_ops(dev); ulong dir_flags; ret = check_reserved(desc, "get_dir_flags"); if (ret) return ret; - dir_flags = desc->flags; - /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */ - dir_flags &= ~GPIOD_IS_OUT_ACTIVE; - if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc)) - dir_flags |= GPIOD_IS_OUT_ACTIVE; + /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */ + if (ops->get_dir_flags) { + ret = ops->get_dir_flags(dev, desc->offset, &dir_flags); + if (ret) + return ret; + /* GPIOD_ACTIVE_LOW is saved in desc->flags */ + value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; + if (desc->flags & GPIOD_ACTIVE_LOW) + value = !value; + dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE); + dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW); + if (value) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } else { + dir_flags = desc->flags; + /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */ + dir_flags &= ~GPIOD_IS_OUT_ACTIVE; + if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc)) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } *flags = dir_flags; return 0; @@ -1128,6 +1145,8 @@ static int gpio_post_bind(struct udevice *dev) ops->get_function += gd->reloc_off; if (ops->xlate) ops->xlate += gd->reloc_off; + if (ops->get_dir_flags) + ops->get_dir_flags += gd->reloc_off; reloc_done++; } diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 4f7b43f163..ac30c3ee4e 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -297,6 +297,21 @@ struct dm_gpio_ops { */ int (*xlate)(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args); + + /** + * get_dir_flags() - Get GPIO dir flags + * + * This function return the GPIO direction flags used. + * + * This method is optional. + * + * @dev: GPIO device + * @offset: GPIO offset within that device + * @flags: place to put the used direction flags by GPIO + * @return 0 if OK, -ve on error + */ + int (*get_dir_flags)(struct udevice *dev, unsigned int offset, + ulong *flags); }; /**