diff options
-rw-r--r-- | Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt | 36 | ||||
-rw-r--r-- | drivers/pinctrl/sh-pfc/pinctrl.c | 109 |
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 | |||
30 | to pinctrl-bindings.txt in this directory for the definition of the term "pin | 30 | to pinctrl-bindings.txt in this directory for the definition of the term "pin |
31 | configuration node" and for the common pinctrl bindings used by client devices. | 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 | 33 | Each pin configuration node represents a desired configuration for a pin, a |
34 | group or a list of pin groups. The functions and pin groups can be specified | 34 | pin group, or a list of pins or pin groups. The configuration can include the |
35 | directly in the pin configuration node, or grouped in child subnodes. Several | 35 | function to select on those pin(s) and pin configuration parameters (such as |
36 | functions can thus be referenced as a single pin configuration node by client | 36 | pull-up and pull-down). |
37 | devices. | ||
38 | 37 | ||
39 | A configuration node or subnode must contain a function and reference at least | 38 | Pin configuration nodes contain pin configuration properties, either directly |
40 | one pin group. | 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 | All pin configuration nodes and subnodes names are ignored. All of those nodes | 48 | All pin configuration nodes and subnodes names are ignored. All of those nodes |
43 | are parsed through phandles and processed purely based on their content. | 49 | are parsed through phandles and processed purely based on their content. |
44 | 50 | ||
45 | Pin Configuration Node Properties: | 51 | Pin 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 | ||
64 | The pin configuration parameters use the generic pinconf bindings defined in | ||
65 | pinctrl-bindings.txt in this directory. The supported parameters are | ||
66 | bias-disable, bias-pull-up and bias-pull-down. | ||
67 | |||
57 | 68 | ||
58 | GPIO | 69 | GPIO |
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 | ||
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 | static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, | 98 | static 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 | ||
137 | done: | 210 | done: |
138 | *index = idx; | 211 | *index = idx; |
212 | kfree(configs); | ||
139 | return ret; | 213 | return ret; |
140 | } | 214 | } |
141 | 215 | ||
142 | static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev, | 216 | static 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 | ||