blob: 7e32bb8c08dd4c835707eabdfd7e1db2d6df31d8 [file] [log] [blame]
Paul Mundtca5481c62012-07-10 12:08:14 +09001/*
2 * SuperH Pin Function Controller pinmux support.
3 *
4 * Copyright (C) 2012 Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
Paul Mundt54407112012-07-20 16:18:21 +090010
Laurent Pinchartc6193ea2012-12-15 23:50:47 +010011#define DRV_NAME "sh-pfc"
Paul Mundtca5481c62012-07-10 12:08:14 +090012
Laurent Pinchart1724acf2012-12-15 23:50:48 +010013#include <linux/device.h>
Laurent Pinchart90efde22012-12-15 23:50:52 +010014#include <linux/err.h>
Paul Mundtca5481c62012-07-10 12:08:14 +090015#include <linux/init.h>
16#include <linux/module.h>
Laurent Pinchartfe1c9a82013-06-17 20:50:02 +020017#include <linux/of.h>
Laurent Pinchart90efde22012-12-15 23:50:52 +010018#include <linux/pinctrl/consumer.h>
Laurent Pinchartfe1c9a82013-06-17 20:50:02 +020019#include <linux/pinctrl/machine.h>
Laurent Pinchart90efde22012-12-15 23:50:52 +010020#include <linux/pinctrl/pinconf.h>
21#include <linux/pinctrl/pinconf-generic.h>
22#include <linux/pinctrl/pinctrl.h>
23#include <linux/pinctrl/pinmux.h>
Paul Mundtca5481c62012-07-10 12:08:14 +090024#include <linux/slab.h>
Paul Mundtd93a8912012-07-11 17:17:10 +090025#include <linux/spinlock.h>
Paul Mundtca5481c62012-07-10 12:08:14 +090026
Laurent Pinchartf9165132012-12-15 23:50:44 +010027#include "core.h"
Laurent Pinchartc58d9c12013-03-10 16:44:02 +010028#include "../core.h"
29#include "../pinconf.h"
Laurent Pinchartf9165132012-12-15 23:50:44 +010030
Laurent Pinchart1a0039d2013-03-08 17:43:54 +010031struct sh_pfc_pin_config {
32 u32 type;
33};
34
Paul Mundtca5481c62012-07-10 12:08:14 +090035struct sh_pfc_pinctrl {
36 struct pinctrl_dev *pctl;
Laurent Pinchartdcc427e2013-02-16 16:38:30 +010037 struct pinctrl_desc pctl_desc;
Laurent Pinchartdcc427e2013-02-16 16:38:30 +010038
Paul Mundtca5481c62012-07-10 12:08:14 +090039 struct sh_pfc *pfc;
40
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +010041 struct pinctrl_pin_desc *pins;
Laurent Pinchart1a0039d2013-03-08 17:43:54 +010042 struct sh_pfc_pin_config *configs;
Paul Mundtca5481c62012-07-10 12:08:14 +090043};
44
Paul Mundte3f805e2012-07-17 15:48:18 +090045static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
Paul Mundtca5481c62012-07-10 12:08:14 +090046{
Paul Mundte3f805e2012-07-17 15:48:18 +090047 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
48
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +010049 return pmx->pfc->info->nr_groups;
Paul Mundtca5481c62012-07-10 12:08:14 +090050}
51
Paul Mundte3f805e2012-07-17 15:48:18 +090052static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev,
Paul Mundtca5481c62012-07-10 12:08:14 +090053 unsigned selector)
54{
Paul Mundte3f805e2012-07-17 15:48:18 +090055 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
56
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +010057 return pmx->pfc->info->groups[selector].name;
Paul Mundtca5481c62012-07-10 12:08:14 +090058}
59
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +010060static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
Paul Mundtca5481c62012-07-10 12:08:14 +090061 const unsigned **pins, unsigned *num_pins)
62{
Paul Mundte3f805e2012-07-17 15:48:18 +090063 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
64
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +010065 *pins = pmx->pfc->info->groups[selector].pins;
66 *num_pins = pmx->pfc->info->groups[selector].nr_pins;
Paul Mundte3f805e2012-07-17 15:48:18 +090067
68 return 0;
Paul Mundtca5481c62012-07-10 12:08:14 +090069}
70
Paul Mundtfdd85ec2012-07-20 16:39:09 +090071static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
72 unsigned offset)
73{
74 seq_printf(s, "%s", DRV_NAME);
75}
76
Laurent Pinchartfe1c9a82013-06-17 20:50:02 +020077static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
78 struct pinctrl_map **map,
79 unsigned int *num_maps, unsigned int *index)
80{
81 struct pinctrl_map *maps = *map;
82 unsigned int nmaps = *num_maps;
83 unsigned int idx = *index;
84 const char *function = NULL;
85 struct property *prop;
86 const char *group;
87 int ret;
88
89 /* Parse the function and configuration properties. At least a function
90 * or one configuration must be specified.
91 */
92 ret = of_property_read_string(np, "renesas,function", &function);
93 if (ret < 0 && ret != -EINVAL) {
94 dev_err(dev, "Invalid function in DT\n");
95 return ret;
96 }
97
98 if (!function) {
99 dev_err(dev, "DT node must contain at least one function\n");
100 goto done;
101 }
102
103 /* Count the number of groups and reallocate mappings. */
104 ret = of_property_count_strings(np, "renesas,groups");
105 if (ret < 0 && ret != -EINVAL) {
106 dev_err(dev, "Invalid pin groups list in DT\n");
107 goto done;
108 }
109
110 if (!ret) {
111 dev_err(dev, "No group provided in DT node\n");
112 ret = -ENODEV;
113 goto done;
114 }
115
116 nmaps += ret;
117
118 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
119 if (maps == NULL) {
120 ret = -ENOMEM;
121 goto done;
122 }
123
124 *map = maps;
125 *num_maps = nmaps;
126
127 /* Iterate over pins and groups and create the mappings. */
128 of_property_for_each_string(np, "renesas,groups", prop, group) {
129 maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
130 maps[idx].data.mux.group = group;
131 maps[idx].data.mux.function = function;
132 idx++;
133 }
134
135 ret = 0;
136
137done:
138 *index = idx;
139 return ret;
140}
141
142static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
143 struct pinctrl_map *map, unsigned num_maps)
144{
145 kfree(map);
146}
147
148static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
149 struct device_node *np,
150 struct pinctrl_map **map, unsigned *num_maps)
151{
152 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
153 struct device *dev = pmx->pfc->dev;
154 struct device_node *child;
155 unsigned int index;
156 int ret;
157
158 *map = NULL;
159 *num_maps = 0;
160 index = 0;
161
162 for_each_child_of_node(np, child) {
163 ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps,
164 &index);
165 if (ret < 0)
166 goto done;
167 }
168
169 /* If no mapping has been found in child nodes try the config node. */
170 if (*num_maps == 0) {
171 ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index);
172 if (ret < 0)
173 goto done;
174 }
175
176 if (*num_maps)
177 return 0;
178
179 dev_err(dev, "no mapping found in node %s\n", np->full_name);
180 ret = -EINVAL;
181
182done:
183 if (ret < 0)
184 sh_pfc_dt_free_map(pctldev, *map, *num_maps);
185
186 return ret;
187}
188
Laurent Pinchartfe330ce2013-02-15 16:04:47 +0100189static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
Paul Mundte3f805e2012-07-17 15:48:18 +0900190 .get_groups_count = sh_pfc_get_groups_count,
191 .get_group_name = sh_pfc_get_group_name,
Paul Mundtca5481c62012-07-10 12:08:14 +0900192 .get_group_pins = sh_pfc_get_group_pins,
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900193 .pin_dbg_show = sh_pfc_pin_dbg_show,
Laurent Pinchartfe1c9a82013-06-17 20:50:02 +0200194 .dt_node_to_map = sh_pfc_dt_node_to_map,
195 .dt_free_map = sh_pfc_dt_free_map,
Paul Mundtca5481c62012-07-10 12:08:14 +0900196};
197
Paul Mundtd93a8912012-07-11 17:17:10 +0900198static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
199{
200 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
Paul Mundtca5481c62012-07-10 12:08:14 +0900201
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100202 return pmx->pfc->info->nr_functions;
Paul Mundtd93a8912012-07-11 17:17:10 +0900203}
204
205static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev,
206 unsigned selector)
207{
208 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
209
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100210 return pmx->pfc->info->functions[selector].name;
Paul Mundtd93a8912012-07-11 17:17:10 +0900211}
212
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100213static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev,
214 unsigned selector,
Paul Mundtca5481c62012-07-10 12:08:14 +0900215 const char * const **groups,
216 unsigned * const num_groups)
217{
Paul Mundtd93a8912012-07-11 17:17:10 +0900218 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
219
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100220 *groups = pmx->pfc->info->functions[selector].groups;
221 *num_groups = pmx->pfc->info->functions[selector].nr_groups;
Paul Mundtd93a8912012-07-11 17:17:10 +0900222
Paul Mundtca5481c62012-07-10 12:08:14 +0900223 return 0;
224}
225
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100226static int sh_pfc_func_enable(struct pinctrl_dev *pctldev, unsigned selector,
Paul Mundtca5481c62012-07-10 12:08:14 +0900227 unsigned group)
228{
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100229 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
230 struct sh_pfc *pfc = pmx->pfc;
231 const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
232 unsigned long flags;
233 unsigned int i;
Laurent Pinchartb705c052013-03-10 16:38:23 +0100234 int ret = 0;
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100235
236 spin_lock_irqsave(&pfc->lock, flags);
237
238 for (i = 0; i < grp->nr_pins; ++i) {
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100239 int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
240 struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
241
242 if (cfg->type != PINMUX_TYPE_NONE) {
243 ret = -EBUSY;
244 goto done;
245 }
246 }
247
248 for (i = 0; i < grp->nr_pins; ++i) {
Laurent Pinchartb705c052013-03-10 16:38:23 +0100249 ret = sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION);
250 if (ret < 0)
251 break;
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100252 }
253
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100254done:
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100255 spin_unlock_irqrestore(&pfc->lock, flags);
256 return ret;
Paul Mundtca5481c62012-07-10 12:08:14 +0900257}
258
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100259static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector,
Paul Mundtca5481c62012-07-10 12:08:14 +0900260 unsigned group)
261{
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100262 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
263 struct sh_pfc *pfc = pmx->pfc;
264 const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
265 unsigned long flags;
266 unsigned int i;
267
268 spin_lock_irqsave(&pfc->lock, flags);
269
270 for (i = 0; i < grp->nr_pins; ++i) {
271 int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
272 struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
273
274 cfg->type = PINMUX_TYPE_NONE;
275 }
276
277 spin_unlock_irqrestore(&pfc->lock, flags);
Paul Mundtca5481c62012-07-10 12:08:14 +0900278}
279
280static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
281 struct pinctrl_gpio_range *range,
282 unsigned offset)
283{
284 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
285 struct sh_pfc *pfc = pmx->pfc;
Laurent Pinchart1a0039d2013-03-08 17:43:54 +0100286 int idx = sh_pfc_get_pin_index(pfc, offset);
287 struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
Paul Mundtca5481c62012-07-10 12:08:14 +0900288 unsigned long flags;
Laurent Pinchart1a0039d2013-03-08 17:43:54 +0100289 int ret;
Paul Mundtca5481c62012-07-10 12:08:14 +0900290
291 spin_lock_irqsave(&pfc->lock, flags);
292
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100293 if (cfg->type != PINMUX_TYPE_NONE) {
Laurent Pinchart9a643c92013-03-10 18:00:02 +0100294 dev_err(pfc->dev,
295 "Pin %u is busy, can't configure it as GPIO.\n",
296 offset);
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100297 ret = -EBUSY;
298 goto done;
Paul Mundtd93a8912012-07-11 17:17:10 +0900299 }
Paul Mundtca5481c62012-07-10 12:08:14 +0900300
Laurent Pincharte3c470512013-03-10 17:30:25 +0100301 if (!pfc->gpio) {
302 /* If GPIOs are handled externally the pin mux type need to be
303 * set to GPIO here.
304 */
305 const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
306
307 ret = sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
308 if (ret < 0)
309 goto done;
310 }
311
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100312 cfg->type = PINMUX_TYPE_GPIO;
313
Paul Mundtca5481c62012-07-10 12:08:14 +0900314 ret = 0;
315
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100316done:
Paul Mundtca5481c62012-07-10 12:08:14 +0900317 spin_unlock_irqrestore(&pfc->lock, flags);
318
319 return ret;
320}
321
322static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev,
323 struct pinctrl_gpio_range *range,
324 unsigned offset)
325{
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100326 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
327 struct sh_pfc *pfc = pmx->pfc;
328 int idx = sh_pfc_get_pin_index(pfc, offset);
329 struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
330 unsigned long flags;
331
332 spin_lock_irqsave(&pfc->lock, flags);
333 cfg->type = PINMUX_TYPE_NONE;
334 spin_unlock_irqrestore(&pfc->lock, flags);
Paul Mundtca5481c62012-07-10 12:08:14 +0900335}
336
337static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev,
338 struct pinctrl_gpio_range *range,
339 unsigned offset, bool input)
340{
341 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100342 struct sh_pfc *pfc = pmx->pfc;
343 int new_type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT;
344 int idx = sh_pfc_get_pin_index(pfc, offset);
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100345 const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100346 struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100347 unsigned long flags;
Laurent Pinchart6dc9b452013-03-13 18:18:30 +0100348 unsigned int dir;
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100349 int ret;
Paul Mundtca5481c62012-07-10 12:08:14 +0900350
Laurent Pinchart6dc9b452013-03-13 18:18:30 +0100351 /* Check if the requested direction is supported by the pin. Not all SoC
352 * provide pin config data, so perform the check conditionally.
353 */
354 if (pin->configs) {
355 dir = input ? SH_PFC_PIN_CFG_INPUT : SH_PFC_PIN_CFG_OUTPUT;
356 if (!(pin->configs & dir))
357 return -EINVAL;
358 }
359
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100360 spin_lock_irqsave(&pfc->lock, flags);
361
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100362 ret = sh_pfc_config_mux(pfc, pin->enum_id, new_type);
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100363 if (ret < 0)
364 goto done;
365
366 cfg->type = new_type;
367
368done:
369 spin_unlock_irqrestore(&pfc->lock, flags);
Laurent Pinchart0d00f002013-03-10 16:55:19 +0100370 return ret;
Paul Mundtca5481c62012-07-10 12:08:14 +0900371}
372
Laurent Pinchartfe330ce2013-02-15 16:04:47 +0100373static const struct pinmux_ops sh_pfc_pinmux_ops = {
Paul Mundtd93a8912012-07-11 17:17:10 +0900374 .get_functions_count = sh_pfc_get_functions_count,
375 .get_function_name = sh_pfc_get_function_name,
Paul Mundtca5481c62012-07-10 12:08:14 +0900376 .get_function_groups = sh_pfc_get_function_groups,
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100377 .enable = sh_pfc_func_enable,
378 .disable = sh_pfc_func_disable,
Paul Mundtca5481c62012-07-10 12:08:14 +0900379 .gpio_request_enable = sh_pfc_gpio_request_enable,
380 .gpio_disable_free = sh_pfc_gpio_disable_free,
381 .gpio_set_direction = sh_pfc_gpio_set_direction,
382};
383
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100384/* Check whether the requested parameter is supported for a pin. */
385static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
386 enum pin_config_param param)
387{
388 int idx = sh_pfc_get_pin_index(pfc, _pin);
389 const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
390
391 switch (param) {
392 case PIN_CONFIG_BIAS_DISABLE:
393 return true;
394
395 case PIN_CONFIG_BIAS_PULL_UP:
396 return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
397
398 case PIN_CONFIG_BIAS_PULL_DOWN:
399 return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
400
401 default:
402 return false;
403 }
404}
405
Laurent Pinchart934cb022013-02-14 22:35:09 +0100406static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
Paul Mundtca5481c62012-07-10 12:08:14 +0900407 unsigned long *config)
408{
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900409 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
410 struct sh_pfc *pfc = pmx->pfc;
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100411 enum pin_config_param param = pinconf_to_config_param(*config);
412 unsigned long flags;
413 unsigned int bias;
Paul Mundtd93a8912012-07-11 17:17:10 +0900414
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100415 if (!sh_pfc_pinconf_validate(pfc, _pin, param))
416 return -ENOTSUPP;
417
418 switch (param) {
419 case PIN_CONFIG_BIAS_DISABLE:
420 case PIN_CONFIG_BIAS_PULL_UP:
421 case PIN_CONFIG_BIAS_PULL_DOWN:
422 if (!pfc->info->ops || !pfc->info->ops->get_bias)
423 return -ENOTSUPP;
424
425 spin_lock_irqsave(&pfc->lock, flags);
426 bias = pfc->info->ops->get_bias(pfc, _pin);
427 spin_unlock_irqrestore(&pfc->lock, flags);
428
429 if (bias != param)
430 return -EINVAL;
431
432 *config = 0;
433 break;
434
435 default:
436 return -ENOTSUPP;
437 }
Paul Mundtd93a8912012-07-11 17:17:10 +0900438
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900439 return 0;
Paul Mundtca5481c62012-07-10 12:08:14 +0900440}
441
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100442static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
Paul Mundtca5481c62012-07-10 12:08:14 +0900443 unsigned long config)
444{
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900445 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100446 struct sh_pfc *pfc = pmx->pfc;
447 enum pin_config_param param = pinconf_to_config_param(config);
448 unsigned long flags;
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900449
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100450 if (!sh_pfc_pinconf_validate(pfc, _pin, param))
451 return -ENOTSUPP;
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900452
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100453 switch (param) {
454 case PIN_CONFIG_BIAS_PULL_UP:
455 case PIN_CONFIG_BIAS_PULL_DOWN:
456 case PIN_CONFIG_BIAS_DISABLE:
457 if (!pfc->info->ops || !pfc->info->ops->set_bias)
458 return -ENOTSUPP;
459
460 spin_lock_irqsave(&pfc->lock, flags);
461 pfc->info->ops->set_bias(pfc, _pin, param);
462 spin_unlock_irqrestore(&pfc->lock, flags);
463
464 break;
465
466 default:
467 return -ENOTSUPP;
468 }
469
470 return 0;
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900471}
472
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100473static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
474 unsigned long config)
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900475{
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100476 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
477 const unsigned int *pins;
478 unsigned int num_pins;
479 unsigned int i;
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900480
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100481 pins = pmx->pfc->info->groups[group].pins;
482 num_pins = pmx->pfc->info->groups[group].nr_pins;
Paul Mundtfdd85ec2012-07-20 16:39:09 +0900483
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100484 for (i = 0; i < num_pins; ++i)
485 sh_pfc_pinconf_set(pctldev, pins[i], config);
486
487 return 0;
Paul Mundtca5481c62012-07-10 12:08:14 +0900488}
489
Laurent Pinchartfe330ce2013-02-15 16:04:47 +0100490static const struct pinconf_ops sh_pfc_pinconf_ops = {
Laurent Pinchartc58d9c12013-03-10 16:44:02 +0100491 .is_generic = true,
492 .pin_config_get = sh_pfc_pinconf_get,
493 .pin_config_set = sh_pfc_pinconf_set,
494 .pin_config_group_set = sh_pfc_pinconf_group_set,
495 .pin_config_config_dbg_show = pinconf_generic_dump_config,
Paul Mundtca5481c62012-07-10 12:08:14 +0900496};
497
Laurent Pinchart63d57382013-02-15 01:33:38 +0100498/* PFC ranges -> pinctrl pin descs */
499static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
Paul Mundtca5481c62012-07-10 12:08:14 +0900500{
Laurent Pinchart63d57382013-02-15 01:33:38 +0100501 const struct pinmux_range *ranges;
502 struct pinmux_range def_range;
503 unsigned int nr_ranges;
504 unsigned int nr_pins;
505 unsigned int i;
Paul Mundtca5481c62012-07-10 12:08:14 +0900506
Laurent Pinchart63d57382013-02-15 01:33:38 +0100507 if (pfc->info->ranges == NULL) {
508 def_range.begin = 0;
509 def_range.end = pfc->info->nr_pins - 1;
510 ranges = &def_range;
511 nr_ranges = 1;
512 } else {
513 ranges = pfc->info->ranges;
514 nr_ranges = pfc->info->nr_ranges;
515 }
Paul Mundtca5481c62012-07-10 12:08:14 +0900516
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100517 pmx->pins = devm_kzalloc(pfc->dev,
518 sizeof(*pmx->pins) * pfc->info->nr_pins,
Laurent Pinchart1724acf2012-12-15 23:50:48 +0100519 GFP_KERNEL);
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100520 if (unlikely(!pmx->pins))
Paul Mundtca5481c62012-07-10 12:08:14 +0900521 return -ENOMEM;
Laurent Pinchart63d57382013-02-15 01:33:38 +0100522
Laurent Pinchart1a0039d2013-03-08 17:43:54 +0100523 pmx->configs = devm_kzalloc(pfc->dev,
524 sizeof(*pmx->configs) * pfc->info->nr_pins,
525 GFP_KERNEL);
526 if (unlikely(!pmx->configs))
527 return -ENOMEM;
528
Laurent Pinchart63d57382013-02-15 01:33:38 +0100529 for (i = 0, nr_pins = 0; i < nr_ranges; ++i) {
530 const struct pinmux_range *range = &ranges[i];
531 unsigned int number;
532
533 for (number = range->begin; number <= range->end;
534 number++, nr_pins++) {
Laurent Pinchart1a0039d2013-03-08 17:43:54 +0100535 struct sh_pfc_pin_config *cfg = &pmx->configs[nr_pins];
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100536 struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins];
Laurent Pinchartcd3c1be2013-02-16 18:47:05 +0100537 const struct sh_pfc_pin *info =
538 &pfc->info->pins[nr_pins];
Laurent Pinchart63d57382013-02-15 01:33:38 +0100539
540 pin->number = number;
541 pin->name = info->name;
Laurent Pinchart9fddc4a2013-03-10 17:25:29 +0100542 cfg->type = PINMUX_TYPE_NONE;
Laurent Pinchart63d57382013-02-15 01:33:38 +0100543 }
Paul Mundtca5481c62012-07-10 12:08:14 +0900544 }
545
Laurent Pinchart63d57382013-02-15 01:33:38 +0100546 pfc->nr_pins = ranges[nr_ranges-1].end + 1;
Paul Mundtca5481c62012-07-10 12:08:14 +0900547
Laurent Pinchart63d57382013-02-15 01:33:38 +0100548 return nr_ranges;
Paul Mundtca5481c62012-07-10 12:08:14 +0900549}
550
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100551int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
Paul Mundtca5481c62012-07-10 12:08:14 +0900552{
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100553 struct sh_pfc_pinctrl *pmx;
Laurent Pinchart63d57382013-02-15 01:33:38 +0100554 int nr_ranges;
Paul Mundtca5481c62012-07-10 12:08:14 +0900555
Laurent Pinchart1724acf2012-12-15 23:50:48 +0100556 pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL);
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100557 if (unlikely(!pmx))
558 return -ENOMEM;
Paul Mundtca5481c62012-07-10 12:08:14 +0900559
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100560 pmx->pfc = pfc;
561 pfc->pinctrl = pmx;
562
Laurent Pinchart63d57382013-02-15 01:33:38 +0100563 nr_ranges = sh_pfc_map_pins(pfc, pmx);
564 if (unlikely(nr_ranges < 0))
565 return nr_ranges;
Paul Mundtca5481c62012-07-10 12:08:14 +0900566
Laurent Pinchartdcc427e2013-02-16 16:38:30 +0100567 pmx->pctl_desc.name = DRV_NAME;
568 pmx->pctl_desc.owner = THIS_MODULE;
569 pmx->pctl_desc.pctlops = &sh_pfc_pinctrl_ops;
570 pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops;
571 pmx->pctl_desc.confops = &sh_pfc_pinconf_ops;
Laurent Pinchart3d8d9f12013-01-03 14:33:13 +0100572 pmx->pctl_desc.pins = pmx->pins;
Laurent Pinchart63d57382013-02-15 01:33:38 +0100573 pmx->pctl_desc.npins = pfc->info->nr_pins;
Laurent Pinchartdcc427e2013-02-16 16:38:30 +0100574
575 pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx);
Wei Yongjunfd9d05b2013-03-11 22:08:12 +0800576 if (pmx->pctl == NULL)
577 return -EINVAL;
Paul Mundtca5481c62012-07-10 12:08:14 +0900578
Paul Mundtca5481c62012-07-10 12:08:14 +0900579 return 0;
Paul Mundtca5481c62012-07-10 12:08:14 +0900580}
581
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100582int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc)
Paul Mundtca5481c62012-07-10 12:08:14 +0900583{
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100584 struct sh_pfc_pinctrl *pmx = pfc->pinctrl;
Paul Mundtca5481c62012-07-10 12:08:14 +0900585
Paul Mundtca5481c62012-07-10 12:08:14 +0900586 pinctrl_unregister(pmx->pctl);
587
Laurent Pinchartc6193ea2012-12-15 23:50:47 +0100588 pfc->pinctrl = NULL;
Paul Mundtca5481c62012-07-10 12:08:14 +0900589 return 0;
590}