aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c77
-rw-r--r--drivers/pinctrl/pinctrl-coh901.h5
-rw-r--r--drivers/pinctrl/pinctrl-u300.c60
4 files changed, 135 insertions, 8 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 07f3d8d38580..abfb96408779 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -73,6 +73,7 @@ config PINCTRL_U300
73 bool "U300 pin controller driver" 73 bool "U300 pin controller driver"
74 depends on ARCH_U300 74 depends on ARCH_U300
75 select PINMUX 75 select PINMUX
76 select GENERIC_PINCONF
76 77
77config PINCTRL_COH901 78config PINCTRL_COH901
78 bool "ST-Ericsson U300 COH 901 335/571 GPIO" 79 bool "ST-Ericsson U300 COH 901 335/571 GPIO"
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 724234c9b01b..0797eba3e33a 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -23,7 +23,9 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/pinctrl/consumer.h> 25#include <linux/pinctrl/consumer.h>
26#include <linux/pinctrl/pinconf-generic.h>
26#include <mach/gpio-u300.h> 27#include <mach/gpio-u300.h>
28#include "pinctrl-coh901.h"
27 29
28/* 30/*
29 * Register definitions for COH 901 335 variant 31 * Register definitions for COH 901 335 variant
@@ -418,8 +420,68 @@ static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
418 return retirq; 420 return retirq;
419} 421}
420 422
421static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, 423/* Returning -EINVAL means "supported but not available" */
422 enum pin_config_param param, unsigned long data) 424int u300_gpio_config_get(struct gpio_chip *chip,
425 unsigned offset,
426 unsigned long *config)
427{
428 struct u300_gpio *gpio = to_u300_gpio(chip);
429 enum pin_config_param param = (enum pin_config_param) *config;
430 bool biasmode;
431 u32 drmode;
432
433 /* One bit per pin, clamp to bool range */
434 biasmode = !!(readl(U300_PIN_REG(offset, per)) & U300_PIN_BIT(offset));
435
436 /* Mask out the two bits for this pin and shift to bits 0,1 */
437 drmode = readl(U300_PIN_REG(offset, pcr));
438 drmode &= (U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
439 drmode >>= ((offset & 0x07) << 1);
440
441 switch(param) {
442 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
443 *config = 0;
444 if (biasmode)
445 return 0;
446 else
447 return -EINVAL;
448 break;
449 case PIN_CONFIG_BIAS_PULL_UP:
450 *config = 0;
451 if (!biasmode)
452 return 0;
453 else
454 return -EINVAL;
455 break;
456 case PIN_CONFIG_DRIVE_PUSH_PULL:
457 *config = 0;
458 if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL)
459 return 0;
460 else
461 return -EINVAL;
462 break;
463 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
464 *config = 0;
465 if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN)
466 return 0;
467 else
468 return -EINVAL;
469 break;
470 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
471 *config = 0;
472 if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE)
473 return 0;
474 else
475 return -EINVAL;
476 break;
477 default:
478 break;
479 }
480 return -ENOTSUPP;
481}
482
483int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset,
484 enum pin_config_param param)
423{ 485{
424 struct u300_gpio *gpio = to_u300_gpio(chip); 486 struct u300_gpio *gpio = to_u300_gpio(chip);
425 unsigned long flags; 487 unsigned long flags;
@@ -620,13 +682,12 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
620 u300_gpio_direction_output(&gpio->chip, offset, conf->outval); 682 u300_gpio_direction_output(&gpio->chip, offset, conf->outval);
621 683
622 /* Deactivate bias mode for output */ 684 /* Deactivate bias mode for output */
623 u300_gpio_config(&gpio->chip, offset, 685 u300_gpio_config_set(&gpio->chip, offset,
624 PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 686 PIN_CONFIG_BIAS_HIGH_IMPEDANCE);
625 0);
626 687
627 /* Set drive mode for output */ 688 /* Set drive mode for output */
628 u300_gpio_config(&gpio->chip, offset, 689 u300_gpio_config_set(&gpio->chip, offset,
629 PIN_CONFIG_DRIVE_PUSH_PULL, 0); 690 PIN_CONFIG_DRIVE_PUSH_PULL);
630 691
631 dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n", 692 dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n",
632 offset, conf->outval); 693 offset, conf->outval);
@@ -637,7 +698,7 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
637 u300_gpio_set(&gpio->chip, offset, 0); 698 u300_gpio_set(&gpio->chip, offset, 0);
638 699
639 /* Set bias mode for input */ 700 /* Set bias mode for input */
640 u300_gpio_config(&gpio->chip, offset, conf->bias_mode, 0); 701 u300_gpio_config_set(&gpio->chip, offset, conf->bias_mode);
641 702
642 dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n", 703 dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n",
643 offset, conf->bias_mode); 704 offset, conf->bias_mode);
diff --git a/drivers/pinctrl/pinctrl-coh901.h b/drivers/pinctrl/pinctrl-coh901.h
new file mode 100644
index 000000000000..87294222583e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-coh901.h
@@ -0,0 +1,5 @@
1int u300_gpio_config_get(struct gpio_chip *chip,
2 unsigned offset,
3 unsigned long *config);
4int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset,
5 enum pin_config_param param);
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index fc4a281caba5..26eb8ccd72d5 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -19,6 +19,9 @@
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/pinctrl/pinctrl.h> 20#include <linux/pinctrl/pinctrl.h>
21#include <linux/pinctrl/pinmux.h> 21#include <linux/pinctrl/pinmux.h>
22#include <linux/pinctrl/pinconf.h>
23#include <linux/pinctrl/pinconf-generic.h>
24#include "pinctrl-coh901.h"
22 25
23/* 26/*
24 * Register definitions for the U300 Padmux control registers in the 27 * Register definitions for the U300 Padmux control registers in the
@@ -1044,12 +1047,69 @@ static struct pinctrl_gpio_range u300_gpio_ranges[] = {
1044 U300_GPIO_RANGE(25, 181, 1), 1047 U300_GPIO_RANGE(25, 181, 1),
1045}; 1048};
1046 1049
1050static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
1051{
1052 int i;
1053
1054 for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
1055 struct pinctrl_gpio_range *range;
1056
1057 range = &u300_gpio_ranges[i];
1058 if (pin >= range->pin_base &&
1059 pin <= (range->pin_base + range->npins - 1))
1060 return range;
1061 }
1062 return NULL;
1063}
1064
1065int u300_pin_config_get(struct pinctrl_dev *pctldev,
1066 unsigned pin,
1067 unsigned long *config)
1068{
1069 struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
1070
1071 /* We get config for those pins we CAN get it for and that's it */
1072 if (!range)
1073 return -ENOTSUPP;
1074
1075 return u300_gpio_config_get(range->gc,
1076 (pin - range->pin_base + range->base),
1077 config);
1078}
1079
1080int u300_pin_config_set(struct pinctrl_dev *pctldev,
1081 unsigned pin,
1082 unsigned long config)
1083{
1084 struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
1085 int ret;
1086
1087 if (!range)
1088 return -EINVAL;
1089
1090 /* Note: none of these configurations take any argument */
1091 ret = u300_gpio_config_set(range->gc,
1092 (pin - range->pin_base + range->base),
1093 pinconf_to_config_param(config));
1094 if (ret)
1095 return ret;
1096
1097 return 0;
1098}
1099
1100static struct pinconf_ops u300_pconf_ops = {
1101 .is_generic = true,
1102 .pin_config_get = u300_pin_config_get,
1103 .pin_config_set = u300_pin_config_set,
1104};
1105
1047static struct pinctrl_desc u300_pmx_desc = { 1106static struct pinctrl_desc u300_pmx_desc = {
1048 .name = DRIVER_NAME, 1107 .name = DRIVER_NAME,
1049 .pins = u300_pads, 1108 .pins = u300_pads,
1050 .npins = ARRAY_SIZE(u300_pads), 1109 .npins = ARRAY_SIZE(u300_pads),
1051 .pctlops = &u300_pctrl_ops, 1110 .pctlops = &u300_pctrl_ops,
1052 .pmxops = &u300_pmx_ops, 1111 .pmxops = &u300_pmx_ops,
1112 .confops = &u300_pconf_ops,
1053 .owner = THIS_MODULE, 1113 .owner = THIS_MODULE,
1054}; 1114};
1055 1115