aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt36
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c109
2 files changed, 124 insertions, 21 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
index 8264cbcdd418..d5dac7b843a9 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
@@ -30,20 +30,27 @@ The PFC node also acts as a container for pin configuration nodes. Please refer
30to pinctrl-bindings.txt in this directory for the definition of the term "pin 30to pinctrl-bindings.txt in this directory for the definition of the term "pin
31configuration node" and for the common pinctrl bindings used by client devices. 31configuration node" and for the common pinctrl bindings used by client devices.
32 32
33Each pin configuration node represents desired functions to select on a pin 33Each pin configuration node represents a desired configuration for a pin, a
34group or a list of pin groups. The functions and pin groups can be specified 34pin group, or a list of pins or pin groups. The configuration can include the
35directly in the pin configuration node, or grouped in child subnodes. Several 35function to select on those pin(s) and pin configuration parameters (such as
36functions can thus be referenced as a single pin configuration node by client 36pull-up and pull-down).
37devices.
38 37
39A configuration node or subnode must contain a function and reference at least 38Pin configuration nodes contain pin configuration properties, either directly
40one pin group. 39or grouped in child subnodes. Both pin muxing and configuration parameters can
40be grouped in that way and referenced as a single pin configuration node by
41client devices.
42
43A configuration node or subnode must reference at least one pin (through the
44pins or pin groups properties) and contain at least a function or one
45configuration parameter. When the function is present only pin groups can be
46used to reference pins.
41 47
42All pin configuration nodes and subnodes names are ignored. All of those nodes 48All pin configuration nodes and subnodes names are ignored. All of those nodes
43are parsed through phandles and processed purely based on their content. 49are parsed through phandles and processed purely based on their content.
44 50
45Pin Configuration Node Properties: 51Pin Configuration Node Properties:
46 52
53- renesas,pins : An array of strings, each string containing the name of a pin.
47- renesas,groups : An array of strings, each string containing the name of a pin 54- renesas,groups : An array of strings, each string containing the name of a pin
48 group. 55 group.
49 56
@@ -54,6 +61,10 @@ Pin Configuration Node Properties:
54 function arrays of the PFC data file corresponding to the SoC 61 function arrays of the PFC data file corresponding to the SoC
55 (drivers/pinctrl/sh-pfc/pfc-*.c) 62 (drivers/pinctrl/sh-pfc/pfc-*.c)
56 63
64The pin configuration parameters use the generic pinconf bindings defined in
65pinctrl-bindings.txt in this directory. The supported parameters are
66bias-disable, bias-pull-up and bias-pull-down.
67
57 68
58GPIO 69GPIO
59---- 70----
@@ -113,8 +124,15 @@ Example 3: KZM-A9-GT (SH-Mobile AG5) default pin state hog and pin control maps
113 pinctrl-names = "default"; 124 pinctrl-names = "default";
114 125
115 mmcif_pins: mmcif { 126 mmcif_pins: mmcif {
116 renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0"; 127 mux {
117 renesas,function = "mmc0"; 128 renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
129 renesas,function = "mmc0";
130 };
131 cfg {
132 renesas,groups = "mmc0_data8_0";
133 renesas,pins = "PORT279";
134 bias-pull-up;
135 };
118 }; 136 };
119 137
120 scifa4_pins: scifa4 { 138 scifa4_pins: scifa4 {
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 7e32bb8c08dd..2cf23476adf8 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -74,6 +74,27 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
74 seq_printf(s, "%s", DRV_NAME); 74 seq_printf(s, "%s", DRV_NAME);
75} 75}
76 76
77static 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
77static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, 98static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
78 struct pinctrl_map **map, 99 struct pinctrl_map **map,
79 unsigned int *num_maps, unsigned int *index) 100 unsigned int *num_maps, unsigned int *index)
@@ -81,9 +102,14 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
81 struct pinctrl_map *maps = *map; 102 struct pinctrl_map *maps = *map;
82 unsigned int nmaps = *num_maps; 103 unsigned int nmaps = *num_maps;
83 unsigned int idx = *index; 104 unsigned int idx = *index;
105 unsigned int num_configs;
84 const char *function = NULL; 106 const char *function = NULL;
107 unsigned long *configs;
85 struct property *prop; 108 struct property *prop;
109 unsigned int num_groups;
110 unsigned int num_pins;
86 const char *group; 111 const char *group;
112 const char *pin;
87 int ret; 113 int ret;
88 114
89 /* Parse the function and configuration properties. At least a function 115 /* Parse the function and configuration properties. At least a function
@@ -95,25 +121,47 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
95 return ret; 121 return ret;
96 } 122 }
97 123
98 if (!function) { 124 ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
99 dev_err(dev, "DT node must contain at least one function\n"); 125 if (ret < 0)
126 return ret;
127
128 if (!function && num_configs == 0) {
129 dev_err(dev,
130 "DT node must contain at least a function or config\n");
100 goto done; 131 goto done;
101 } 132 }
102 133
103 /* Count the number of groups and reallocate mappings. */ 134 /* Count the number of pins and groups and reallocate mappings. */
135 ret = of_property_count_strings(np, "renesas,pins");
136 if (ret == -EINVAL) {
137 num_pins = 0;
138 } else if (ret < 0) {
139 dev_err(dev, "Invalid pins list in DT\n");
140 goto done;
141 } else {
142 num_pins = ret;
143 }
144
104 ret = of_property_count_strings(np, "renesas,groups"); 145 ret = of_property_count_strings(np, "renesas,groups");
105 if (ret < 0 && ret != -EINVAL) { 146 if (ret == -EINVAL) {
147 num_groups = 0;
148 } else if (ret < 0) {
106 dev_err(dev, "Invalid pin groups list in DT\n"); 149 dev_err(dev, "Invalid pin groups list in DT\n");
107 goto done; 150 goto done;
151 } else {
152 num_groups = ret;
108 } 153 }
109 154
110 if (!ret) { 155 if (!num_pins && !num_groups) {
111 dev_err(dev, "No group provided in DT node\n"); 156 dev_err(dev, "No pin or group provided in DT node\n");
112 ret = -ENODEV; 157 ret = -ENODEV;
113 goto done; 158 goto done;
114 } 159 }
115 160
116 nmaps += ret; 161 if (function)
162 nmaps += num_groups;
163 if (configs)
164 nmaps += num_pins + num_groups;
117 165
118 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL); 166 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
119 if (maps == NULL) { 167 if (maps == NULL) {
@@ -126,22 +174,59 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
126 174
127 /* Iterate over pins and groups and create the mappings. */ 175 /* Iterate over pins and groups and create the mappings. */
128 of_property_for_each_string(np, "renesas,groups", prop, group) { 176 of_property_for_each_string(np, "renesas,groups", prop, group) {
129 maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; 177 if (function) {
130 maps[idx].data.mux.group = group; 178 maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
131 maps[idx].data.mux.function = function; 179 maps[idx].data.mux.group = group;
132 idx++; 180 maps[idx].data.mux.function = function;
181 idx++;
182 }
183
184 if (configs) {
185 ret = sh_pfc_map_add_config(&maps[idx], group,
186 PIN_MAP_TYPE_CONFIGS_GROUP,
187 configs, num_configs);
188 if (ret < 0)
189 goto done;
190
191 idx++;
192 }
133 } 193 }
134 194
135 ret = 0; 195 if (!configs) {
196 ret = 0;
197 goto done;
198 }
199
200 of_property_for_each_string(np, "renesas,pins", prop, pin) {
201 ret = sh_pfc_map_add_config(&maps[idx], pin,
202 PIN_MAP_TYPE_CONFIGS_PIN,
203 configs, num_configs);
204 if (ret < 0)
205 goto done;
206
207 idx++;
208 }
136 209
137done: 210done:
138 *index = idx; 211 *index = idx;
212 kfree(configs);
139 return ret; 213 return ret;
140} 214}
141 215
142static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev, 216static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
143 struct pinctrl_map *map, unsigned num_maps) 217 struct pinctrl_map *map, unsigned num_maps)
144{ 218{
219 unsigned int i;
220
221 if (map == NULL)
222 return;
223
224 for (i = 0; i < num_maps; ++i) {
225 if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
226 map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
227 kfree(map[i].data.configs.configs);
228 }
229
145 kfree(map); 230 kfree(map);
146} 231}
147 232