summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2017-01-27 05:07:14 -0500
committerLinus Walleij <linus.walleij@linaro.org>2017-01-30 09:01:35 -0500
commite57725eabf87c9c75bc73bd19ea00e887155e43f (patch)
tree93e55ff43d92764fd78a4810d531050a5eb5259f /drivers/pinctrl
parent74694269116bf04a97d89dfce7489fde7eb41ab1 (diff)
pinctrl: intel: Add support for hardware debouncer
The next generation Intel GPIO hardware has two additional registers PADCFG2 and PADCFG3. The latter is marked as reserved but the former includes configuration for per-pad hardware debouncer. This patch adds support for that in the Intel pinctrl core driver. Since these are additional features on top of the current generation hardware, we use revision number and feature flags to enable this if detected. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c130
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.h5
2 files changed, 133 insertions, 2 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 377a3f090dd1..36263d69df41 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/gpio/driver.h> 15#include <linux/gpio/driver.h>
16#include <linux/log2.h>
16#include <linux/platform_device.h> 17#include <linux/platform_device.h>
17#include <linux/pinctrl/pinctrl.h> 18#include <linux/pinctrl/pinctrl.h>
18#include <linux/pinctrl/pinmux.h> 19#include <linux/pinctrl/pinmux.h>
@@ -23,6 +24,10 @@
23#include "pinctrl-intel.h" 24#include "pinctrl-intel.h"
24 25
25/* Offset from regs */ 26/* Offset from regs */
27#define REVID 0x000
28#define REVID_SHIFT 16
29#define REVID_MASK GENMASK(31, 16)
30
26#define PADBAR 0x00c 31#define PADBAR 0x00c
27#define GPI_IS 0x100 32#define GPI_IS 0x100
28#define GPI_GPE_STS 0x140 33#define GPI_GPE_STS 0x140
@@ -41,6 +46,7 @@
41#define PADCFG0_RXEVCFG_EDGE 1 46#define PADCFG0_RXEVCFG_EDGE 1
42#define PADCFG0_RXEVCFG_DISABLED 2 47#define PADCFG0_RXEVCFG_DISABLED 2
43#define PADCFG0_RXEVCFG_EDGE_BOTH 3 48#define PADCFG0_RXEVCFG_EDGE_BOTH 3
49#define PADCFG0_PREGFRXSEL BIT(24)
44#define PADCFG0_RXINV BIT(23) 50#define PADCFG0_RXINV BIT(23)
45#define PADCFG0_GPIROUTIOXAPIC BIT(20) 51#define PADCFG0_GPIROUTIOXAPIC BIT(20)
46#define PADCFG0_GPIROUTSCI BIT(19) 52#define PADCFG0_GPIROUTSCI BIT(19)
@@ -62,9 +68,17 @@
62#define PADCFG1_TERM_5K 2 68#define PADCFG1_TERM_5K 2
63#define PADCFG1_TERM_1K 1 69#define PADCFG1_TERM_1K 1
64 70
71#define PADCFG2 0x008
72#define PADCFG2_DEBEN BIT(0)
73#define PADCFG2_DEBOUNCE_SHIFT 1
74#define PADCFG2_DEBOUNCE_MASK GENMASK(4, 1)
75
76#define DEBOUNCE_PERIOD 31250 /* ns */
77
65struct intel_pad_context { 78struct intel_pad_context {
66 u32 padcfg0; 79 u32 padcfg0;
67 u32 padcfg1; 80 u32 padcfg1;
81 u32 padcfg2;
68}; 82};
69 83
70struct intel_community_context { 84struct intel_community_context {
@@ -126,13 +140,19 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
126{ 140{
127 const struct intel_community *community; 141 const struct intel_community *community;
128 unsigned padno; 142 unsigned padno;
143 size_t nregs;
129 144
130 community = intel_get_community(pctrl, pin); 145 community = intel_get_community(pctrl, pin);
131 if (!community) 146 if (!community)
132 return NULL; 147 return NULL;
133 148
134 padno = pin_to_padno(community, pin); 149 padno = pin_to_padno(community, pin);
135 return community->pad_regs + reg + padno * 8; 150 nregs = (community->features & PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2;
151
152 if (reg == PADCFG2 && !(community->features & PINCTRL_FEATURE_DEBOUNCE))
153 return NULL;
154
155 return community->pad_regs + reg + padno * nregs * 4;
136} 156}
137 157
138static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin) 158static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
@@ -244,6 +264,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
244 unsigned pin) 264 unsigned pin)
245{ 265{
246 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 266 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
267 void __iomem *padcfg;
247 u32 cfg0, cfg1, mode; 268 u32 cfg0, cfg1, mode;
248 bool locked, acpi; 269 bool locked, acpi;
249 270
@@ -263,6 +284,11 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
263 284
264 seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1); 285 seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1);
265 286
287 /* Dump the additional PADCFG registers if available */
288 padcfg = intel_get_padcfg(pctrl, pin, PADCFG2);
289 if (padcfg)
290 seq_printf(s, " 0x%08x", readl(padcfg));
291
266 locked = intel_pad_locked(pctrl, pin); 292 locked = intel_pad_locked(pctrl, pin);
267 acpi = intel_pad_acpi_mode(pctrl, pin); 293 acpi = intel_pad_acpi_mode(pctrl, pin);
268 294
@@ -433,7 +459,7 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
433 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 459 struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
434 enum pin_config_param param = pinconf_to_config_param(*config); 460 enum pin_config_param param = pinconf_to_config_param(*config);
435 u32 value, term; 461 u32 value, term;
436 u16 arg = 0; 462 u32 arg = 0;
437 463
438 if (!intel_pad_owned_by_host(pctrl, pin)) 464 if (!intel_pad_owned_by_host(pctrl, pin))
439 return -ENOTSUPP; 465 return -ENOTSUPP;
@@ -483,6 +509,24 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
483 509
484 break; 510 break;
485 511
512 case PIN_CONFIG_INPUT_DEBOUNCE: {
513 void __iomem *padcfg2;
514 u32 v;
515
516 padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
517 if (!padcfg2)
518 return -ENOTSUPP;
519
520 v = readl(padcfg2);
521 if (!(v & PADCFG2_DEBEN))
522 return -EINVAL;
523
524 v = (v & PADCFG2_DEBOUNCE_MASK) >> PADCFG2_DEBOUNCE_SHIFT;
525 arg = BIT(v) * DEBOUNCE_PERIOD / 1000;
526
527 break;
528 }
529
486 default: 530 default:
487 return -ENOTSUPP; 531 return -ENOTSUPP;
488 } 532 }
@@ -560,6 +604,53 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
560 return ret; 604 return ret;
561} 605}
562 606
607static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned pin,
608 unsigned debounce)
609{
610 void __iomem *padcfg0, *padcfg2;
611 unsigned long flags;
612 u32 value0, value2;
613 int ret = 0;
614
615 padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
616 if (!padcfg2)
617 return -ENOTSUPP;
618
619 padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
620
621 raw_spin_lock_irqsave(&pctrl->lock, flags);
622
623 value0 = readl(padcfg0);
624 value2 = readl(padcfg2);
625
626 /* Disable glitch filter and debouncer */
627 value0 &= ~PADCFG0_PREGFRXSEL;
628 value2 &= ~(PADCFG2_DEBEN | PADCFG2_DEBOUNCE_MASK);
629
630 if (debounce) {
631 unsigned long v;
632
633 v = order_base_2(debounce * 1000 / DEBOUNCE_PERIOD);
634 if (v < 3 || v > 15) {
635 ret = -EINVAL;
636 goto exit_unlock;
637 } else {
638 /* Enable glitch filter and debouncer */
639 value0 |= PADCFG0_PREGFRXSEL;
640 value2 |= v << PADCFG2_DEBOUNCE_SHIFT;
641 value2 |= PADCFG2_DEBEN;
642 }
643 }
644
645 writel(value0, padcfg0);
646 writel(value2, padcfg2);
647
648exit_unlock:
649 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
650
651 return ret;
652}
653
563static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin, 654static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
564 unsigned long *configs, unsigned nconfigs) 655 unsigned long *configs, unsigned nconfigs)
565{ 656{
@@ -579,6 +670,13 @@ static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
579 return ret; 670 return ret;
580 break; 671 break;
581 672
673 case PIN_CONFIG_INPUT_DEBOUNCE:
674 ret = intel_config_set_debounce(pctrl, pin,
675 pinconf_to_config_argument(configs[i]));
676 if (ret)
677 return ret;
678 break;
679
582 default: 680 default:
583 return -ENOTSUPP; 681 return -ENOTSUPP;
584 } 682 }
@@ -653,6 +751,7 @@ static const struct gpio_chip intel_gpio_chip = {
653 .direction_output = intel_gpio_direction_output, 751 .direction_output = intel_gpio_direction_output,
654 .get = intel_gpio_get, 752 .get = intel_gpio_get,
655 .set = intel_gpio_set, 753 .set = intel_gpio_set,
754 .set_config = gpiochip_generic_config,
656}; 755};
657 756
658static void intel_gpio_irq_ack(struct irq_data *d) 757static void intel_gpio_irq_ack(struct irq_data *d)
@@ -1008,6 +1107,18 @@ int intel_pinctrl_probe(struct platform_device *pdev,
1008 if (IS_ERR(regs)) 1107 if (IS_ERR(regs))
1009 return PTR_ERR(regs); 1108 return PTR_ERR(regs);
1010 1109
1110 /*
1111 * Determine community features based on the revision if
1112 * not specified already.
1113 */
1114 if (!community->features) {
1115 u32 rev;
1116
1117 rev = (readl(regs + REVID) & REVID_MASK) >> REVID_SHIFT;
1118 if (rev >= 0x94)
1119 community->features |= PINCTRL_FEATURE_DEBOUNCE;
1120 }
1121
1011 /* Read offset of the pad configuration registers */ 1122 /* Read offset of the pad configuration registers */
1012 padbar = readl(regs + PADBAR); 1123 padbar = readl(regs + PADBAR);
1013 1124
@@ -1081,6 +1192,7 @@ int intel_pinctrl_suspend(struct device *dev)
1081 pads = pctrl->context.pads; 1192 pads = pctrl->context.pads;
1082 for (i = 0; i < pctrl->soc->npins; i++) { 1193 for (i = 0; i < pctrl->soc->npins; i++) {
1083 const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i]; 1194 const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
1195 void __iomem *padcfg;
1084 u32 val; 1196 u32 val;
1085 1197
1086 if (!intel_pinctrl_should_save(pctrl, desc->number)) 1198 if (!intel_pinctrl_should_save(pctrl, desc->number))
@@ -1090,6 +1202,10 @@ int intel_pinctrl_suspend(struct device *dev)
1090 pads[i].padcfg0 = val & ~PADCFG0_GPIORXSTATE; 1202 pads[i].padcfg0 = val & ~PADCFG0_GPIORXSTATE;
1091 val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG1)); 1203 val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG1));
1092 pads[i].padcfg1 = val; 1204 pads[i].padcfg1 = val;
1205
1206 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2);
1207 if (padcfg)
1208 pads[i].padcfg2 = readl(padcfg);
1093 } 1209 }
1094 1210
1095 communities = pctrl->context.communities; 1211 communities = pctrl->context.communities;
@@ -1162,6 +1278,16 @@ int intel_pinctrl_resume(struct device *dev)
1162 dev_dbg(dev, "restored pin %u padcfg1 %#08x\n", 1278 dev_dbg(dev, "restored pin %u padcfg1 %#08x\n",
1163 desc->number, readl(padcfg)); 1279 desc->number, readl(padcfg));
1164 } 1280 }
1281
1282 padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2);
1283 if (padcfg) {
1284 val = readl(padcfg);
1285 if (val != pads[i].padcfg2) {
1286 writel(pads[i].padcfg2, padcfg);
1287 dev_dbg(dev, "restored pin %u padcfg2 %#08x\n",
1288 desc->number, readl(padcfg));
1289 }
1290 }
1165 } 1291 }
1166 1292
1167 communities = pctrl->context.communities; 1293 communities = pctrl->context.communities;
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index c22c44485c5d..1ff5abf309e3 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -58,6 +58,7 @@ struct intel_function {
58 * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK, 58 * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
59 * HOSTSW_OWN, GPI_IS, GPI_IE, etc. 59 * HOSTSW_OWN, GPI_IS, GPI_IE, etc.
60 * @npins: Number of pins in this community 60 * @npins: Number of pins in this community
61 * @features: Additional features supported by the hardware
61 * @regs: Community specific common registers (reserved for core driver) 62 * @regs: Community specific common registers (reserved for core driver)
62 * @pad_regs: Community specific pad registers (reserved for core driver) 63 * @pad_regs: Community specific pad registers (reserved for core driver)
63 * @ngpps: Number of groups (hw groups) in this community (reserved for 64 * @ngpps: Number of groups (hw groups) in this community (reserved for
@@ -72,11 +73,15 @@ struct intel_community {
72 unsigned pin_base; 73 unsigned pin_base;
73 unsigned gpp_size; 74 unsigned gpp_size;
74 size_t npins; 75 size_t npins;
76 unsigned features;
75 void __iomem *regs; 77 void __iomem *regs;
76 void __iomem *pad_regs; 78 void __iomem *pad_regs;
77 size_t ngpps; 79 size_t ngpps;
78}; 80};
79 81
82/* Additional features supported by the hardware */
83#define PINCTRL_FEATURE_DEBOUNCE BIT(0)
84
80#define PIN_GROUP(n, p, m) \ 85#define PIN_GROUP(n, p, m) \
81 { \ 86 { \
82 .name = (n), \ 87 .name = (n), \