Add support for muxing individual pins
Subsystems (21)
cover Add support for muxing individual pins
This series add support for muxing individual pins within pin mux, rather than just whole groups. Mainly, I had two motivations here, one to avoid the need to add loads of groups containing individual pins and hardware that actually has some internal concept of groups of pins, and disambiguating that from individual pin muxing. I have marked it as RFC to just get peoples opinions at this stage, although it should be pretty well tested. Sorry about the amount of files touched in patch 2 it would be possible to drop it from the chain although it leaves the field rather inaccurately named.
Also I have left all the existing code paths parsing all mux options as groups from DT, and added a new helper to unlock the pin based functionality this should ease the transition across.
Thanks,
Charles
Charles Keepax (4):
pinctrl: Factor out individual pin handling from pinmux_pins_show
pinctrl: Rename mux group to group_or_pin to prepare for pin support
pinctrl: Add support for muxing individual pins
pinctrl: Add support for parsing individual pinmux from DT
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- drivers/pinctrl/core.c | 26 ++- drivers/pinctrl/core.h | 3 +- drivers/pinctrl/freescale/pinctrl-imx.c | 5 +- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 5 +- drivers/pinctrl/freescale/pinctrl-mxs.c | 4 +- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +- drivers/pinctrl/mvebu/pinctrl-mvebu.c | 2 +- drivers/pinctrl/nomadik/pinctrl-abx500.c | 2 +- drivers/pinctrl/nomadik/pinctrl-nomadik.c | 2 +- drivers/pinctrl/pinconf-generic.c | 30 ++- drivers/pinctrl/pinctrl-at91.c | 5 +- drivers/pinctrl/pinctrl-lantiq.c | 2 +- drivers/pinctrl/pinctrl-rockchip.c | 5 +- drivers/pinctrl/pinctrl-rza1.c | 2 +- drivers/pinctrl/pinctrl-single.c | 4 +- drivers/pinctrl/pinctrl-st.c | 2 +- drivers/pinctrl/pinctrl-tz1090-pdc.c | 2 +- drivers/pinctrl/pinctrl-tz1090.c | 2 +- drivers/pinctrl/pinctrl-utils.c | 10 +- drivers/pinctrl/pinctrl-utils.h | 14 +- drivers/pinctrl/pinmux.c | 311 ++++++++++++++++++-------- drivers/pinctrl/samsung/pinctrl-exynos5440.c | 4 +- drivers/pinctrl/samsung/pinctrl-samsung.c | 2 +- drivers/pinctrl/sh-pfc/pinctrl.c | 2 +- drivers/pinctrl/sirf/pinctrl-atlas7.c | 3 +- drivers/pinctrl/sirf/pinctrl-sirf.c | 2 +- drivers/pinctrl/spear/pinctrl-spear.c | 2 +- drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +- drivers/pinctrl/vt8500/pinctrl-wmt.c | 2 +- include/linux/pinctrl/machine.h | 3 +- include/linux/pinctrl/pinconf-generic.h | 24 +- include/linux/pinctrl/pinmux.h | 7 + 34 files changed, 338 insertions(+), 159 deletions(-)
Signature · 1 line
2.11.0
RFC PATCH 1/4 pinctrl: Factor out individual pin handling from pinmux_pins_show
Add a new helper function to be called for each pin rather than keeping everything in the same function. Primarily this just reduces the code indentation a bit.
--- drivers/pinctrl/pinmux.c | 100 +++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 47 deletions(-)
drivers/pinctrl/pinmux.c +53 -47
@@ -555,12 +555,61 @@ static int pinmux_functions_show(struct seq_file *s, void *what)return 0 ; } -static int pinmux_pins_show (struct seq_file *s,void *what) +static int pinmux_pin_show (struct seq_file *s,unsigned int pin) {struct pinctrl_dev *pctldev = s->private;const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;const struct pinmux_ops *pmxops = pctldev->desc->pmxops; -unsigned i, pin; +struct pin_desc *desc =pin_desc_get (pctldev, pin); +bool is_hog = false; + +/* Skip if we cannot search the pin */ +if (desc ==NULL ) +return 0 ; + +if (desc->mux_owner && + !strcmp (desc->mux_owner,pinctrl_dev_get_name (pctldev))) + is_hog = true; + +if (pmxops->strict) { +if (desc->mux_owner) +seq_printf (s,"pin %d (%s): device %s%s" , + pin, desc->name, desc->mux_owner, + is_hog ?" (HOG)" :"" ); +else if (desc->gpio_owner) +seq_printf (s,"pin %d (%s): GPIO %s" , + pin, desc->name, desc->gpio_owner); +else +seq_printf (s,"pin %d (%s): UNCLAIMED" , + pin, desc->name); + }else { +/* For non-strict controllers */ +seq_printf (s,"pin %d (%s): %s %s%s" , pin, desc->name, + desc->mux_owner ? desc->mux_owner + :"(MUX UNCLAIMED)" , + desc->gpio_owner ? desc->gpio_owner + :"(GPIO UNCLAIMED)" , + is_hog ?" (HOG)" :"" ); + } + +/* If mux: print function+group claiming the pin */ +if (desc->mux_setting) +seq_printf (s," function %s group %s\n" , + pmxops->get_function_name (pctldev, + desc->mux_setting->func), + pctlops->get_group_name (pctldev, + desc->mux_setting->group)); +else +seq_puts (s,"\n" ); + +return 0 ; +} + +static int pinmux_pins_show (struct seq_file *s,void *what) +{ +struct pinctrl_dev *pctldev = s->private; +const struct pinmux_ops *pmxops = pctldev->desc->pmxops; +unsigned int i;if (!pmxops)return 0 ;
@@ -576,51 +625,8 @@ static int pinmux_pins_show(struct seq_file *s, void *what)mutex_lock (&pctldev->mutex);/* The pin number can be retrived from the pin controller descriptor */ -for (i =0 ; i < pctldev->desc->npins; i++) { -struct pin_desc *desc; -bool is_hog = false; - - pin = pctldev->desc->pins[i].number; - desc =pin_desc_get (pctldev, pin); -/* Skip if we cannot search the pin */ -if (desc ==NULL ) -continue ; - -if (desc->mux_owner && - !strcmp (desc->mux_owner,pinctrl_dev_get_name (pctldev))) - is_hog = true; - -if (pmxops->strict) { -if (desc->mux_owner) -seq_printf (s,"pin %d (%s): device %s%s" , - pin, desc->name, desc->mux_owner, - is_hog ?" (HOG)" :"" ); -else if (desc->gpio_owner) -seq_printf (s,"pin %d (%s): GPIO %s" , - pin, desc->name, desc->gpio_owner); -else -seq_printf (s,"pin %d (%s): UNCLAIMED" , - pin, desc->name); - }else { -/* For non-strict controllers */ -seq_printf (s,"pin %d (%s): %s %s%s" , pin, desc->name, - desc->mux_owner ? desc->mux_owner - :"(MUX UNCLAIMED)" , - desc->gpio_owner ? desc->gpio_owner - :"(GPIO UNCLAIMED)" , - is_hog ?" (HOG)" :"" ); - } - -/* If mux: print function+group claiming the pin */ -if (desc->mux_setting) -seq_printf (s," function %s group %s\n" , - pmxops->get_function_name (pctldev, - desc->mux_setting->func), - pctlops->get_group_name (pctldev, - desc->mux_setting->group)); -else -seq_printf (s,"\n" ); - } +for (i =0 ; i < pctldev->desc->npins; i++) +pinmux_pin_show (s, pctldev->desc->pins[i].number);mutex_unlock (&pctldev->mutex);
Signature · 1 line
2.11.0
RFC PATCH 2/4 pinctrl: Rename mux group to group_or_pin to prepare for pin support
In reply to Charles KeepaxFrom: Charles Keepax <[email protected]>
To prepare for adding support for muxing individual pins rename the group member of the pinctrl_map_mux and pinctrl_setting_mux structs to group_or_pin.
--- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- drivers/pinctrl/core.h | 2 +- drivers/pinctrl/freescale/pinctrl-imx.c | 5 ++-- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 5 ++-- drivers/pinctrl/freescale/pinctrl-mxs.c | 4 +-- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +- drivers/pinctrl/mvebu/pinctrl-mvebu.c | 2 +- drivers/pinctrl/nomadik/pinctrl-abx500.c | 2 +- drivers/pinctrl/nomadik/pinctrl-nomadik.c | 2 +- drivers/pinctrl/pinctrl-at91.c | 5 ++-- drivers/pinctrl/pinctrl-lantiq.c | 2 +- drivers/pinctrl/pinctrl-rockchip.c | 5 ++-- drivers/pinctrl/pinctrl-rza1.c | 2 +- drivers/pinctrl/pinctrl-single.c | 4 +-- drivers/pinctrl/pinctrl-st.c | 2 +- drivers/pinctrl/pinctrl-tz1090-pdc.c | 2 +- drivers/pinctrl/pinctrl-tz1090.c | 2 +- drivers/pinctrl/pinctrl-utils.c | 2 +- drivers/pinctrl/pinmux.c | 37 +++++++++++++++------------ drivers/pinctrl/samsung/pinctrl-exynos5440.c | 4 +-- drivers/pinctrl/samsung/pinctrl-samsung.c | 2 +- drivers/pinctrl/sh-pfc/pinctrl.c | 2 +- drivers/pinctrl/sirf/pinctrl-sirf.c | 2 +- drivers/pinctrl/spear/pinctrl-spear.c | 2 +- drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +- drivers/pinctrl/vt8500/pinctrl-wmt.c | 2 +- include/linux/pinctrl/machine.h | 2 +- 28 files changed, 59 insertions(+), 50 deletions(-)
drivers/pinctrl/bcm/pinctrl-bcm2835.c +1 -1
@@ -692,7 +692,7 @@ static int bcm2835_pctl_dt_node_to_map_func(struct bcm2835_pinctrl *pc, } map->type =PIN_MAP_TYPE_MUX_GROUP ; - map->data.mux.group = bcm2835_gpio_groups[pin]; + map->data.mux.group_or_pin = bcm2835_gpio_groups[pin]; map->data.mux.function = bcm2835_functions[fnum]; (*maps)++;
drivers/pinctrl/core.h +1 -1
@@ -102,7 +102,7 @@ struct pinctrl_state {* @func: the function selector to program */ struct pinctrl_setting_mux { -unsigned group; +unsigned group_or_pin;unsigned func; };
drivers/pinctrl/freescale/pinctrl-imx.c +3 -2
@@ -102,7 +102,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, } new_map[0 ].type =PIN_MAP_TYPE_MUX_GROUP ; new_map[0 ].data.mux.function = parent->name; - new_map[0 ].data.mux.group = np->name; + new_map[0 ].data.mux.group_or_pin = np->name;of_node_put (parent);/* create config map */
@@ -121,7 +121,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, }dev_dbg (pctldev->dev,"maps: function %s group %s num %d\n" , - (*map)->data.mux.function, (*map)->data.mux.group, map_num); + (*map)->data.mux.function, (*map)->data.mux.group_or_pin, + map_num);return 0 ; }
drivers/pinctrl/freescale/pinctrl-imx1-core.c +3 -2
@@ -261,7 +261,7 @@ static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev, } new_map[0 ].type =PIN_MAP_TYPE_MUX_GROUP ; new_map[0 ].data.mux.function = parent->name; - new_map[0 ].data.mux.group = np->name; + new_map[0 ].data.mux.group_or_pin = np->name;of_node_put (parent);/* create config map */
@@ -276,7 +276,8 @@ static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev, }dev_dbg (pctldev->dev,"maps: function %s group %s num %d\n" , - (*map)->data.mux.function, (*map)->data.mux.group, map_num); + (*map)->data.mux.function, (*map)->data.mux.group_or_pin, + map_num);return 0 ; }
drivers/pinctrl/freescale/pinctrl-mxs.c +2 -2
@@ -111,7 +111,7 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, goto free; }snprintf (group, length,"%s.%d" , np->name, reg); - new_map[i].data.mux.group = group; + new_map[i].data.mux.group_or_pin = group; i++; }
@@ -149,7 +149,7 @@ static void mxs_dt_free_map(struct pinctrl_dev *pctldev,for (i =0 ; i < num_maps; i++) {if (map[i].type ==PIN_MAP_TYPE_MUX_GROUP ) -kfree (map[i].data.mux.group); +kfree (map[i].data.mux.group_or_pin);if (map[i].type ==PIN_MAP_TYPE_CONFIGS_GROUP )kfree (map[i].data.configs.configs); }
drivers/pinctrl/mediatek/pinctrl-mtk-common.c +1 -1
@@ -475,7 +475,7 @@ static int mtk_pctrl_dt_node_to_map_func(struct mtk_pinctrl *pctl,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = grp->name; + (*map)[*num_maps].data.mux.group_or_pin = grp->name; ret =mtk_pctrl_is_function_valid (pctl, pin, fnum);if (!ret) {
drivers/pinctrl/mvebu/pinctrl-mvebu.c +1 -1
@@ -445,7 +445,7 @@ static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, } (*map)[n].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[n].data.mux.group = group; + (*map)[n].data.mux.group_or_pin = group; (*map)[n].data.mux.function = function; n++; }
drivers/pinctrl/nomadik/pinctrl-abx500.c +1 -1
@@ -815,7 +815,7 @@ static int abx500_dt_add_map_mux(struct pinctrl_map **map,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;
drivers/pinctrl/nomadik/pinctrl-nomadik.c +1 -1
@@ -1270,7 +1270,7 @@ static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;
drivers/pinctrl/pinctrl-at91.c +3 -2
@@ -284,7 +284,7 @@ static int at91_dt_node_to_map(struct pinctrl_dev *pctldev, } new_map[0 ].type =PIN_MAP_TYPE_MUX_GROUP ; new_map[0 ].data.mux.function = parent->name; - new_map[0 ].data.mux.group = np->name; + new_map[0 ].data.mux.group_or_pin = np->name;of_node_put (parent);/* create config map */
@@ -298,7 +298,8 @@ static int at91_dt_node_to_map(struct pinctrl_dev *pctldev, }dev_dbg (pctldev->dev,"maps: function %s group %s num %d\n" , - (*map)->data.mux.function, (*map)->data.mux.group, map_num); + (*map)->data.mux.function, (*map)->data.mux.group_or_pin, + map_num);return 0 ; }
drivers/pinctrl/pinctrl-lantiq.c +1 -1
@@ -96,7 +96,7 @@ static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,of_property_for_each_string (np,"lantiq,groups" , prop, group) { (*map)->type =PIN_MAP_TYPE_MUX_GROUP ; (*map)->name = function; - (*map)->data.mux.group = group; + (*map)->data.mux.group_or_pin = group; (*map)->data.mux.function = function; (*map)++; }
drivers/pinctrl/pinctrl-rockchip.c +3 -2
@@ -522,7 +522,7 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, } new_map[0 ].type =PIN_MAP_TYPE_MUX_GROUP ; new_map[0 ].data.mux.function = parent->name; - new_map[0 ].data.mux.group = np->name; + new_map[0 ].data.mux.group_or_pin = np->name;of_node_put (parent);/* create config map */
@@ -536,7 +536,8 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, }dev_dbg (pctldev->dev,"maps: function %s group %s num %d\n" , - (*map)->data.mux.function, (*map)->data.mux.group, map_num); + (*map)->data.mux.function, (*map)->data.mux.group_or_pin, + map_num);return 0 ; }
drivers/pinctrl/pinctrl-rza1.c +1 -1
@@ -952,7 +952,7 @@ static int rza1_dt_node_to_map(struct pinctrl_dev *pctldev, } (*map)->type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)->data.mux.group = np->name; + (*map)->data.mux.group_or_pin = np->name; (*map)->data.mux.function = np->name; *num_maps =1 ;
drivers/pinctrl/pinctrl-single.c +2 -2
@@ -1019,7 +1019,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, goto free_function; (*map)->type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)->data.mux.group = np->name; + (*map)->data.mux.group_or_pin = np->name; (*map)->data.mux.function = np->name;if (PCS_HAS_PINCONF ) {
@@ -1153,7 +1153,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, goto free_function; (*map)->type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)->data.mux.group = np->name; + (*map)->data.mux.group_or_pin = np->name; (*map)->data.mux.function = np->name;if (PCS_HAS_PINCONF ) {
drivers/pinctrl/pinctrl-st.c +1 -1
@@ -838,7 +838,7 @@ static int st_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, *num_maps = map_num; new_map[0 ].type =PIN_MAP_TYPE_MUX_GROUP ; new_map[0 ].data.mux.function = parent->name; - new_map[0 ].data.mux.group = np->name; + new_map[0 ].data.mux.group_or_pin = np->name;of_node_put (parent);/* create config map per pin */
drivers/pinctrl/pinctrl-tz1090-pdc.c +1 -1
@@ -318,7 +318,7 @@ static int add_map_mux(struct pinctrl_map **map, unsigned int *reserved_maps,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;
drivers/pinctrl/pinctrl-tz1090.c +1 -1
@@ -1062,7 +1062,7 @@ static int add_map_mux(struct pinctrl_map **map, unsigned int *reserved_maps,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;
drivers/pinctrl/pinctrl-utils.c +1 -1
@@ -62,7 +62,7 @@ int pinctrl_utils_add_map_mux(struct pinctrl_dev *pctldev,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;
drivers/pinctrl/pinmux.c +21 -16
@@ -348,8 +348,8 @@ int pinmux_map_to_setting(const struct pinctrl_map *map, map->data.mux.function);return -EINVAL ; } -if (map->data.mux.group) { - group = map->data.mux.group; +if (map->data.mux.group_or_pin) { + group = map->data.mux.group_or_pin; ret =match_string (groups, num_groups, group);if (ret <0 ) { dev_err(pctldev->dev,
@@ -364,10 +364,10 @@ int pinmux_map_to_setting(const struct pinctrl_map *map, ret =pinctrl_get_group_selector (pctldev, group);if (ret <0 ) {dev_err (pctldev->dev,"invalid group %s in map table\n" , - map->data.mux.group); + map->data.mux.group_or_pin);return ret; } - setting->data.mux.group = ret; + setting->data.mux.group_or_pin = ret;return 0 ; }
@@ -389,7 +389,8 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)struct pin_desc *desc;if (pctlops->get_group_pins) - ret = pctlops->get_group_pins (pctldev, setting->data.mux.group, + ret = pctlops->get_group_pins (pctldev, + setting->data.mux.group_or_pin, &pins, &num_pins);if (ret) {
@@ -397,7 +398,7 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)/* errors only affect debug data, so just warn */ gname = pctlops->get_group_name (pctldev, - setting->data.mux.group); + setting->data.mux.group_or_pin);dev_warn (pctldev->dev,"could not get pins for group %s\n" , gname);
@@ -414,7 +415,7 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting) desc =pin_desc_get (pctldev, pins[i]); pname = desc ? desc->name :"non-existing" ; gname = pctlops->get_group_name (pctldev, - setting->data.mux.group); + setting->data.mux.group_or_pin); dev_err(pctldev->dev, "could not request pin %d (%s) from group %s " " on device %s\n",
@@ -437,7 +438,7 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting) } ret = ops->set_mux (pctldev, setting->data.mux.func, - setting->data.mux.group); + setting->data.mux.group_or_pin);if (ret) goto err_set_mux;
@@ -469,14 +470,15 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)struct pin_desc *desc;if (pctlops->get_group_pins) - ret = pctlops->get_group_pins (pctldev, setting->data.mux.group, + ret = pctlops->get_group_pins (pctldev, + setting->data.mux.group_or_pin, &pins, &num_pins);if (ret) {const char *gname;/* errors only affect debug data, so just warn */ gname = pctlops->get_group_name (pctldev, - setting->data.mux.group); + setting->data.mux.group_or_pin);dev_warn (pctldev->dev,"could not get pins for group %s\n" , gname);
@@ -500,7 +502,7 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)const char *gname; gname = pctlops->get_group_name (pctldev, - setting->data.mux.group); + setting->data.mux.group_or_pin);dev_warn (pctldev->dev,"not freeing pin %d (%s) as part of " "deactivating group %s - it is already "
@@ -598,7 +600,7 @@ static int pinmux_pin_show(struct seq_file *s, unsigned int pin) pmxops->get_function_name (pctldev, desc->mux_setting->func), pctlops->get_group_name (pctldev, - desc->mux_setting->group)); + desc->mux_setting->group_or_pin)); else seq_puts(s, "\n");
@@ -635,9 +637,11 @@ static int pinmux_pins_show(struct seq_file *s, void *what)void pinmux_show_map (struct seq_file *s,const struct pinctrl_map *map) { +const struct pinctrl_map_mux *mux = &map->data.mux; +seq_printf (s,"group %s\nfunction %s\n" , - map->data.mux.group ? map->data.mux.group :"(default)" , - map->data.mux.function); + mux->group_or_pin ? mux->group_or_pin :"(default)" , + mux->function); } void pinmux_show_setting(struct seq_file *s,
@@ -648,8 +652,9 @@ void pinmux_show_setting(struct seq_file *s,const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;seq_printf (s,"group: %s (%u) function: %s (%u)\n" , - pctlops->get_group_name (pctldev, setting->data.mux.group), - setting->data.mux.group, + pctlops->get_group_name (pctldev, + setting->data.mux.group_or_pin), + setting->data.mux.group_or_pin, pmxops->get_function_name (pctldev, setting->data.mux.func), setting->data.mux.func); }
drivers/pinctrl/samsung/pinctrl-exynos5440.c +2 -2
@@ -254,7 +254,7 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,if (!fname) goto free_cfg; - map[*nmaps].data.mux.group = gname; + map[*nmaps].data.mux.group_or_pin = gname; map[*nmaps].data.mux.function = fname; map[*nmaps].type =PIN_MAP_TYPE_MUX_GROUP ; *nmaps +=1 ;
@@ -282,7 +282,7 @@ static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,if (map[idx].type ==PIN_MAP_TYPE_MUX_GROUP ) {kfree (map[idx].data.mux.function);if (!idx) -kfree (map[idx].data.mux.group); +kfree (map[idx].data.mux.group_or_pin); }else if (map->type ==PIN_MAP_TYPE_CONFIGS_GROUP ) {kfree (map[idx].data.configs.configs);if (!idx)
drivers/pinctrl/samsung/pinctrl-samsung.c +1 -1
@@ -111,7 +111,7 @@ static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;
drivers/pinctrl/sh-pfc/pinctrl.c +1 -1
@@ -202,7 +202,7 @@ static int sh_pfc_dt_subnode_to_map(struct pinctrl_dev *pctldev,of_property_for_each_string (np, pmx->groups_prop_name, prop, group) {if (function) { maps[idx].type =PIN_MAP_TYPE_MUX_GROUP ; - maps[idx].data.mux.group = group; + maps[idx].data.mux.group_or_pin = group; maps[idx].data.mux.function = function; idx++; }
drivers/pinctrl/sirf/pinctrl-sirf.c +1 -1
@@ -116,7 +116,7 @@ static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,of_property_read_string (np,"sirf,function" , &function);of_property_for_each_string (np,"sirf,pins" , prop, group) { (*map)[index].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[index].data.mux.group = group; + (*map)[index].data.mux.group_or_pin = group; (*map)[index].data.mux.function = function; index++; }
drivers/pinctrl/spear/pinctrl-spear.c +1 -1
@@ -180,7 +180,7 @@ static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,of_property_read_string (np,"st,function" , &function);of_property_for_each_string (np,"st,pins" , prop, group) { (*map)[index].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[index].data.mux.group = group; + (*map)[index].data.mux.group_or_pin = group; (*map)[index].data.mux.function = function; index++; }
drivers/pinctrl/stm32/pinctrl-stm32.c +1 -1
@@ -375,7 +375,7 @@ static int stm32_pctrl_dt_node_to_map_func(struct stm32_pinctrl *pctl,return -ENOSPC ; (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[*num_maps].data.mux.group = grp->name; + (*map)[*num_maps].data.mux.group_or_pin = grp->name;if (!stm32_pctrl_is_function_valid (pctl, pin, fnum)) { dev_err(pctl->dev, "invalid function %d on pin %d .\n",
drivers/pinctrl/sunxi/pinctrl-sunxi.c +1 -1
@@ -377,7 +377,7 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, } (*map)[i].type =PIN_MAP_TYPE_MUX_GROUP ; - (*map)[i].data.mux.group = group; + (*map)[i].data.mux.group_or_pin = group; (*map)[i].data.mux.function = function; i++;
drivers/pinctrl/vt8500/pinctrl-wmt.c +1 -1
@@ -232,7 +232,7 @@ static int wmt_pctl_dt_node_to_map_func(struct wmt_pinctrl_data *data, } map->type =PIN_MAP_TYPE_MUX_GROUP ; - map->data.mux.group = data->groups[group]; + map->data.mux.group_or_pin = data->groups[group]; map->data.mux.function = wmt_functions[fnum]; (*maps)++;
include/linux/pinctrl/machine.h +1 -1
@@ -32,7 +32,7 @@ enum pinctrl_map_type {* @function: the mux function to select for the group */ struct pinctrl_map_mux { -const char *group; +const char *group_or_pin;const char *function; };
Signature · 1 line
2.11.0
Re: [PATCH RFC 2/4] pinctrl: Rename mux group to group_or_pin to prepare for pin support
Quoted 16 lines · Charles Keepax
From: Charles Keepax <[email protected]>
To prepare for adding support for muxing individual pins rename the group member of the
pinctrl_map_muxandpinctrl_setting_muxstructs togroup_or_pin.Signed-off-by Charles Keepax <[email protected]>--- include/linux/pinctrl/machine.h | 2 +- 28 files changed, 59 insertions(+), 50 deletions(-)include/linux/pinctrl/machine.h +0
-0
include/linux/pinctrl/machine.h enum pinctrl_map_type { · line 37
Quoted 7 lines
include/linux/pinctrl/machine.h +1
-1@@ -32,7 +32,7 @@ enum pinctrl_map_type {* @function: the mux function to select for the group */ struct pinctrl_map_mux { -const char *group; +const char *group_or_pin;const char *function; };
One additional fix is required for PIN_MAP_MUX_GROUP in this file.
Thanks,
Charles
RFC PATCH 3/4 pinctrl: Add support for muxing individual pins
In reply to Charles KeepaxFrom: Charles Keepax <[email protected]>
Currently pinmuxing can only be applied to groups, this has lead to several drivers within the kernel adding many pin groups that just contain a single pin to allow muxing of individual pins.
Add support to the core for muxing individual pins. Groups are still used as a mechanism to determine if a function is suitable to be applied to a specific pin. For example a pin might be in the GPIO group allowing it to be muxed to a GPIO but it would now be possible to just mux one pin from that group.
This change makes no changes to the current DT parsing, everything will still be parsed into a group type map.
--- drivers/pinctrl/core.c | 26 ++++- drivers/pinctrl/core.h | 1 + drivers/pinctrl/pinmux.c | 218 +++++++++++++++++++++++++++++----------- include/linux/pinctrl/machine.h | 1 + include/linux/pinctrl/pinmux.h | 7 ++ 5 files changed, 192 insertions(+), 61 deletions(-)
drivers/pinctrl/core.c +22 -4
@@ -950,6 +950,7 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev, setting->dev_name = map->dev_name;switch (map->type) { +case PIN_MAP_TYPE_MUX_PIN :case PIN_MAP_TYPE_MUX_GROUP : ret =pinmux_map_to_setting (map, setting);break ;
@@ -1104,6 +1105,7 @@ static void pinctrl_free_setting(bool disable_setting, struct pinctrl_setting *setting) {switch (setting->type) { +case PIN_MAP_TYPE_MUX_PIN :case PIN_MAP_TYPE_MUX_GROUP :if (disable_setting)pinmux_disable_setting (setting);
@@ -1210,9 +1212,14 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)* to pinmux_enable_setting() in the loop below. */ list_for_each_entry (setting, &p->state->settings, node) { -if (setting->type !=PIN_MAP_TYPE_MUX_GROUP ) -continue ; -pinmux_disable_setting (setting); +switch (setting->type) { +case PIN_MAP_TYPE_MUX_GROUP : +case PIN_MAP_TYPE_MUX_PIN : +pinmux_disable_setting (setting); +break ; +default : +break ; + } } }
@@ -1221,6 +1228,7 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)/* Apply all the settings for the new state */ list_for_each_entry (setting, &state->settings, node) {switch (setting->type) { +case PIN_MAP_TYPE_MUX_PIN :case PIN_MAP_TYPE_MUX_GROUP : ret =pinmux_enable_setting (setting);break ;
@@ -1255,8 +1263,14 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)* "unmux a pin"!), but it's not a big deal since the pins * are free to be muxed by another apply_setting. */ -if (setting2->type ==PIN_MAP_TYPE_MUX_GROUP ) +switch (setting2->type) { +case PIN_MAP_TYPE_MUX_GROUP : +case PIN_MAP_TYPE_MUX_PIN :pinmux_disable_setting (setting2); +break ; +default : +break ; + } }/* There's no infinite recursive loop here because p->state is NULL */
@@ -1353,6 +1367,7 @@ int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,switch (maps[i].type) {case PIN_MAP_TYPE_DUMMY_STATE :break ; +case PIN_MAP_TYPE_MUX_PIN :case PIN_MAP_TYPE_MUX_GROUP : ret =pinmux_validate_map (&maps[i], i);if (ret <0 )
@@ -1686,6 +1701,7 @@ static inline const char *map_type(enum pinctrl_map_type type)static const char *const names[] = {"INVALID" ,"DUMMY_STATE" , +"MUX_PIN" ,"MUX_GROUP" ,"CONFIGS_PIN" ,"CONFIGS_GROUP" ,
@@ -1716,6 +1732,7 @@ static int pinctrl_maps_show(struct seq_file *s, void *what) map->ctrl_dev_name);switch (map->type) { +case PIN_MAP_TYPE_MUX_PIN :case PIN_MAP_TYPE_MUX_GROUP :pinmux_show_map (s, map);break ;
@@ -1760,6 +1777,7 @@ static int pinctrl_show(struct seq_file *s, void *what) pinctrl_dev_get_name(pctldev));switch (setting->type) { +case PIN_MAP_TYPE_MUX_PIN :case PIN_MAP_TYPE_MUX_GROUP :pinmux_show_setting (s, setting);break ;
drivers/pinctrl/core.h +1 -0
@@ -166,6 +166,7 @@ struct pin_desc {#ifdef CONFIG_PINMUX unsigned mux_usecount;const char *mux_owner; +enum pinctrl_map_type mux_type;const struct pinctrl_setting_mux *mux_setting;const char *gpio_owner;#endif
drivers/pinctrl/pinmux.c +161 -57
327 lines not on this page · raw message
include/linux/pinctrl/machine.h +1 -0
@@ -19,6 +19,7 @@enum pinctrl_map_type {PIN_MAP_TYPE_INVALID ,PIN_MAP_TYPE_DUMMY_STATE , +PIN_MAP_TYPE_MUX_PIN ,PIN_MAP_TYPE_MUX_GROUP ,PIN_MAP_TYPE_CONFIGS_PIN ,PIN_MAP_TYPE_CONFIGS_GROUP ,
include/linux/pinctrl/pinmux.h +7 -0
@@ -45,6 +45,11 @@ struct pinctrl_dev;* are handled by the pinmux subsystem. The @func_selector selects a * certain function whereas @group_selector selects a certain set of pins * to be used. On simple controllers the latter argument may be ignored +* @set_mux_pin: enable a certain muxing function with a certain pin. The driver +* does not need to figure out whether enabling this function conflicts +* some other use of the pin, such collisions are handled by the pinmux +* subsystem. The @func_selector selects a certain function whereas +* @pin_selector selects a certain pin to be used. * @gpio_request_enable: requests and enables GPIO on a certain pin. * Implement this only if you can mux every pin individually as GPIO. The * affected GPIO range is passed along with an offset(pin number) into that
@@ -72,6 +77,8 @@ struct pinmux_ops { unsigned *num_groups);int (*set_mux) (struct pinctrl_dev *pctldev,unsigned func_selector,unsigned group_selector); +int (*set_mux_pin) (struct pinctrl_dev *pctldev,unsigned func_selector, +unsigned pin_selector);int (*gpio_request_enable) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset);
Signature · 1 line
2.11.0
RFC PATCH 4/4 pinctrl: Add support for parsing individual pinmux from DT
In reply to Charles KeepaxFrom: Charles Keepax <[email protected]>
So as to not break existing drivers that rely on pins properties being treated as a group, leave functionality of the existing generic parsing functions the same. Add a new parsing function pinctrl_generic_dt_node_to_map_all that will map pin properties from DT to the newly created pin type maps.
--- drivers/pinctrl/pinconf-generic.c | 30 +++++++++++++++++++----------- drivers/pinctrl/pinctrl-utils.c | 8 ++++---- drivers/pinctrl/pinctrl-utils.h | 14 ++++++++++++-- drivers/pinctrl/sirf/pinctrl-atlas7.c | 3 ++- include/linux/pinctrl/pinconf-generic.h | 24 +++++++++++++++++++----- 5 files changed, 56 insertions(+), 23 deletions(-)
drivers/pinctrl/pinconf-generic.c +19 -11
@@ -287,7 +287,8 @@ int pinconf_generic_parse_dt_config(struct device_node *np,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) +enum pinctrl_map_type conf_type, +enum pinctrl_map_type mux_type) {int ret;const char *function;
@@ -305,12 +306,16 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,if (ret <0 )/* skip this node; may contain config child nodes */ return 0 ; -if (type ==PIN_MAP_TYPE_INVALID ) - type =PIN_MAP_TYPE_CONFIGS_GROUP ; +if (conf_type ==PIN_MAP_TYPE_INVALID ) + conf_type =PIN_MAP_TYPE_CONFIGS_GROUP ; +if (mux_type ==PIN_MAP_TYPE_INVALID ) + mux_type =PIN_MAP_TYPE_MUX_GROUP ; subnode_target_type ="groups" ; }else { -if (type ==PIN_MAP_TYPE_INVALID ) - type =PIN_MAP_TYPE_CONFIGS_PIN ; +if (conf_type ==PIN_MAP_TYPE_INVALID ) + conf_type =PIN_MAP_TYPE_CONFIGS_PIN ; +if (mux_type ==PIN_MAP_TYPE_INVALID ) + mux_type =PIN_MAP_TYPE_MUX_PIN ; } strings_count = ret;
@@ -345,9 +350,9 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,of_property_for_each_string (np, subnode_target_type, prop, group) {if (function) { - ret =pinctrl_utils_add_map_mux (pctldev, map, + ret =pinctrl_utils_add_map_mux_type (pctldev, map, reserved_maps, num_maps, group, - function); + function, mux_type);if (ret <0 ) goto exit; }
@@ -355,7 +360,7 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,if (num_configs) { ret =pinctrl_utils_add_map_configs (pctldev, map, reserved_maps, num_maps, group, configs, - num_configs, type); + num_configs, conf_type);if (ret <0 ) goto exit; }
@@ -370,7 +375,8 @@ EXPORT_SYMBOL_GPL(pinconf_generic_dt_subnode_to_map);int pinconf_generic_dt_node_to_map (struct pinctrl_dev *pctldev,struct device_node *np_config,struct pinctrl_map **map, -unsigned *num_maps,enum pinctrl_map_type type) +unsigned *num_maps,enum pinctrl_map_type conf_type, +enum pinctrl_map_type mux_type) {unsigned reserved_maps;struct device_node *np;
@@ -381,13 +387,15 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, *num_maps =0 ; ret =pinconf_generic_dt_subnode_to_map (pctldev, np_config, map, - &reserved_maps, num_maps, type); + &reserved_maps, num_maps, + conf_type, mux_type);if (ret <0 ) goto exit;for_each_available_child_of_node (np_config, np) { ret =pinconf_generic_dt_subnode_to_map (pctldev, np, map, - &reserved_maps, num_maps, type); + &reserved_maps, num_maps, + conf_type, mux_type);if (ret <0 ) goto exit; }
drivers/pinctrl/pinctrl-utils.c +4 -4
@@ -53,22 +53,22 @@ int pinctrl_utils_reserve_map(struct pinctrl_dev *pctldev, }EXPORT_SYMBOL_GPL (pinctrl_utils_reserve_map); -int pinctrl_utils_add_map_mux (struct pinctrl_dev *pctldev, +int pinctrl_utils_add_map_mux_type (struct pinctrl_dev *pctldev,struct pinctrl_map **map,unsigned *reserved_maps,unsigned *num_maps,const char *group, -const char *function) +const char *function,enum pinctrl_map_type type) {if (WARN_ON (*num_maps == *reserved_maps))return -ENOSPC ; - (*map)[*num_maps].type =PIN_MAP_TYPE_MUX_GROUP ; + (*map)[*num_maps].type = type; (*map)[*num_maps].data.mux.group_or_pin = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++;return 0 ; } -EXPORT_SYMBOL_GPL (pinctrl_utils_add_map_mux); +EXPORT_SYMBOL_GPL (pinctrl_utils_add_map_mux_type); int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev, struct pinctrl_map **map, unsigned *reserved_maps,
drivers/pinctrl/pinctrl-utils.h +12 -2
@@ -25,10 +25,10 @@int pinctrl_utils_reserve_map (struct pinctrl_dev *pctldev,struct pinctrl_map **map,unsigned *reserved_maps,unsigned *num_maps,unsigned reserve); -int pinctrl_utils_add_map_mux (struct pinctrl_dev *pctldev, +int pinctrl_utils_add_map_mux_type (struct pinctrl_dev *pctldev,struct pinctrl_map **map,unsigned *reserved_maps,unsigned *num_maps,const char *group, -const char *function); +const char *function,enum pinctrl_map_type type); int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev, struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps, const char *group,
@@ -40,4 +40,14 @@ int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,void pinctrl_utils_free_map (struct pinctrl_dev *pctldev,struct pinctrl_map *map,unsigned num_maps); +static inline int pinctrl_utils_add_map_mux (struct pinctrl_dev *pctldev, +struct pinctrl_map **map,unsigned *reserved_maps, +unsigned *num_maps,const char *group, +const char *function) +{ +return pinctrl_utils_add_map_mux_type (pctldev, map, reserved_maps, + num_maps, group, function, +PIN_MAP_TYPE_MUX_GROUP ); +} +#endif /* __PINCTRL_UTILS_H__ */
drivers/pinctrl/sirf/pinctrl-atlas7.c +2 -1
@@ -5301,7 +5301,8 @@ static int atlas7_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, u32 *num_maps) {return pinconf_generic_dt_node_to_map (pctldev, np_config, map, - num_maps,PIN_MAP_TYPE_INVALID ); + num_maps,PIN_MAP_TYPE_INVALID , +PIN_MAP_TYPE_MUX_GROUP ); } static void atlas7_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
include/linux/pinctrl/pinconf-generic.h +19 -5
@@ -180,10 +180,12 @@ struct pinconf_generic_params {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); +enum pinctrl_map_type conf_type, +enum pinctrl_map_type mux_type);int pinconf_generic_dt_node_to_map (struct pinctrl_dev *pctldev,struct device_node *np_config,struct pinctrl_map **map, -unsigned *num_maps,enum pinctrl_map_type type); +unsigned *num_maps,enum pinctrl_map_type conf_type, +enum pinctrl_map_type mux_type);void pinconf_generic_dt_free_map (struct pinctrl_dev *pctldev,struct pinctrl_map *map,unsigned num_maps);
@@ -192,7 +194,7 @@ static inline int pinconf_generic_dt_node_to_map_group( struct pinctrl_map **map, unsigned *num_maps) { return pinconf_generic_dt_node_to_map(pctldev, np_config, map, num_maps, -PIN_MAP_TYPE_CONFIGS_GROUP ); +PIN_MAP_TYPE_CONFIGS_GROUP ,PIN_MAP_TYPE_MUX_GROUP ); } static inline int pinconf_generic_dt_node_to_map_pin(
@@ -200,7 +202,7 @@ static inline int pinconf_generic_dt_node_to_map_pin( struct pinctrl_map **map, unsigned *num_maps) { return pinconf_generic_dt_node_to_map(pctldev, np_config, map, num_maps, -PIN_MAP_TYPE_CONFIGS_PIN ); +PIN_MAP_TYPE_CONFIGS_PIN ,PIN_MAP_TYPE_MUX_GROUP ); } static inline int pinconf_generic_dt_node_to_map_all(
@@ -212,7 +214,19 @@ static inline int pinconf_generic_dt_node_to_map_all(* to infer the map type from the DT properties used. */ return pinconf_generic_dt_node_to_map (pctldev, np_config, map, num_maps, - PIN_MAP_TYPE_INVALID); + PIN_MAP_TYPE_INVALID, PIN_MAP_TYPE_MUX_GROUP); +} + +static inline int pinctrl_generic_dt_node_to_map_all ( +struct pinctrl_dev *pctldev,struct device_node *np_config, +struct pinctrl_map **map,unsigned *num_maps) +{ +/* +* passing the type as PIN_MAP_TYPE_INVALID causes the underlying parser +* to infer the map type from the DT properties used. +*/ +return pinconf_generic_dt_node_to_map (pctldev, np_config, map, num_maps, +PIN_MAP_TYPE_INVALID ,PIN_MAP_TYPE_INVALID ); }#endif
Signature · 1 line
2.11.0
Quoted 11 lines · Charles Keepax
This series add support for muxing individual pins within pin mux, rather than just whole groups. Mainly, I had two motivations here, one to avoid the need to add loads of groups containing individual pins and hardware that actually has some internal concept of groups of pins, and disambiguating that from individual pin muxing. I have marked it as RFC to just get peoples opinions at this stage, although it should be pretty well tested. Sorry about the amount of files touched in patch 2 it would be possible to drop it from the chain although it leaves the field rather inaccurately named.
Quoted 3 lines
Also I have left all the existing code paths parsing all mux options as groups from DT, and added a new helper to unlock the pin based functionality this should ease the transition across.
There is currently a driver in the pin control subsystem that handles individual pins and that is pinctrl-single.c.
The driver is deployed for single pins muxed by a single register, and if this infrastructure is to be deployed it must be applied also in pinctrl-single. We cannot have several ways of doing the same thing, that way lies madness.
So you need Tony Lindgren's review and direction on this patch series.
I see the problem you are setting out to solve. I too have ran into the situation (on systems such as Qualcomm's) where single-pin groups are more rule than exception. It would be good to alleviate this and handle it in the core somehow.
Yours,
Linus Walleij
Quoted 18 lines · Linus Walleij
Quoted 11 lines · Charles Keepax
This series add support for muxing individual pins within pin mux, rather than just whole groups. Mainly, I had two motivations here, one to avoid the need to add loads of groups containing individual pins and hardware that actually has some internal concept of groups of pins, and disambiguating that from individual pin muxing. I have marked it as RFC to just get peoples opinions at this stage, although it should be pretty well tested. Sorry about the amount of files touched in patch 2 it would be possible to drop it from the chain although it leaves the field rather inaccurately named.
Quoted 3 lines
Also I have left all the existing code paths parsing all mux options as groups from DT, and added a new helper to unlock the pin based functionality this should ease the transition across.
Quoted 8 lines
There is currently a driver in the pin control subsystem that handles individual pins and that is
pinctrl-single.c.The driver is deployed for single pins muxed by a single register, and if this infrastructure is to be deployed it must be applied also in pinctrl-single. We cannot have several ways of doing the same thing, that way lies madness.
Apologies for the oversight I will have a look at that and try to update the series as appropriate. I am travelling for the next couple of weeks so there might be a small lag in getting an updated version out.
Quoted 3 lines
So you need Tony Lindgren's review and direction on this patch series.
Any thoughts would be greatly appreciated.
Quoted 4 lines
I see the problem you are setting out to solve. I too have ran into the situation (on systems such as Qualcomm's) where single-pin groups are more rule than exception. It would be good to alleviate this and handle it in the core somehow.
Thanks,
Charles
Quoted 19 lines · Linus Walleij
Quoted 11 lines · Charles Keepax
This series add support for muxing individual pins within pin mux, rather than just whole groups. Mainly, I had two motivations here, one to avoid the need to add loads of groups containing individual pins and hardware that actually has some internal concept of groups of pins, and disambiguating that from individual pin muxing. I have marked it as RFC to just get peoples opinions at this stage, although it should be pretty well tested. Sorry about the amount of files touched in patch 2 it would be possible to drop it from the chain although it leaves the field rather inaccurately named.
Quoted 3 lines
Also I have left all the existing code paths parsing all mux options as groups from DT, and added a new helper to unlock the pin based functionality this should ease the transition across.
There is currently a driver in the pin control subsystem that handles individual pins and that is
pinctrl-single.c.
Quoted 7 lines
The driver is deployed for single pins muxed by a single register, and if this infrastructure is to be deployed it must be applied also in pinctrl-single. We cannot have several ways of doing the same thing, that way lies madness.
So you need Tony Lindgren's review and direction on this patch series.
Apologies for the delay on this one, I got some what snowed under with other tasks. Please let me know if you would rather I just resent the series to refresh everyones memory. But I have finally managed to get some time to look over the pinctrl-single stuff.
Naively one could convert the pinctrl-single stuff over to use the patches I proposed creating one large group for the driver and then mux each pin individually from within that. However I am not really sure it would make sense. From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others. My thinking had been more along the lines of you perhaps have a group that represents an I2S port but you can also individually assign each of those pins as a GPIO when not in use as the I2S port.
Alternatively one could perhaps look at expanding the pinctrl-single stuff to have some notion of groups as well. So you could define sub groups of the pins that can be set as a block. Allowing users to configure either groups or individual pins.
I guess my main question is what is the intention of the pinctrl-single code, is this something that should be seeing expansion to handle groups as well or is it firmly for the unrelated pins cases?
Thanks,
Charles
Quoted 16 lines · Charles Keepax
(...) I have finally
managed to get some time to look over the pinctrl-single stuff.Naively one could convert the pinctrl-single stuff over to use the patches I proposed creating one large group for the driver and then mux each pin individually from within that. However I am not really sure it would make sense. From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others. My thinking had been more along the lines of you perhaps have a group that represents an I2S port but you can also individually assign each of those pins as a GPIO when not in use as the I2S port.
So then I toss the qcom driver into the game instead :)
If you look at drivers/pinctrl/qcom/* e.g. pinctrl-ipq4019.c or essentially any of the subdrivers, you find exactly this scenario.
I am concerned that if we add infrastructure for this, it needs to have more than one user. Qualcomm does fit your description above I think.
Yours,
Linus Walleij
Quoted 20 lines · Linus Walleij
Quoted 16 lines · Charles Keepax
(...) I have finally
managed to get some time to look over the pinctrl-single stuff.Naively one could convert the pinctrl-single stuff over to use the patches I proposed creating one large group for the driver and then mux each pin individually from within that. However I am not really sure it would make sense. From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others. My thinking had been more along the lines of you perhaps have a group that represents an I2S port but you can also individually assign each of those pins as a GPIO when not in use as the I2S port.
Quoted 9 lines
So then I toss the qcom driver into the game instead :)
If you look at
drivers/pinctrl/qcom/*e.g.pinctrl-ipq4019.cor essentially any of the subdrivers, you find exactly this scenario.I am concerned that if we add infrastructure for this, it needs to have more than one user. Qualcomm does fit your description above I think.
Yeah I could certainly have a hunt through for other users that would make good candidates to update. The QC driver certainly looks like it would be capable of muxing individual pins, although it looks like it might not let you mux an individual GPIO at the moment, need to dig into that more.
I guess maybe a bigger question is do we think this is a problem worth solving or should really just be adding a group for each pin I want to be able to mux?
Thanks,
Charles
Quoted 31 lines · Charles Keepax
Quoted 20 lines · Linus Walleij
Quoted 16 lines · Charles Keepax
(...) I have finally
managed to get some time to look over the pinctrl-single stuff.Naively one could convert the pinctrl-single stuff over to use the patches I proposed creating one large group for the driver and then mux each pin individually from within that. However I am not really sure it would make sense. From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others. My thinking had been more along the lines of you perhaps have a group that represents an I2S port but you can also individually assign each of those pins as a GPIO when not in use as the I2S port.
Quoted 9 lines
So then I toss the qcom driver into the game instead :)
If you look at
drivers/pinctrl/qcom/*e.g.pinctrl-ipq4019.cor essentially any of the subdrivers, you find exactly this scenario.I am concerned that if we add infrastructure for this, it needs to have more than one user. Qualcomm does fit your description above I think.
Quoted 6 lines
Yeah I could certainly have a hunt through for other users that would make good candidates to update. The QC driver certainly looks like it would be capable of muxing individual pins, although it looks like it might not let you mux an individual GPIO at the moment, need to dig into that more.
In the Qualcomm hardware we have X GPIO pins and some number of special purpose pins. GPIO pins can be muxed and controlled individually and the special purpose pins (e.g. SDCC) are controlled as a group.
I expected to describe both of these types as "pinctrl groups", but after struggling with this I realized that as the control is on pin-granularity (for the GPIOs) this is what should be represented as a group in pinctl/pinmux/pinconf.
So each GPIO pin can be controlled/muxed individually and as such is represented as a group, special groups are describes as one group (matching the single set of registers).
To configure a "logical group" (e.g. a UART), we list each pin (technically group), specify the same function and the necessary configuration options.
So if you hardware supports configuring individual pins within a group my suggestion is that you should rework the driver to make "group" match "configurable thing" and then tie together logical groups when configuring your system.
PS. A side effect of this is that e.g. UART is a function of 4 pins, but by specifying the pinmux/pinconf of only two of them I have a 2 pin UART, without having to describe this setup in the pinctrl driver.
Regards,
Bjorn
Tony Lindgren
maintainerQuoted 6 lines · Charles Keepax
From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others.
Maybe check again or else I don't follow you :)
The pinctrl groups are created dynamically with pinctrl-single based on how the pins are grouped in the dts file:
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x0e2, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0e4, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0e6, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0e8, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0ea, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0ec, PIN_INPUT_PULLUP | MUX_MODE0)
>;
};Then on a booted system we have the following under /sys/kernel/debug/pinctrl/4a100040.pinmux/pingroups:
group: pinmux_mmc1_pins
pin 81 (PIN81)
pin 82 (PIN82)
pin 83 (PIN83)
pin 84 (PIN84)
pin 85 (PIN85)
pin 86 (PIN86)
Regards,
Tony
Quoted 27 lines · Tony Lindgren
Quoted 6 lines · Charles Keepax
From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others.
Maybe check again or else I don't follow you :)
The pinctrl groups are created dynamically with pinctrl-single based on how the pins are grouped in the dts file:
mmc1_pins: pinmux_mmc1_pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0e2, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0e4, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0e6, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0e8, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0ea, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0ec, PIN_INPUT_PULLUP | MUX_MODE0) >; };Then on a booted system we have the following under
/sys/kernel/debug/pinctrl/4a100040.pinmux/pingroups:
Quoted 8 lines
group:
pinmux_mmc1_pins
pin 81 (PIN81)
pin 82 (PIN82)
pin 83 (PIN83)
pin 84 (PIN84)
pin 85 (PIN85)
pin 86 (PIN86)
Hmm... apologies, I suspect this is me that needs to review the code some more. So this is actually creating a group per user rather than per controller.
Although I guess my original point still stands that I am not clear how this would benefit from my patches to allow muxing of individual pins within a group. Since I guess each user will just get a group created for the pins they use regardless. Or am I missing something here too?
Thanks,
Charles
Tony Lindgren
maintainerQuoted 41 lines · Charles Keepax
Quoted 27 lines · Tony Lindgren
Quoted 6 lines · Charles Keepax
From the implementation so far the pinctrl-single stuff appears to target systems where there isn't really a concept of groups. Each pin is just a completely separate entry and you can only configure things one pin at a time. In that case it almost makes more sense to model each pin as an individual group such that it is clearly distinct from the others.
Maybe check again or else I don't follow you :)
The pinctrl groups are created dynamically with pinctrl-single based on how the pins are grouped in the dts file:
mmc1_pins: pinmux_mmc1_pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0e2, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0e4, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0e6, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0e8, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0ea, PIN_INPUT_PULLUP | MUX_MODE0) OMAP4_IOPAD(0x0ec, PIN_INPUT_PULLUP | MUX_MODE0) >; };Then on a booted system we have the following under
/sys/kernel/debug/pinctrl/4a100040.pinmux/pingroups:Quoted 8 lines
group:
pinmux_mmc1_pins
pin 81 (PIN81)
pin 82 (PIN82)
pin 83 (PIN83)
pin 84 (PIN84)
pin 85 (PIN85)
pin 86 (PIN86)Hmm... apologies, I suspect this is me that needs to review the code some more. So this is actually creating a group per user rather than per controller.
Quoted 5 lines
Although I guess my original point still stands that I am not clear how this would benefit from my patches to allow muxing of individual pins within a group. Since I guess each user will just get a group created for the pins they use regardless. Or am I missing something here too?
Yeah it seems pinctrl-single does not need anything specific for muxing individual pins within a group. You can already do that quite easily by creating multiple groups in the dts for the device. Let's assume you need to dynamically remux MMC dat1 line between GPIO and MMC mode (similar to what we do on am335x for dat1 wake-up interrupts). In that case you would just modify the grouping example above with:
mmc1_dat1_pin: pinmux_mmc1_dat1_pin {
pinctrl-single,pins = <
OMAP4_IOPAD(0x0e8, PIN_INPUT_PULLUP | MUX_MODE0)
>;
};mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x0e2, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0e4, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0e6, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0ea, PIN_INPUT_PULLUP | MUX_MODE0)
OMAP4_IOPAD(0x0ec, PIN_INPUT_PULLUP | MUX_MODE0)
>;
};And that allows you to dynamically change dat1 pin only.
Not sure if that helps in your case though, just trying to clarify how it currently works :)
Regards,
Tony