Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh-pfc: Add pinconf support to DT bindings

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Laurent Pinchart and committed by
Linus Walleij
12f3ad8d fe1c9a82

+124 -21
+27 -9
Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
··· 30 30 to pinctrl-bindings.txt in this directory for the definition of the term "pin 31 31 configuration node" and for the common pinctrl bindings used by client devices. 32 32 33 - Each pin configuration node represents desired functions to select on a pin 34 - group or a list of pin groups. The functions and pin groups can be specified 35 - directly in the pin configuration node, or grouped in child subnodes. Several 36 - functions can thus be referenced as a single pin configuration node by client 37 - devices. 33 + Each pin configuration node represents a desired configuration for a pin, a 34 + pin group, or a list of pins or pin groups. The configuration can include the 35 + function to select on those pin(s) and pin configuration parameters (such as 36 + pull-up and pull-down). 38 37 39 - A configuration node or subnode must contain a function and reference at least 40 - one pin group. 38 + Pin configuration nodes contain pin configuration properties, either directly 39 + or grouped in child subnodes. Both pin muxing and configuration parameters can 40 + be grouped in that way and referenced as a single pin configuration node by 41 + client devices. 42 + 43 + A configuration node or subnode must reference at least one pin (through the 44 + pins or pin groups properties) and contain at least a function or one 45 + configuration parameter. When the function is present only pin groups can be 46 + used to reference pins. 41 47 42 48 All pin configuration nodes and subnodes names are ignored. All of those nodes 43 49 are parsed through phandles and processed purely based on their content. 44 50 45 51 Pin Configuration Node Properties: 46 52 53 + - renesas,pins : An array of strings, each string containing the name of a pin. 47 54 - renesas,groups : An array of strings, each string containing the name of a pin 48 55 group. 49 56 ··· 60 53 Valid values for pin, group and function names can be found in the group and 61 54 function arrays of the PFC data file corresponding to the SoC 62 55 (drivers/pinctrl/sh-pfc/pfc-*.c) 56 + 57 + The pin configuration parameters use the generic pinconf bindings defined in 58 + pinctrl-bindings.txt in this directory. The supported parameters are 59 + bias-disable, bias-pull-up and bias-pull-down. 63 60 64 61 65 62 GPIO ··· 124 113 pinctrl-names = "default"; 125 114 126 115 mmcif_pins: mmcif { 127 - renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0"; 128 - renesas,function = "mmc0"; 116 + mux { 117 + renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0"; 118 + renesas,function = "mmc0"; 119 + }; 120 + cfg { 121 + renesas,groups = "mmc0_data8_0"; 122 + renesas,pins = "PORT279"; 123 + bias-pull-up; 124 + }; 129 125 }; 130 126 131 127 scifa4_pins: scifa4 {
+97 -12
drivers/pinctrl/sh-pfc/pinctrl.c
··· 74 74 seq_printf(s, "%s", DRV_NAME); 75 75 } 76 76 77 + static int sh_pfc_map_add_config(struct pinctrl_map *map, 78 + const char *group_or_pin, 79 + enum pinctrl_map_type type, 80 + unsigned long *configs, 81 + unsigned int num_configs) 82 + { 83 + unsigned long *cfgs; 84 + 85 + cfgs = kmemdup(configs, num_configs * sizeof(*cfgs), 86 + GFP_KERNEL); 87 + if (cfgs == NULL) 88 + return -ENOMEM; 89 + 90 + map->type = type; 91 + map->data.configs.group_or_pin = group_or_pin; 92 + map->data.configs.configs = cfgs; 93 + map->data.configs.num_configs = num_configs; 94 + 95 + return 0; 96 + } 97 + 77 98 static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, 78 99 struct pinctrl_map **map, 79 100 unsigned int *num_maps, unsigned int *index) ··· 102 81 struct pinctrl_map *maps = *map; 103 82 unsigned int nmaps = *num_maps; 104 83 unsigned int idx = *index; 84 + unsigned int num_configs; 105 85 const char *function = NULL; 86 + unsigned long *configs; 106 87 struct property *prop; 88 + unsigned int num_groups; 89 + unsigned int num_pins; 107 90 const char *group; 91 + const char *pin; 108 92 int ret; 109 93 110 94 /* Parse the function and configuration properties. At least a function ··· 121 95 return ret; 122 96 } 123 97 124 - if (!function) { 125 - dev_err(dev, "DT node must contain at least one function\n"); 98 + ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs); 99 + if (ret < 0) 100 + return ret; 101 + 102 + if (!function && num_configs == 0) { 103 + dev_err(dev, 104 + "DT node must contain at least a function or config\n"); 126 105 goto done; 127 106 } 128 107 129 - /* Count the number of groups and reallocate mappings. */ 108 + /* Count the number of pins and groups and reallocate mappings. */ 109 + ret = of_property_count_strings(np, "renesas,pins"); 110 + if (ret == -EINVAL) { 111 + num_pins = 0; 112 + } else if (ret < 0) { 113 + dev_err(dev, "Invalid pins list in DT\n"); 114 + goto done; 115 + } else { 116 + num_pins = ret; 117 + } 118 + 130 119 ret = of_property_count_strings(np, "renesas,groups"); 131 - if (ret < 0 && ret != -EINVAL) { 120 + if (ret == -EINVAL) { 121 + num_groups = 0; 122 + } else if (ret < 0) { 132 123 dev_err(dev, "Invalid pin groups list in DT\n"); 133 124 goto done; 125 + } else { 126 + num_groups = ret; 134 127 } 135 128 136 - if (!ret) { 137 - dev_err(dev, "No group provided in DT node\n"); 129 + if (!num_pins && !num_groups) { 130 + dev_err(dev, "No pin or group provided in DT node\n"); 138 131 ret = -ENODEV; 139 132 goto done; 140 133 } 141 134 142 - nmaps += ret; 135 + if (function) 136 + nmaps += num_groups; 137 + if (configs) 138 + nmaps += num_pins + num_groups; 143 139 144 140 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL); 145 141 if (maps == NULL) { ··· 174 126 175 127 /* Iterate over pins and groups and create the mappings. */ 176 128 of_property_for_each_string(np, "renesas,groups", prop, group) { 177 - maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; 178 - maps[idx].data.mux.group = group; 179 - maps[idx].data.mux.function = function; 129 + if (function) { 130 + maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; 131 + maps[idx].data.mux.group = group; 132 + maps[idx].data.mux.function = function; 133 + idx++; 134 + } 135 + 136 + if (configs) { 137 + ret = sh_pfc_map_add_config(&maps[idx], group, 138 + PIN_MAP_TYPE_CONFIGS_GROUP, 139 + configs, num_configs); 140 + if (ret < 0) 141 + goto done; 142 + 143 + idx++; 144 + } 145 + } 146 + 147 + if (!configs) { 148 + ret = 0; 149 + goto done; 150 + } 151 + 152 + of_property_for_each_string(np, "renesas,pins", prop, pin) { 153 + ret = sh_pfc_map_add_config(&maps[idx], pin, 154 + PIN_MAP_TYPE_CONFIGS_PIN, 155 + configs, num_configs); 156 + if (ret < 0) 157 + goto done; 158 + 180 159 idx++; 181 160 } 182 161 183 - ret = 0; 184 - 185 162 done: 186 163 *index = idx; 164 + kfree(configs); 187 165 return ret; 188 166 } 189 167 190 168 static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev, 191 169 struct pinctrl_map *map, unsigned num_maps) 192 170 { 171 + unsigned int i; 172 + 173 + if (map == NULL) 174 + return; 175 + 176 + for (i = 0; i < num_maps; ++i) { 177 + if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP || 178 + map[i].type == PIN_MAP_TYPE_CONFIGS_PIN) 179 + kfree(map[i].data.configs.configs); 180 + } 181 + 193 182 kfree(map); 194 183 } 195 184