sh-pfc: Don't modify pinmux_data_reg SoC data
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / pinctrl / sh-pfc / pinctrl.c
CommitLineData
ca5481c6
PM
1/*
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 */
54407110 10
c6193eac 11#define DRV_NAME "sh-pfc"
f9492fda 12#define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt
ca5481c6 13
1724acfd 14#include <linux/device.h>
90efde22 15#include <linux/err.h>
ca5481c6
PM
16#include <linux/init.h>
17#include <linux/module.h>
ca5481c6 18#include <linux/pinctrl/consumer.h>
ca5481c6 19#include <linux/pinctrl/pinconf.h>
ca5481c6 20#include <linux/pinctrl/pinconf-generic.h>
90efde22
LP
21#include <linux/pinctrl/pinctrl.h>
22#include <linux/pinctrl/pinmux.h>
90efde22
LP
23#include <linux/slab.h>
24#include <linux/spinlock.h>
ca5481c6 25
f9165132
LP
26#include "core.h"
27
ca5481c6
PM
28struct sh_pfc_pinctrl {
29 struct pinctrl_dev *pctl;
dcc427e1 30 struct pinctrl_desc pctl_desc;
dcc427e1 31
ca5481c6
PM
32 struct sh_pfc *pfc;
33
3d8d9f1d 34 struct pinctrl_pin_desc *pins;
ca5481c6
PM
35};
36
e3f805e8 37static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
ca5481c6 38{
e3f805e8
PM
39 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
40
3d8d9f1d 41 return pmx->pfc->info->nr_groups;
ca5481c6
PM
42}
43
e3f805e8 44static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev,
ca5481c6
PM
45 unsigned selector)
46{
e3f805e8
PM
47 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
48
3d8d9f1d 49 return pmx->pfc->info->groups[selector].name;
ca5481c6
PM
50}
51
3d8d9f1d 52static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
ca5481c6
PM
53 const unsigned **pins, unsigned *num_pins)
54{
e3f805e8
PM
55 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
56
3d8d9f1d
LP
57 *pins = pmx->pfc->info->groups[selector].pins;
58 *num_pins = pmx->pfc->info->groups[selector].nr_pins;
e3f805e8
PM
59
60 return 0;
ca5481c6
PM
61}
62
fdd85ec3
PM
63static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
64 unsigned offset)
65{
66 seq_printf(s, "%s", DRV_NAME);
67}
68
fe330ce8 69static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
e3f805e8
PM
70 .get_groups_count = sh_pfc_get_groups_count,
71 .get_group_name = sh_pfc_get_group_name,
ca5481c6 72 .get_group_pins = sh_pfc_get_group_pins,
fdd85ec3 73 .pin_dbg_show = sh_pfc_pin_dbg_show,
ca5481c6
PM
74};
75
d93a891f
PM
76static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
77{
78 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
79
3d8d9f1d 80 return pmx->pfc->info->nr_functions;
d93a891f
PM
81}
82
83static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev,
84 unsigned selector)
85{
86 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
87
3d8d9f1d 88 return pmx->pfc->info->functions[selector].name;
d93a891f 89}
ca5481c6 90
3d8d9f1d
LP
91static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev,
92 unsigned selector,
ca5481c6
PM
93 const char * const **groups,
94 unsigned * const num_groups)
95{
d93a891f
PM
96 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
97
3d8d9f1d
LP
98 *groups = pmx->pfc->info->functions[selector].groups;
99 *num_groups = pmx->pfc->info->functions[selector].nr_groups;
d93a891f 100
ca5481c6
PM
101 return 0;
102}
103
3d8d9f1d 104static int sh_pfc_func_enable(struct pinctrl_dev *pctldev, unsigned selector,
ca5481c6
PM
105 unsigned group)
106{
3d8d9f1d
LP
107 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
108 struct sh_pfc *pfc = pmx->pfc;
109 const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
110 unsigned long flags;
111 unsigned int i;
112 int ret = -EINVAL;
113
114 spin_lock_irqsave(&pfc->lock, flags);
115
116 for (i = 0; i < grp->nr_pins; ++i) {
117 if (sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION,
118 GPIO_CFG_DRYRUN))
119 goto done;
120
121 if (sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION,
122 GPIO_CFG_REQ))
123 goto done;
124 }
125
126 ret = 0;
127
128done:
129 spin_unlock_irqrestore(&pfc->lock, flags);
130 return ret;
ca5481c6
PM
131}
132
3d8d9f1d 133static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector,
ca5481c6
PM
134 unsigned group)
135{
3d8d9f1d
LP
136 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
137 struct sh_pfc *pfc = pmx->pfc;
138 const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
139 unsigned long flags;
140 unsigned int i;
141
142 spin_lock_irqsave(&pfc->lock, flags);
143
144 for (i = 0; i < grp->nr_pins; ++i)
145 sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION,
146 GPIO_CFG_FREE);
147
148 spin_unlock_irqrestore(&pfc->lock, flags);
ca5481c6
PM
149}
150
fdd85ec3
PM
151static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset,
152 int new_type)
153{
934cb02b
LP
154 struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, offset);
155 unsigned int mark = pin->enum_id;
fdd85ec3
PM
156 unsigned long flags;
157 int pinmux_type;
158 int ret = -EINVAL;
159
160 spin_lock_irqsave(&pfc->lock, flags);
161
934cb02b 162 pinmux_type = pin->flags & PINMUX_FLAG_TYPE;
fdd85ec3
PM
163
164 /*
165 * See if the present config needs to first be de-configured.
166 */
167 switch (pinmux_type) {
168 case PINMUX_TYPE_GPIO:
169 break;
170 case PINMUX_TYPE_OUTPUT:
171 case PINMUX_TYPE_INPUT:
172 case PINMUX_TYPE_INPUT_PULLUP:
173 case PINMUX_TYPE_INPUT_PULLDOWN:
a68fdca9 174 sh_pfc_config_mux(pfc, mark, pinmux_type, GPIO_CFG_FREE);
fdd85ec3
PM
175 break;
176 default:
177 goto err;
178 }
179
180 /*
181 * Dry run
182 */
a68fdca9 183 if (sh_pfc_config_mux(pfc, mark, new_type, GPIO_CFG_DRYRUN) != 0)
fdd85ec3
PM
184 goto err;
185
186 /*
187 * Request
188 */
a68fdca9 189 if (sh_pfc_config_mux(pfc, mark, new_type, GPIO_CFG_REQ) != 0)
fdd85ec3
PM
190 goto err;
191
934cb02b
LP
192 pin->flags &= ~PINMUX_FLAG_TYPE;
193 pin->flags |= new_type;
fdd85ec3
PM
194
195 ret = 0;
196
197err:
198 spin_unlock_irqrestore(&pfc->lock, flags);
199
200 return ret;
201}
202
ca5481c6
PM
203static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
204 struct pinctrl_gpio_range *range,
205 unsigned offset)
206{
207 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
208 struct sh_pfc *pfc = pmx->pfc;
934cb02b 209 struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, offset);
ca5481c6 210 unsigned long flags;
d93a891f 211 int ret, pinmux_type;
ca5481c6
PM
212
213 spin_lock_irqsave(&pfc->lock, flags);
214
934cb02b 215 pinmux_type = pin->flags & PINMUX_FLAG_TYPE;
ca5481c6 216
d93a891f 217 switch (pinmux_type) {
d93a891f 218 case PINMUX_TYPE_GPIO:
16d74ebe
PM
219 case PINMUX_TYPE_INPUT:
220 case PINMUX_TYPE_OUTPUT:
d93a891f 221 break;
2119f7c9 222 case PINMUX_TYPE_FUNCTION:
d93a891f
PM
223 default:
224 pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
077664a2
LP
225 ret = -ENOTSUPP;
226 goto err;
d93a891f 227 }
ca5481c6
PM
228
229 ret = 0;
230
231err:
232 spin_unlock_irqrestore(&pfc->lock, flags);
233
234 return ret;
235}
236
237static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev,
238 struct pinctrl_gpio_range *range,
239 unsigned offset)
240{
241 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
242 struct sh_pfc *pfc = pmx->pfc;
934cb02b 243 struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, offset);
ca5481c6
PM
244 unsigned long flags;
245 int pinmux_type;
246
247 spin_lock_irqsave(&pfc->lock, flags);
248
934cb02b 249 pinmux_type = pin->flags & PINMUX_FLAG_TYPE;
ca5481c6 250
934cb02b 251 sh_pfc_config_mux(pfc, pin->enum_id, pinmux_type, GPIO_CFG_FREE);
ca5481c6 252
ca5481c6
PM
253 spin_unlock_irqrestore(&pfc->lock, flags);
254}
255
256static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev,
257 struct pinctrl_gpio_range *range,
258 unsigned offset, bool input)
259{
260 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
fdd85ec3 261 int type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT;
ca5481c6 262
fdd85ec3 263 return sh_pfc_reconfig_pin(pmx->pfc, offset, type);
ca5481c6
PM
264}
265
fe330ce8 266static const struct pinmux_ops sh_pfc_pinmux_ops = {
d93a891f
PM
267 .get_functions_count = sh_pfc_get_functions_count,
268 .get_function_name = sh_pfc_get_function_name,
ca5481c6 269 .get_function_groups = sh_pfc_get_function_groups,
3d8d9f1d
LP
270 .enable = sh_pfc_func_enable,
271 .disable = sh_pfc_func_disable,
ca5481c6
PM
272 .gpio_request_enable = sh_pfc_gpio_request_enable,
273 .gpio_disable_free = sh_pfc_gpio_disable_free,
274 .gpio_set_direction = sh_pfc_gpio_set_direction,
275};
276
934cb02b 277static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
ca5481c6
PM
278 unsigned long *config)
279{
fdd85ec3
PM
280 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
281 struct sh_pfc *pfc = pmx->pfc;
934cb02b 282 struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, _pin);
d93a891f 283
934cb02b 284 *config = pin->flags & PINMUX_FLAG_TYPE;
d93a891f 285
fdd85ec3 286 return 0;
ca5481c6
PM
287}
288
289static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
290 unsigned long config)
291{
fdd85ec3 292 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
fdd85ec3
PM
293
294 /* Validate the new type */
295 if (config >= PINMUX_FLAG_TYPE)
296 return -EINVAL;
297
298 return sh_pfc_reconfig_pin(pmx->pfc, pin, config);
299}
300
301static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev,
302 struct seq_file *s, unsigned pin)
303{
304 const char *pinmux_type_str[] = {
305 [PINMUX_TYPE_NONE] = "none",
306 [PINMUX_TYPE_FUNCTION] = "function",
307 [PINMUX_TYPE_GPIO] = "gpio",
308 [PINMUX_TYPE_OUTPUT] = "output",
309 [PINMUX_TYPE_INPUT] = "input",
310 [PINMUX_TYPE_INPUT_PULLUP] = "input bias pull up",
311 [PINMUX_TYPE_INPUT_PULLDOWN] = "input bias pull down",
312 };
313 unsigned long config;
314 int rc;
315
316 rc = sh_pfc_pinconf_get(pctldev, pin, &config);
317 if (unlikely(rc != 0))
318 return;
319
320 seq_printf(s, " %s", pinmux_type_str[config]);
ca5481c6
PM
321}
322
fe330ce8 323static const struct pinconf_ops sh_pfc_pinconf_ops = {
ca5481c6
PM
324 .pin_config_get = sh_pfc_pinconf_get,
325 .pin_config_set = sh_pfc_pinconf_set,
fdd85ec3 326 .pin_config_dbg_show = sh_pfc_pinconf_dbg_show,
ca5481c6
PM
327};
328
63d57383
LP
329/* PFC ranges -> pinctrl pin descs */
330static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
ca5481c6 331{
63d57383
LP
332 const struct pinmux_range *ranges;
333 struct pinmux_range def_range;
334 unsigned int nr_ranges;
335 unsigned int nr_pins;
336 unsigned int i;
337
338 if (pfc->info->ranges == NULL) {
339 def_range.begin = 0;
340 def_range.end = pfc->info->nr_pins - 1;
341 ranges = &def_range;
342 nr_ranges = 1;
343 } else {
344 ranges = pfc->info->ranges;
345 nr_ranges = pfc->info->nr_ranges;
346 }
ca5481c6 347
3d8d9f1d
LP
348 pmx->pins = devm_kzalloc(pfc->dev,
349 sizeof(*pmx->pins) * pfc->info->nr_pins,
1724acfd 350 GFP_KERNEL);
3d8d9f1d 351 if (unlikely(!pmx->pins))
ca5481c6 352 return -ENOMEM;
ca5481c6 353
63d57383
LP
354 for (i = 0, nr_pins = 0; i < nr_ranges; ++i) {
355 const struct pinmux_range *range = &ranges[i];
356 unsigned int number;
357
358 for (number = range->begin; number <= range->end;
359 number++, nr_pins++) {
3d8d9f1d 360 struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins];
63d57383 361 struct sh_pfc_pin *info = &pfc->info->pins[nr_pins];
ca5481c6 362
63d57383
LP
363 pin->number = number;
364 pin->name = info->name;
365 }
ca5481c6
PM
366 }
367
63d57383
LP
368 pfc->nr_pins = ranges[nr_ranges-1].end + 1;
369
370 return nr_ranges;
ca5481c6
PM
371}
372
c6193eac 373int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
ca5481c6 374{
c6193eac 375 struct sh_pfc_pinctrl *pmx;
63d57383 376 int nr_ranges;
ca5481c6 377
1724acfd 378 pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL);
c6193eac
LP
379 if (unlikely(!pmx))
380 return -ENOMEM;
381
c6193eac
LP
382 pmx->pfc = pfc;
383 pfc->pinctrl = pmx;
ca5481c6 384
63d57383
LP
385 nr_ranges = sh_pfc_map_pins(pfc, pmx);
386 if (unlikely(nr_ranges < 0))
387 return nr_ranges;
ca5481c6 388
dcc427e1
LP
389 pmx->pctl_desc.name = DRV_NAME;
390 pmx->pctl_desc.owner = THIS_MODULE;
391 pmx->pctl_desc.pctlops = &sh_pfc_pinctrl_ops;
392 pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops;
393 pmx->pctl_desc.confops = &sh_pfc_pinconf_ops;
3d8d9f1d 394 pmx->pctl_desc.pins = pmx->pins;
63d57383 395 pmx->pctl_desc.npins = pfc->info->nr_pins;
dcc427e1
LP
396
397 pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx);
fd9d05b0
WY
398 if (pmx->pctl == NULL)
399 return -EINVAL;
ca5481c6 400
ca5481c6 401 return 0;
ca5481c6
PM
402}
403
c6193eac 404int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc)
ca5481c6 405{
c6193eac 406 struct sh_pfc_pinctrl *pmx = pfc->pinctrl;
ca5481c6 407
ca5481c6
PM
408 pinctrl_unregister(pmx->pctl);
409
c6193eac 410 pfc->pinctrl = NULL;
ca5481c6
PM
411 return 0;
412}