pinctrl: prototyping a per pin mux approach
Subsystems (6)
cover pinctrl: prototyping a per pin mux approach
Hi,
Here is an implementation of what I need for the future at91 pin controller. The pinctrl driver is a draft made for a sama5d4 in order to test it. It is not clean and many things are missing but I think it will be easier to debate on code.
Quoted 1 line
From the discussion with Sascha, it seems that we agree that current pinctrl
doesn't fit the needs of controllers who have per pin muxing because the concepts of groups is not real.
In my opinion, even if groups are not real it is quite convenient to use them at least for debug sysfs.
The new at91 pin controller is close to Mediatek one. I am not totally happy with their solution since a group is describing a pin. It is probably the easiest way to do it but it doesn't fit my needs. I have two constraints:
- I want something readable in sysfs as:
device fc000000.mmc
state default
type MUX_GROUP (2)
controlling device ahb:apb:pinctrl at fc06a000
group mci1_0_4bit
function C
device fc000000.mmc
state default
type CONFIGS_PIN (3)
controlling device ahb:apb:pinctrl at fc06a000
pin PE19
config 00010003
I don't want to have a group named as a pin.
- I want to perform some verifications on user choices. A concept of ioset is introduced. An ioset is a set of pins dedicated to a device. A device can have several iosets. For example we can have i2c0 ioset1 with pins PA0 and PA1 and i2c0 ioset2 with pins PE10 and PE11. The controller has no knowledge about iosets. It means I could take the i2c data signal from ioset1 and the i2c clock signal from ioset2 BUT validation has been done only per ioset. For devices such as i2c it should not be a problem but it could be for other ones such as mci, isi, etc.
- I don't want big tables describing pins in my driver. It represents a huge amount of code mainly useless in the case of a multiplatform image.
- I would like to find a generic solution if possible by still using pinconf_generic_dt_node_to_map_all() instead of having my own implementation which will only call pinconf_generic_parse_dt_config().
Well, I let you having a look to the following patch, it should help you to understand what I mean and what I need.
Regards
Ludovic
Ludovic Desroches (4):
pinctrl: change function behavior for per pin muxing controllers
pinctrl: introduce complex pin description
pinctrl: rough draft for a future controller
ARM: at91/dt: proto dt
arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/at91-sama5d4ek_proto.dts | 243 ++++++++++ arch/arm/boot/dts/sama5d4_proto-pinfunc.h | 463 +++++++++++++++++++ arch/arm/boot/dts/sama5d4_proto.dtsi | 716 +++++++++++++++++++++++++++++ drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinconf-generic.c | 115 +++-- drivers/pinctrl/pinctrl-at91-pio4.c | 625 +++++++++++++++++++++++++ drivers/pinctrl/pinmux.c | 58 +-- include/linux/pinctrl/pinctrl.h | 5 + include/linux/pinctrl/pinmux.h | 3 + 11 files changed, 2180 insertions(+), 60 deletions(-) create mode 100644 arch/arm/boot/dts/at91-sama5d4ek_proto.dts create mode 100644 arch/arm/boot/dts/sama5d4_proto-pinfunc.h create mode 100644 arch/arm/boot/dts/sama5d4_proto.dtsi create mode 100644 drivers/pinctrl/pinctrl-at91-pio4.c
Signature · 1 line
2.2.0
RFC PATCH 1/4 pinctrl: change function behavior for per pin muxing controllers
When having a controller which allows per pin muxing, declaring with which groups a function can be used is a useless constraint since groups are something virtual.
--- drivers/pinctrl/pinmux.c | 58 +++++++++++++++++++++++------------------- include/linux/pinctrl/pinmux.h | 3 +++ 2 files changed, 35 insertions(+), 26 deletions(-)
drivers/pinctrl/pinmux.c +32 -26
@@ -40,7 +40,7 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev)if (!ops || !ops->get_functions_count || !ops->get_function_name || - !ops->get_function_groups || + (!ops->get_function_groups & !ops->mux_per_pin) || !ops->set_mux) {dev_err (pctldev->dev,"pinmux ops lacks necessary functions\n" );return -EINVAL ;
@@ -338,36 +338,42 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, } setting->data.mux.func = ret; - ret = pmxops->get_function_groups (pctldev, setting->data.mux.func, - &groups, &num_groups); -if (ret <0 ) { -dev_err (pctldev->dev,"can't query groups for function %s\n" , - map->data.mux.function); -return ret; - } -if (!num_groups) { -dev_err (pctldev->dev, -"function %s can't be selected on any group\n" , - map->data.mux.function); -return -EINVAL ; - } -if (map->data.mux.group) { -bool found = false; - group = map->data.mux.group; -for (i =0 ; i < num_groups; i++) { -if (!strcmp (group, groups[i])) { - found = true; -break ; - } +if (!pmxops->mux_per_pin) { + ret = pmxops->get_function_groups (pctldev, + setting->data.mux.func, + &groups, &num_groups); +if (ret <0 ) { +dev_err (pctldev->dev, +"can't query groups for function %s\n" , + map->data.mux.function); +return ret; } -if (!found) { +if (!num_groups) {dev_err (pctldev->dev, -"invalid group \"%s\" for function \"%s\"\n" , - group, map->data.mux.function); +"function %s can't be selected on any group\n" , + map->data.mux.function);return -EINVAL ; } +if (map->data.mux.group) { +bool found = false; + group = map->data.mux.group; +for (i =0 ; i < num_groups; i++) { +if (!strcmp (group, groups[i])) { + found = true; +break ; + } + } +if (!found) { +dev_err (pctldev->dev, +"invalid group \"%s\" for function \"%s\"\n" , + group, map->data.mux.function); +return -EINVAL ; + } + }else { + group = groups[0 ]; + } }else { - group = groups[0 ]; + group = map->data.mux.group; } ret =pinctrl_get_group_selector (pctldev, group);
include/linux/pinctrl/pinmux.h +3 -0
@@ -23,6 +23,8 @@ struct pinctrl_dev;/** * struct pinmux_ops - pinmux operations, to be implemented by pin controller * drivers that support pinmuxing +* @mux_per_pin: in case of per pin muxing, it removes the need to declare +* with which groups a function can be used. * @request: called by the core to see if a certain pin can be made * available for muxing. This is called by the core to acquire the pins * before selecting any actual mux setting across a function. The driver
@@ -58,6 +60,7 @@ struct pinctrl_dev;* to the GPIO controllers that need pin muxing. */ struct pinmux_ops { +bool mux_per_pin;int (*request) (struct pinctrl_dev *pctldev,unsigned offset);int (*free) (struct pinctrl_dev *pctldev,unsigned offset);int (*get_functions_count) (struct pinctrl_dev *pctldev);
Signature · 1 line
2.2.0
RFC PATCH 2/4 pinctrl: introduce complex pin description
In reply to Ludovic DesrochesSome extra information may be needed to describe a pin, mainly for controllers support per pin muxing where groups are an abstract concept. Instead of using its name, use a 32 bit value whose 16 lowest bits are used for the pin number and the 16 highest ones can be used for extra information.
--- drivers/pinctrl/pinconf-generic.c | 115 +++++++++++++++++++++++++++----------- include/linux/pinctrl/pinctrl.h | 5 ++ 2 files changed, 86 insertions(+), 34 deletions(-)
drivers/pinctrl/pinconf-generic.c +81 -34
@@ -268,28 +268,53 @@ out:return ret; } -int pinconf_generic_dt_subnode_to_map (struct pinctrl_dev *pctldev, +int pinconf_generic_dt_subnode_to_mux_map (struct pinctrl_dev *pctldev,struct device_node *np,struct pinctrl_map **map,unsigned *reserved_maps,unsigned *num_maps, -enum pinctrl_map_type type) +const char *function) {int ret; -const char *function; -struct device *dev = pctldev->dev; -unsigned long *configs =NULL ; -unsigned num_configs =0 ; -unsigned reserve; -struct property *prop;const char *group; -const char *subnode_target_type ="pins" ; +struct property *prop; +struct device *dev = pctldev->dev; ret =of_property_read_string (np,"function" , &function); -if (ret <0 ) { -/* EINVAL=missing, which is fine since it's optional */ -if (ret != -EINVAL ) -dev_err (dev,"could not parse property function\n" ); - function =NULL ; + +of_property_for_each_string (np,"groups" , prop, group) { + + ret =pinctrl_utils_reserve_map (pctldev, map, reserved_maps, + num_maps,1 ); +if (ret <0 ) + goto exit; + + ret =pinctrl_utils_add_map_mux (pctldev, map, reserved_maps, + num_maps, group, function); +if (ret <0 ) + goto exit; } + ret =0 ; + +exit: +return ret; +} + +int pinconf_generic_dt_subnode_to_conf_map (struct pinctrl_dev *pctldev, +struct device_node *np,struct pinctrl_map **map, +unsigned *reserved_maps,unsigned *num_maps, +enum pinctrl_map_type type) +{ +const struct pinctrl_desc *pctldesc = pctldev->desc; +int ret; +unsigned reserve, pin_id; +unsigned long *configs =NULL ; +const char *pin; +const char *group; +const char *subnode_target_type ="pins" ; +struct property *prop; +const __be32 *cur; +u32 val; +unsigned num_configs =0 ; +struct device *dev = pctldev->dev; ret =pinconf_generic_parse_dt_config (np, pctldev, &configs, &num_configs);
@@ -298,14 +323,7 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,return ret; } - reserve =0 ; -if (function !=NULL ) - reserve++; -if (num_configs) - reserve++; - - ret =of_property_count_strings (np,"pins" ); -if (ret <0 ) { +if (!of_property_read_bool (np,"pins" )) { ret =of_property_count_strings (np,"groups" );if (ret <0 ) {dev_err (dev,"could not parse property pins/groups\n" );
@@ -315,26 +333,35 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, type =PIN_MAP_TYPE_CONFIGS_GROUP ; subnode_target_type ="groups" ; }else { +if (pctldesc->complex_pin_desc) + ret =of_property_count_u32_elems (np,"pins" ); +else + ret =of_property_count_strings (np,"pins" ); + +if (ret <0 ) { +dev_err (dev,"could not parse property pins\n" ); + goto exit; + }if (type ==PIN_MAP_TYPE_INVALID ) type =PIN_MAP_TYPE_CONFIGS_PIN ; } - reserve *= ret; + reserve = ret; ret =pinctrl_utils_reserve_map (pctldev, map, reserved_maps, num_maps, reserve);if (ret <0 ) goto exit; -of_property_for_each_string (np, subnode_target_type, prop, group) { -if (function) { - ret =pinctrl_utils_add_map_mux (pctldev, map, - reserved_maps, num_maps, group, - function); -if (ret <0 ) - goto exit; +if (pctldesc->complex_pin_desc) { +of_property_for_each_u32 (np, subnode_target_type, prop, cur, val) { + pin_id = val &PINCTRL_PIN_MASK ; + pin = pctldesc->pins[pin_id].name; + ret =pinctrl_utils_add_map_configs (pctldev, map, + reserved_maps, num_maps, pin, configs, + num_configs, type); } - -if (num_configs) { + }else { +of_property_for_each_string (np, subnode_target_type, prop, group) { ret =pinctrl_utils_add_map_configs (pctldev, map, reserved_maps, num_maps, group, configs, num_configs, type);
@@ -342,12 +369,32 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, goto exit; } } - ret =0 ; - exit:kfree (configs);return ret; } + +int pinconf_generic_dt_subnode_to_map (struct pinctrl_dev *pctldev, +struct device_node *np,struct pinctrl_map **map, +unsigned *reserved_maps,unsigned *num_maps, +enum pinctrl_map_type type) +{ +int ret; +const char *function; +struct device *dev = pctldev->dev; + + ret =of_property_read_string (np,"function" , &function); +if (ret <0 ) { +/* EINVAL=missing, which is fine since it's optional */ +if (ret != -EINVAL ) +dev_err (dev,"could not parse property function\n" ); +return pinconf_generic_dt_subnode_to_conf_map (pctldev, + np, map, reserved_maps, num_maps, type); + }else { +return pinconf_generic_dt_subnode_to_mux_map (pctldev, + np, map, reserved_maps, num_maps, function); + } +}EXPORT_SYMBOL_GPL (pinconf_generic_dt_subnode_to_map); int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
include/linux/pinctrl/pinctrl.h +5 -0
@@ -45,6 +45,8 @@ struct pinctrl_pin_desc {#define PINCTRL_PIN (a, b) { .number = a, .name = b }#define PINCTRL_PIN_ANON (a) { .number = a } +#define PINCTRL_PIN_MASK 0xffff +/** * struct pinctrl_gpio_range - each pin controller can provide subranges of * the GPIO number space to be handled by the controller
@@ -112,6 +114,8 @@ struct pinctrl_ops {* this pin controller * @npins: number of descriptors in the array, usually just ARRAY_SIZE() * of the pins field above +* @complex_pin_desc: some pin controller needs more information than the pin +* name. In this case pins property uses u32 elements instead of strings * @pctlops: pin control operation vtable, to support global concepts like * grouping of pins, this is optional. * @pmxops: pinmux operations vtable, if you support pinmuxing in your driver
@@ -126,6 +130,7 @@ struct pinctrl_desc {const char *name;struct pinctrl_pin_desc const *pins;unsigned int npins; +bool complex_pin_desc;const struct pinctrl_ops *pctlops;const struct pinmux_ops *pmxops;const struct pinconf_ops *confops;
Signature · 1 line
2.2.0
RFC PATCH 3/4 pinctrl: rough draft for a future controller
In reply to Ludovic DesrochesDraft for a future controller which can mux each pin to any functions.
There are up to 6 functions plus a gpio mode (gpio controller driver won't be included in the pincontroller driver).
There is a concept of ioset. An ioset is a set of pins for a device. A device can have several iosets.
There is no obligation to use the whole ioset, for example if you have a mmc 4-bits data bus, you can use data4,5,6,7 for another devices. The pincontroller has no knowledge about the iosets. So potentially you don't have to take care about it BUT validation is done by ioset. It means that if you mix device signals from several iosets, you may have some bugs. That's why we need to warn the user if he mixes pins from several iosets.
There is no chip dependant table, that's why groups (mainly used for ioset and debug sysfs readability) are defined in the device tree.
--- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-at91-pio4.c | 625 ++++++++++++++++++++++++++++++++++++ 3 files changed, 636 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-at91-pio4.c
drivers/pinctrl/Kconfig +10 -0
@@ -67,6 +67,16 @@ config PINCTRL_AT91 help Say Y here to enable the at91 pinctrl driver +config PINCTRL_AT91PIO4 + bool "AT91 PIO4 pinctrl driver" + depends on OF + depends on ARCH_AT91 + select PINMUX + select PINCONF + select GENERIC_PINCONF + help + Say Y here to enable the at91-pio4 pinctrl driver + config PINCTRL_BAYTRAIL bool "Intel Baytrail GPIO pin control" depends on GPIOLIB && ACPI && X86
drivers/pinctrl/Makefile +1 -0
@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o +obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
drivers/pinctrl/pinctrl-at91-pio4.c new file +625 -0
625 lines not on this page · raw message
Signature · 1 line
2.2.0
RFC PATCH 4/4 ARM: at91/dt: proto dt
In reply to Ludovic Desroches--- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/at91-sama5d4ek_proto.dts | 243 ++++++++++ arch/arm/boot/dts/sama5d4_proto-pinfunc.h | 463 +++++++++++++++++++ arch/arm/boot/dts/sama5d4_proto.dtsi | 716 +++++++++++++++++++++++++++++ 4 files changed, 1423 insertions(+) create mode 100644 arch/arm/boot/dts/at91-sama5d4ek_proto.dts create mode 100644 arch/arm/boot/dts/sama5d4_proto-pinfunc.h create mode 100644 arch/arm/boot/dts/sama5d4_proto.dtsi
arch/arm/boot/dts/Makefile +1 -0
@@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_AT91) += sama5d36ek_revc.dtb # sama5d4 dtb-$(CONFIG_ARCH_AT91) += at91-sama5d4_xplained.dtb dtb-$(CONFIG_ARCH_AT91) += at91-sama5d4ek.dtb +dtb-$(CONFIG_ARCH_AT91) += at91-sama5d4ek_proto.dtb dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb
arch/arm/boot/dts/at91-sama5d4ek_proto.dts new file +243 -0
243 lines not on this page · raw message
arch/arm/boot/dts/sama5d4_proto-pinfunc.h new file +463 -0
463 lines not on this page · raw message
arch/arm/boot/dts/sama5d4_proto.dtsi new file +716 -0
716 lines not on this page · raw message
Signature · 1 line
2.2.0
cover pinctrl: prototyping a per pin mux approach
In reply to Ludovic DesrochesQuoted 45 lines · Ludovic Desroches
Hi,
Here is an implementation of what I need for the future at91 pin controller. The pinctrl driver is a draft made for a sama5d4 in order to test it. It is not clean and many things are missing but I think it will be easier to debate on code.
From the discussion with Sascha, it seems that we agree that current pinctrl doesn't fit the needs of controllers who have per pin muxing because the concepts of groups is not real.
In my opinion, even if groups are not real it is quite convenient to use them at least for debug sysfs.The new at91 pin controller is close to Mediatek one. I am not totally happy with their solution since a group is describing a pin. It is probably the easiest way to do it but it doesn't fit my needs. I have two constraints:
- I want something readable in sysfs as:
device fc000000.mmc
state default
typeMUX_GROUP(2)
controlling device ahb:apb:pinctrl atfc06a000
groupmci1_0_4bit
function Cdevice fc000000.mmc
state default
typeCONFIGS_PIN(3)
controlling device ahb:apb:pinctrl atfc06a000
pin PE19
config 00010003I don't want to have a group named as a pin.
- I want to perform some verifications on user choices. A concept of ioset is introduced. An ioset is a set of pins dedicated to a device. A device can have several iosets. For example we can have i2c0 ioset1 with pins PA0 and PA1 and i2c0 ioset2 with pins PE10 and PE11. The controller has no knowledge about iosets. It means I could take the i2c data signal from ioset1 and the i2c clock signal from ioset2 BUT validation has been done only per ioset. For devices such as i2c it should not be a problem but it could be for other ones such as mci, isi, etc.
Quoted 2 lines
- I don't want big tables describing pins in my driver. It represents a huge amount of code mainly useless in the case of a multiplatform image.
This is needed due to some misdesign in the pinctrl core that's just, sorry, braindamaged. The pinctrl core forces you to parse a device node (which your driver perfectly understands) into a struct pinctrl_map. This struct contains a struct pinctrl_map_mux which contains a group and a function as strings. With the help of the driver struct pinctrl_map is converted to struct pinctrl_setting which basically contains the same information, but with a struct pinctrl_setting_mux which contains a group and a function as integers. Instead of passing this data back to the driver to act upon the structs are shred into pieces and passed to the driver as individual variables.
So to recap the pinctrl core forces you to parse your data from the device node into a format not native to the driver, then uses the drivers help to convert this data in yet another format which it then passes back to the driver in little pieces. Note that the pinctrl core doesn't even use all this data except for requesting pins and for generating debugfs entries. These debugfs entries even often contain useless information because neither struct pinctrl_map nor struct pinctrl_setting are suitable for storing information for per-pin controllers. Most drivers only put some information in there to find the informations back the device node already contained.
A sane approach would just let the driver parse the data from a device node into a cookie which is then passed back to the driver to be activated. The driver would then be free to store whatever information it needs in this cookie. The driver just request the necessary pins itself from the pinctrl core instead of letting the core doing it.
I know this is not the answer you were looking for, but the pinctrl core in my eyes is a big midlayer mistake and I'm not very fond of stretching this concept further to be able to live with it for another round.
Sascha
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
cover pinctrl: prototyping a per pin mux approach
Hello Sascha,
Quoted 77 lines · Sascha Hauer
Quoted 45 lines · Ludovic Desroches
Hi,
Here is an implementation of what I need for the future at91 pin controller. The pinctrl driver is a draft made for a sama5d4 in order to test it. It is not clean and many things are missing but I think it will be easier to debate on code.
From the discussion with Sascha, it seems that we agree that current pinctrl doesn't fit the needs of controllers who have per pin muxing because the concepts of groups is not real.
In my opinion, even if groups are not real it is quite convenient to use them at least for debug sysfs.The new at91 pin controller is close to Mediatek one. I am not totally happy with their solution since a group is describing a pin. It is probably the easiest way to do it but it doesn't fit my needs. I have two constraints:
- I want something readable in sysfs as:
device fc000000.mmc
state default
typeMUX_GROUP(2)
controlling device ahb:apb:pinctrl atfc06a000
groupmci1_0_4bit
function Cdevice fc000000.mmc
state default
typeCONFIGS_PIN(3)
controlling device ahb:apb:pinctrl atfc06a000
pin PE19
config 00010003I don't want to have a group named as a pin.
- I want to perform some verifications on user choices. A concept of ioset is introduced. An ioset is a set of pins dedicated to a device. A device can have several iosets. For example we can have i2c0 ioset1 with pins PA0 and PA1 and i2c0 ioset2 with pins PE10 and PE11. The controller has no knowledge about iosets. It means I could take the i2c data signal from ioset1 and the i2c clock signal from ioset2 BUT validation has been done only per ioset. For devices such as i2c it should not be a problem but it could be for other ones such as mci, isi, etc.
Quoted 2 lines
- I don't want big tables describing pins in my driver. It represents a huge amount of code mainly useless in the case of a multiplatform image.
This is needed due to some misdesign in the pinctrl core that's just, sorry, braindamaged. The pinctrl core forces you to parse a device node (which your driver perfectly understands) into a struct
pinctrl_map. This struct contains a structpinctrl_map_muxwhich contains a group and a function as strings. With the help of the driver structpinctrl_mapis converted to structpinctrl_settingwhich basically contains the same information, but with a structpinctrl_setting_muxwhich contains a group and a function as integers. Instead of passing this data back to the driver to act upon the structs are shred into pieces and passed to the driver as individual variables.So to recap the pinctrl core forces you to parse your data from the device node into a format not native to the driver, then uses the drivers help to convert this data in yet another format which it then passes back to the driver in little pieces. Note that the pinctrl core doesn't even use all this data except for requesting pins and for generating debugfs entries. These debugfs entries even often contain useless information because neither struct
pinctrl_mapnor structpinctrl_settingare suitable for storing information for per-pin controllers. Most drivers only put some information in there to find the informations back the device node already contained.A sane approach would just let the driver parse the data from a device node into a cookie which is then passed back to the driver to be activated. The driver would then be free to store whatever information it needs in this cookie. The driver just request the necessary pins itself from the pinctrl core instead of letting the core doing it.
Quoted 4 lines
I know this is not the answer you were looking for, but the pinctrl core in my eyes is a big midlayer mistake and I'm not very fond of stretching this concept further to be able to live with it for another round.
For sure it was not the kind of answer I was looking for :) I understand your point of view.
I won't discuss about the design of the pinctrl. I don't have enough knowledge about other controllers and I have never worked on a midlayer.
My concern is the actual pinctrl doesn't fit my needs and add some strong constraints. I don't have the time (and probably not the skill) to re-design pinctrl without introducing breakage for existing users. My goal is to try to find some ways to make it more flexible.
Linus, what do you think about all this? Are the changes proposed acceptable?
Regards
Ludovic