aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-03-10 11:44:02 -0400
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-03-15 08:33:54 -0400
commitc58d9c1b26e3ab2933abc7d5444e945ddad44809 (patch)
treee751a0f696141d30aac72ba518d9c0a1db309845 /drivers
parentb705c054255ae3264aa02d46347e9cfbcf26523a (diff)
sh-pfc: Implement generic pinconf support
The existing PFC pinconf implementation, tied to the PFC-specific pin types, isn't used by drivers or boards. Replace it with the generic pinconf types to implement bias (pull-up/down) setup. Other pin configuration options can be implemented later if needed. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pinctrl/sh-pfc/Kconfig1
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c123
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h16
3 files changed, 110 insertions, 30 deletions
diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
index c3340f54d2ad..af16f8f6ab6c 100644
--- a/drivers/pinctrl/sh-pfc/Kconfig
+++ b/drivers/pinctrl/sh-pfc/Kconfig
@@ -10,6 +10,7 @@ config PINCTRL_SH_PFC
10 select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB 10 select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
11 select PINMUX 11 select PINMUX
12 select PINCONF 12 select PINCONF
13 select GENERIC_PINCONF
13 def_bool y 14 def_bool y
14 help 15 help
15 This enables pin control drivers for SH and SH Mobile platforms 16 This enables pin control drivers for SH and SH Mobile platforms
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index c15091096f65..79fa170b4872 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -24,6 +24,8 @@
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25 25
26#include "core.h" 26#include "core.h"
27#include "../core.h"
28#include "../pinconf.h"
27 29
28struct sh_pfc_pin_config { 30struct sh_pfc_pin_config {
29 u32 type; 31 u32 type;
@@ -230,57 +232,118 @@ static const struct pinmux_ops sh_pfc_pinmux_ops = {
230 .gpio_set_direction = sh_pfc_gpio_set_direction, 232 .gpio_set_direction = sh_pfc_gpio_set_direction,
231}; 233};
232 234
235/* Check whether the requested parameter is supported for a pin. */
236static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
237 enum pin_config_param param)
238{
239 int idx = sh_pfc_get_pin_index(pfc, _pin);
240 const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
241
242 switch (param) {
243 case PIN_CONFIG_BIAS_DISABLE:
244 return true;
245
246 case PIN_CONFIG_BIAS_PULL_UP:
247 return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
248
249 case PIN_CONFIG_BIAS_PULL_DOWN:
250 return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
251
252 default:
253 return false;
254 }
255}
256
233static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, 257static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
234 unsigned long *config) 258 unsigned long *config)
235{ 259{
236 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); 260 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
237 struct sh_pfc *pfc = pmx->pfc; 261 struct sh_pfc *pfc = pmx->pfc;
238 int idx = sh_pfc_get_pin_index(pfc, _pin); 262 enum pin_config_param param = pinconf_to_config_param(*config);
239 struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; 263 unsigned long flags;
264 unsigned int bias;
265
266 if (!sh_pfc_pinconf_validate(pfc, _pin, param))
267 return -ENOTSUPP;
240 268
241 *config = cfg->type; 269 switch (param) {
270 case PIN_CONFIG_BIAS_DISABLE:
271 case PIN_CONFIG_BIAS_PULL_UP:
272 case PIN_CONFIG_BIAS_PULL_DOWN:
273 if (!pfc->info->ops || !pfc->info->ops->get_bias)
274 return -ENOTSUPP;
275
276 spin_lock_irqsave(&pfc->lock, flags);
277 bias = pfc->info->ops->get_bias(pfc, _pin);
278 spin_unlock_irqrestore(&pfc->lock, flags);
279
280 if (bias != param)
281 return -EINVAL;
282
283 *config = 0;
284 break;
285
286 default:
287 return -ENOTSUPP;
288 }
242 289
243 return 0; 290 return 0;
244} 291}
245 292
246static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, 293static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
247 unsigned long config) 294 unsigned long config)
248{ 295{
249 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); 296 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
297 struct sh_pfc *pfc = pmx->pfc;
298 enum pin_config_param param = pinconf_to_config_param(config);
299 unsigned long flags;
250 300
251 /* Validate the new type */ 301 if (!sh_pfc_pinconf_validate(pfc, _pin, param))
252 if (config >= PINMUX_FLAG_TYPE) 302 return -ENOTSUPP;
253 return -EINVAL;
254 303
255 return sh_pfc_reconfig_pin(pmx, pin, config); 304 switch (param) {
305 case PIN_CONFIG_BIAS_PULL_UP:
306 case PIN_CONFIG_BIAS_PULL_DOWN:
307 case PIN_CONFIG_BIAS_DISABLE:
308 if (!pfc->info->ops || !pfc->info->ops->set_bias)
309 return -ENOTSUPP;
310
311 spin_lock_irqsave(&pfc->lock, flags);
312 pfc->info->ops->set_bias(pfc, _pin, param);
313 spin_unlock_irqrestore(&pfc->lock, flags);
314
315 break;
316
317 default:
318 return -ENOTSUPP;
319 }
320
321 return 0;
256} 322}
257 323
258static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev, 324static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
259 struct seq_file *s, unsigned pin) 325 unsigned long config)
260{ 326{
261 const char *pinmux_type_str[] = { 327 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
262 [PINMUX_TYPE_NONE] = "none", 328 const unsigned int *pins;
263 [PINMUX_TYPE_FUNCTION] = "function", 329 unsigned int num_pins;
264 [PINMUX_TYPE_GPIO] = "gpio", 330 unsigned int i;
265 [PINMUX_TYPE_OUTPUT] = "output", 331
266 [PINMUX_TYPE_INPUT] = "input", 332 pins = pmx->pfc->info->groups[group].pins;
267 [PINMUX_TYPE_INPUT_PULLUP] = "input bias pull up", 333 num_pins = pmx->pfc->info->groups[group].nr_pins;
268 [PINMUX_TYPE_INPUT_PULLDOWN] = "input bias pull down", 334
269 }; 335 for (i = 0; i < num_pins; ++i)
270 unsigned long config; 336 sh_pfc_pinconf_set(pctldev, pins[i], config);
271 int rc; 337
272 338 return 0;
273 rc = sh_pfc_pinconf_get(pctldev, pin, &config);
274 if (unlikely(rc != 0))
275 return;
276
277 seq_printf(s, " %s", pinmux_type_str[config]);
278} 339}
279 340
280static const struct pinconf_ops sh_pfc_pinconf_ops = { 341static const struct pinconf_ops sh_pfc_pinconf_ops = {
281 .pin_config_get = sh_pfc_pinconf_get, 342 .is_generic = true,
282 .pin_config_set = sh_pfc_pinconf_set, 343 .pin_config_get = sh_pfc_pinconf_get,
283 .pin_config_dbg_show = sh_pfc_pinconf_dbg_show, 344 .pin_config_set = sh_pfc_pinconf_set,
345 .pin_config_group_set = sh_pfc_pinconf_group_set,
346 .pin_config_config_dbg_show = pinconf_generic_dump_config,
284}; 347};
285 348
286/* PFC ranges -> pinctrl pin descs */ 349/* PFC ranges -> pinctrl pin descs */
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index b250dacaf8dd..3b785fc428d5 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -31,9 +31,15 @@ enum {
31 PINMUX_FLAG_TYPE, /* must be last */ 31 PINMUX_FLAG_TYPE, /* must be last */
32}; 32};
33 33
34#define SH_PFC_PIN_CFG_INPUT (1 << 0)
35#define SH_PFC_PIN_CFG_OUTPUT (1 << 1)
36#define SH_PFC_PIN_CFG_PULL_UP (1 << 2)
37#define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3)
38
34struct sh_pfc_pin { 39struct sh_pfc_pin {
35 const pinmux_enum_t enum_id; 40 const pinmux_enum_t enum_id;
36 const char *name; 41 const char *name;
42 unsigned int configs;
37}; 43};
38 44
39#define SH_PFC_PIN_GROUP(n) \ 45#define SH_PFC_PIN_GROUP(n) \
@@ -120,8 +126,18 @@ struct pinmux_range {
120 pinmux_enum_t force; 126 pinmux_enum_t force;
121}; 127};
122 128
129struct sh_pfc;
130
131struct sh_pfc_soc_operations {
132 unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin);
133 void (*set_bias)(struct sh_pfc *pfc, unsigned int pin,
134 unsigned int bias);
135};
136
123struct sh_pfc_soc_info { 137struct sh_pfc_soc_info {
124 const char *name; 138 const char *name;
139 const struct sh_pfc_soc_operations *ops;
140
125 struct pinmux_range input; 141 struct pinmux_range input;
126 struct pinmux_range input_pd; 142 struct pinmux_range input_pd;
127 struct pinmux_range input_pu; 143 struct pinmux_range input_pu;