[U-Boot] [PATCH v1 0/5] Add get_function_number ops

This series : - Add new gpio ops get_function_number - Add get_function and get_function_number support to stm32 gpio driver - Add get_function_number test
Christophe Kerello (1): gpio: stm32f7: Add ops get_function
Patrice Chotard (2): gpio: sandbox: Rename GPIOF_(OUTPUT|HIGH|ODR) to SDBX_GPIO_(OUTPUT|HIGH|ODR) test: dm: Add gpio get_function_number ops test
Patrick Delaunay (2): dm: gpio: Add get_function_number ops gpio: stm32f7: Add ops get_function_number
arch/sandbox/include/asm/gpio.h | 23 ++++++++++++++++++++ drivers/gpio/gpio-uclass.c | 6 ++++++ drivers/gpio/sandbox.c | 47 +++++++++++++++++++++++++++++++---------- drivers/gpio/stm32f7_gpio.c | 36 +++++++++++++++++++++++++++++++ include/asm-generic/gpio.h | 11 ++++++++++ test/dm/gpio.c | 13 ++++++++++++ 6 files changed, 125 insertions(+), 11 deletions(-)

From: Patrick Delaunay patrick.delaunay@st.com
When a pin is not configured as a GPIO, it could have several alternate function.
To be able to identify the alternate function, add ops get_function_number() to request the pin function index from the driver when pin is not used as gpio.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
drivers/gpio/gpio-uclass.c | 6 ++++++ include/asm-generic/gpio.h | 11 +++++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index da5e9ba6e524..fa249f7b12d4 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -568,6 +568,12 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) label ? label : ""); }
+ if (func == GPIOF_FUNC && ops->get_function_number) { + ret = ops->get_function_number(dev, offset); + if (ret >= 0) + snprintf(str + len, buffsize - len, ": %d", ret); + } + return 0; }
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index d03602696f6d..f8cd6ddccbbf 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -266,6 +266,17 @@ struct dm_gpio_ops { int (*get_function)(struct udevice *dev, unsigned offset);
/** + * get_function_number() Get the function number + * + * get index for GPIOF_FUNC, when pin is not used as a GPIO + * + * @dev: Device to check + * @offset: GPIO offset within that device + * @return current function index + */ + int (*get_function_number)(struct udevice *dev, unsigned int offset); + + /** * xlate() - Translate phandle arguments into a GPIO description * * This function should set up the fields in desc according to the

Hi Patrice,
On 1 August 2018 at 10:38, Patrice Chotard patrice.chotard@st.com wrote:
From: Patrick Delaunay patrick.delaunay@st.com
When a pin is not configured as a GPIO, it could have several alternate function.
To be able to identify the alternate function, add ops get_function_number() to request the pin function index from the driver when pin is not used as gpio.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com Signed-off-by: Patrice Chotard patrice.chotard@st.com
drivers/gpio/gpio-uclass.c | 6 ++++++ include/asm-generic/gpio.h | 11 +++++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index da5e9ba6e524..fa249f7b12d4 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -568,6 +568,12 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) label ? label : ""); }
if (func == GPIOF_FUNC && ops->get_function_number) {
ret = ops->get_function_number(dev, offset);
if (ret >= 0)
snprintf(str + len, buffsize - len, ": %d", ret);
}
return 0;
}
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index d03602696f6d..f8cd6ddccbbf 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -266,6 +266,17 @@ struct dm_gpio_ops { int (*get_function)(struct udevice *dev, unsigned offset);
/**
* get_function_number() Get the function number
*
* get index for GPIOF_FUNC, when pin is not used as a GPIO
*
* @dev: Device to check
* @offset: GPIO offset within that device
* @return current function index
*/
int (*get_function_number)(struct udevice *dev, unsigned int offset);
Can you please add comments as to how this is different from get_function(), Also, I suggest a different name, since it would be confusing for people to have such similar names for different things,
/** * xlate() - Translate phandle arguments into a GPIO description * * This function should set up the fields in desc according to the
-- 1.9.1
Regards, Simon

Hi Simon
On 08/02/2018 06:56 PM, Simon Glass wrote:
Hi Patrice,
On 1 August 2018 at 10:38, Patrice Chotard patrice.chotard@st.com wrote:
From: Patrick Delaunay patrick.delaunay@st.com
When a pin is not configured as a GPIO, it could have several alternate function.
To be able to identify the alternate function, add ops get_function_number() to request the pin function index from the driver when pin is not used as gpio.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com Signed-off-by: Patrice Chotard patrice.chotard@st.com
drivers/gpio/gpio-uclass.c | 6 ++++++ include/asm-generic/gpio.h | 11 +++++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index da5e9ba6e524..fa249f7b12d4 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -568,6 +568,12 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) label ? label : ""); }
if (func == GPIOF_FUNC && ops->get_function_number) {
ret = ops->get_function_number(dev, offset);
if (ret >= 0)
snprintf(str + len, buffsize - len, ": %d", ret);
}
}return 0;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index d03602696f6d..f8cd6ddccbbf 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -266,6 +266,17 @@ struct dm_gpio_ops { int (*get_function)(struct udevice *dev, unsigned offset);
/**
* get_function_number() Get the function number
*
* get index for GPIOF_FUNC, when pin is not used as a GPIO
*
* @dev: Device to check
* @offset: GPIO offset within that device
* @return current function index
*/
int (*get_function_number)(struct udevice *dev, unsigned int offset);
Can you please add comments as to how this is different from get_function(), Also, I suggest a different name, since it would be confusing for people to have such similar names for different things,
Ok, i will rename get_function_number() to get_alternate_function() and add a comments
Thanks
Patrice
/** * xlate() - Translate phandle arguments into a GPIO description * * This function should set up the fields in desc according to the
-- 1.9.1
Regards, Simon

From: Christophe Kerello christophe.kerello@st.com
This patch adds gpio get_function ops support. This function reports the state of a gpio.
Signed-off-by: Christophe Kerello christophe.kerello@st.com Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
drivers/gpio/stm32f7_gpio.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/drivers/gpio/stm32f7_gpio.c b/drivers/gpio/stm32f7_gpio.c index 5b08e7ee275c..55e121699022 100644 --- a/drivers/gpio/stm32f7_gpio.c +++ b/drivers/gpio/stm32f7_gpio.c @@ -66,11 +66,31 @@ static int stm32_gpio_set_value(struct udevice *dev, unsigned offset, int value) return 0; }
+static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct stm32_gpio_priv *priv = dev_get_priv(dev); + struct stm32_gpio_regs *regs = priv->regs; + int bits_index = MODE_BITS(offset); + int mask = MODE_BITS_MASK << bits_index; + u32 mode; + + mode = (readl(®s->moder) & mask) >> bits_index; + if (mode == STM32_GPIO_MODE_OUT) + return GPIOF_OUTPUT; + if (mode == STM32_GPIO_MODE_IN) + return GPIOF_INPUT; + if (mode == STM32_GPIO_MODE_AN) + return GPIOF_UNUSED; + + return GPIOF_FUNC; +} + static const struct dm_gpio_ops gpio_stm32_ops = { .direction_input = stm32_gpio_direction_input, .direction_output = stm32_gpio_direction_output, .get_value = stm32_gpio_get_value, .set_value = stm32_gpio_set_value, + .get_function = stm32_gpio_get_function, };
static int gpio_stm32_probe(struct udevice *dev)

On 1 August 2018 at 10:38, Patrice Chotard patrice.chotard@st.com wrote:
From: Christophe Kerello christophe.kerello@st.com
This patch adds gpio get_function ops support. This function reports the state of a gpio.
Signed-off-by: Christophe Kerello christophe.kerello@st.com Signed-off-by: Patrice Chotard patrice.chotard@st.com
drivers/gpio/stm32f7_gpio.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrick Delaunay patrick.delaunay@st.com
Allow to display function number using "gpio" command. Example, display all gpio state :
gpio status -a GPIOD2: func: 12 GPIOD3: func: 9 GPIOE3: func: 9 GPIOG6: func: 10
It's useful to control pin configuration
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
drivers/gpio/stm32f7_gpio.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/drivers/gpio/stm32f7_gpio.c b/drivers/gpio/stm32f7_gpio.c index 55e121699022..67c3002acd31 100644 --- a/drivers/gpio/stm32f7_gpio.c +++ b/drivers/gpio/stm32f7_gpio.c @@ -85,12 +85,28 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset) return GPIOF_FUNC; }
+static int stm32_gpio_get_function_number(struct udevice *dev, + unsigned int offset) +{ + struct stm32_gpio_priv *priv = dev_get_priv(dev); + struct stm32_gpio_regs *regs = priv->regs; + u32 af; + u32 alt_shift = (offset % 8) * 4; + u32 alt_index = offset / 8; + + af = (readl(®s->afr[alt_index]) & + GENMASK(alt_shift + 3, alt_shift)) >> alt_shift; + + return af; +} + static const struct dm_gpio_ops gpio_stm32_ops = { .direction_input = stm32_gpio_direction_input, .direction_output = stm32_gpio_direction_output, .get_value = stm32_gpio_get_value, .set_value = stm32_gpio_set_value, .get_function = stm32_gpio_get_function, + .get_function_number = stm32_gpio_get_function_number, };
static int gpio_stm32_probe(struct udevice *dev)

To avoid confusion with enum gpio_func_t GPIOF_OUTPUT defined in asm-generic/gpio.h, rename all sandbox flags GPIOF_(OUTPUT|HIGH|ODR) to SDBX_GPIO_(OUTPUT|HIGH|ODR)
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
drivers/gpio/sandbox.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 2ef5c67ad593..50afa697d01c 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -12,9 +12,9 @@ #include <dt-bindings/gpio/gpio.h>
/* Flags for each GPIO */ -#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */ -#define GPIOF_HIGH (1 << 1) /* Currently set high */ -#define GPIOF_ODR (1 << 2) /* Currently set to open drain mode */ +#define SDBX_GPIO_OUTPUT BIT(0) /* Currently set as an output */ +#define SDBX_GPIO_HIGH BIT(1) /* Currently set high */ +#define SDBX_GPIO_ODR BIT(2) /* Currently set to open drain mode */
struct gpio_state { const char *label; /* label given by requester */ @@ -60,34 +60,34 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
int sandbox_gpio_get_value(struct udevice *dev, unsigned offset) { - if (get_gpio_flag(dev, offset, GPIOF_OUTPUT)) + if (get_gpio_flag(dev, offset, SDBX_GPIO_OUTPUT)) debug("sandbox_gpio: get_value on output gpio %u\n", offset); - return get_gpio_flag(dev, offset, GPIOF_HIGH); + return get_gpio_flag(dev, offset, SDBX_GPIO_HIGH); }
int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value) { - return set_gpio_flag(dev, offset, GPIOF_HIGH, value); + return set_gpio_flag(dev, offset, SDBX_GPIO_HIGH, value); }
int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset) { - return get_gpio_flag(dev, offset, GPIOF_ODR); + return get_gpio_flag(dev, offset, SDBX_GPIO_ODR); }
int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value) { - return set_gpio_flag(dev, offset, GPIOF_ODR, value); + return set_gpio_flag(dev, offset, SDBX_GPIO_ODR, value); }
int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset) { - return get_gpio_flag(dev, offset, GPIOF_OUTPUT); + return get_gpio_flag(dev, offset, SDBX_GPIO_OUTPUT); }
int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output) { - return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output); + return set_gpio_flag(dev, offset, SDBX_GPIO_OUTPUT, output); }
/* @@ -158,7 +158,7 @@ static int sb_gpio_set_open_drain(struct udevice *dev, unsigned offset, int valu
static int sb_gpio_get_function(struct udevice *dev, unsigned offset) { - if (get_gpio_flag(dev, offset, GPIOF_OUTPUT)) + if (get_gpio_flag(dev, offset, SDBX_GPIO_OUTPUT)) return GPIOF_OUTPUT; return GPIOF_INPUT; }

In order to test get_function_number ops, add sandbox_gpio_set_function() and sandbox_gpio_set_function_number() to be able to configure a pin not as a GPIO and to select the function number.
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
arch/sandbox/include/asm/gpio.h | 23 +++++++++++++++++++++++ drivers/gpio/sandbox.c | 25 +++++++++++++++++++++++++ test/dm/gpio.c | 13 +++++++++++++ 3 files changed, 61 insertions(+)
diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h index de8ac37f4262..d1eea307efc8 100644 --- a/arch/sandbox/include/asm/gpio.h +++ b/arch/sandbox/include/asm/gpio.h @@ -82,4 +82,27 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned int offset); int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset, int output);
+/** + * Set the simulated usage of a pin, as a GPIO or not (used only in sandbox + * test code) + * + * @param dev device to use + * @param offset GPIO offset within bank + * @param value 0 to set as GPIO, 1 to set as not a GPIO + * @return -1 on error, 0 if ok + */ +int sandbox_gpio_set_function(struct udevice *dev, unsigned int offset, + int value); + +/** + * Set the simulated alternate function of a pin when pin is not used as a GPIO + * (used only in sandbox test code) + * + * @param dev device to use + * @param offset GPIO offset within bank + * @param value pin alternate function number + * @return -1 on error, 0 if ok + */ +int sandbox_gpio_set_function_number(struct udevice *dev, unsigned int offset, + int value); #endif diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 50afa697d01c..cdaab8f9bf2e 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -15,6 +15,8 @@ #define SDBX_GPIO_OUTPUT BIT(0) /* Currently set as an output */ #define SDBX_GPIO_HIGH BIT(1) /* Currently set high */ #define SDBX_GPIO_ODR BIT(2) /* Currently set to open drain mode */ +#define SDBX_GPIO_FUNC BIT(3) /* Currently set as not used as GPIO */ +#define SDBX_GPIO_FUNC_NB BIT(4) /* Currently set as function number 1 */
struct gpio_state { const char *label; /* label given by requester */ @@ -90,6 +92,18 @@ int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output) return set_gpio_flag(dev, offset, SDBX_GPIO_OUTPUT, output); }
+int sandbox_gpio_set_function(struct udevice *dev, unsigned int offset, + int value) +{ + return set_gpio_flag(dev, offset, SDBX_GPIO_FUNC, value); +} + +int sandbox_gpio_set_function_number(struct udevice *dev, unsigned int offset, + int value) +{ + return set_gpio_flag(dev, offset, SDBX_GPIO_FUNC_NB, value); +} + /* * These functions implement the public interface within U-Boot */ @@ -158,11 +172,21 @@ static int sb_gpio_set_open_drain(struct udevice *dev, unsigned offset, int valu
static int sb_gpio_get_function(struct udevice *dev, unsigned offset) { + if (get_gpio_flag(dev, offset, SDBX_GPIO_FUNC)) + return GPIOF_FUNC; + if (get_gpio_flag(dev, offset, SDBX_GPIO_OUTPUT)) return GPIOF_OUTPUT; return GPIOF_INPUT; }
+static int sb_gpio_get_function_number(struct udevice *dev, unsigned int offset) +{ + debug("%s: offset:%u\n", __func__, offset); + + return get_gpio_flag(dev, offset, SDBX_GPIO_FUNC_NB); +} + static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args) { @@ -189,6 +213,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = { .get_open_drain = sb_gpio_get_open_drain, .set_open_drain = sb_gpio_set_open_drain, .get_function = sb_gpio_get_function, + .get_function_number = sb_gpio_get_function_number, .xlate = sb_gpio_xlate, };
diff --git a/test/dm/gpio.c b/test/dm/gpio.c index bb4b20cea938..1cca1ba007bf 100644 --- a/test/dm/gpio.c +++ b/test/dm/gpio.c @@ -92,6 +92,19 @@ static int dm_test_gpio(struct unit_test_state *uts) ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); ut_asserteq_str("b4: input: 0 [ ]", buf);
+ /* + * Make it not used as GPIO, select function + * (by default function number 0 is active) + */ + sandbox_gpio_set_function(dev, offset, 1); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: func: 0", buf); + + /* select function number 1 */ + sandbox_gpio_set_function_number(dev, offset, 1); + ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); + ut_asserteq_str("b4: func: 1", buf); + /* Check the 'a' bank also */ ut_assertok(gpio_lookup_name("a15", &dev, &offset, &gpio)); ut_asserteq_str(dev->name, "base-gpios");
participants (3)
-
Patrice CHOTARD
-
Patrice Chotard
-
Simon Glass