aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2016-04-25 06:38:34 -0400
committerLinus Walleij <linus.walleij@linaro.org>2016-04-29 05:03:15 -0400
commit3737de42afb8d76f405689a4699e8e5dd5e2ef96 (patch)
tree543f4edbaea901b4ac4f4ad2d7b8baccbf5006ce /drivers/gpio
parentb546be0db955840e2c14aae5d8e5f93a456f9982 (diff)
gpio: tegra: Add support for gpio debounce
NVIDIA's Tegra210 support the HW debounce in the GPIO controller for all its GPIO pins. Add support for setting debounce timing by implementing the set_debounce callback of gpiochip. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-tegra.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 653825db4baa..b3ddd922290d 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -46,10 +46,13 @@
46#define GPIO_INT_ENB(t, x) (GPIO_REG(t, x) + 0x50) 46#define GPIO_INT_ENB(t, x) (GPIO_REG(t, x) + 0x50)
47#define GPIO_INT_LVL(t, x) (GPIO_REG(t, x) + 0x60) 47#define GPIO_INT_LVL(t, x) (GPIO_REG(t, x) + 0x60)
48#define GPIO_INT_CLR(t, x) (GPIO_REG(t, x) + 0x70) 48#define GPIO_INT_CLR(t, x) (GPIO_REG(t, x) + 0x70)
49#define GPIO_DBC_CNT(t, x) (GPIO_REG(t, x) + 0xF0)
50
49 51
50#define GPIO_MSK_CNF(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x00) 52#define GPIO_MSK_CNF(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x00)
51#define GPIO_MSK_OE(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x10) 53#define GPIO_MSK_OE(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x10)
52#define GPIO_MSK_OUT(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0X20) 54#define GPIO_MSK_OUT(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0X20)
55#define GPIO_MSK_DBC_EN(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x30)
53#define GPIO_MSK_INT_STA(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x40) 56#define GPIO_MSK_INT_STA(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x40)
54#define GPIO_MSK_INT_ENB(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x50) 57#define GPIO_MSK_INT_ENB(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x50)
55#define GPIO_MSK_INT_LVL(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x60) 58#define GPIO_MSK_INT_LVL(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x60)
@@ -67,6 +70,7 @@ struct tegra_gpio_bank {
67 int bank; 70 int bank;
68 int irq; 71 int irq;
69 spinlock_t lvl_lock[4]; 72 spinlock_t lvl_lock[4];
73 spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */
70#ifdef CONFIG_PM_SLEEP 74#ifdef CONFIG_PM_SLEEP
71 u32 cnf[4]; 75 u32 cnf[4];
72 u32 out[4]; 76 u32 out[4];
@@ -74,11 +78,14 @@ struct tegra_gpio_bank {
74 u32 int_enb[4]; 78 u32 int_enb[4];
75 u32 int_lvl[4]; 79 u32 int_lvl[4];
76 u32 wake_enb[4]; 80 u32 wake_enb[4];
81 u32 dbc_enb[4];
77#endif 82#endif
83 u32 dbc_cnt[4];
78 struct tegra_gpio_info *tgi; 84 struct tegra_gpio_info *tgi;
79}; 85};
80 86
81struct tegra_gpio_soc_config { 87struct tegra_gpio_soc_config {
88 bool debounce_supported;
82 u32 bank_stride; 89 u32 bank_stride;
83 u32 upper_offset; 90 u32 upper_offset;
84}; 91};
@@ -184,6 +191,39 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
184 return 0; 191 return 0;
185} 192}
186 193
194static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
195 unsigned int debounce)
196{
197 struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
198 struct tegra_gpio_bank *bank = &tgi->bank_info[GPIO_BANK(offset)];
199 unsigned int debounce_ms = DIV_ROUND_UP(debounce, 1000);
200 unsigned long flags;
201 int port;
202
203 if (!debounce_ms) {
204 tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset),
205 offset, 0);
206 return 0;
207 }
208
209 debounce_ms = min(debounce_ms, 255U);
210 port = GPIO_PORT(offset);
211
212 /* There is only one debounce count register per port and hence
213 * set the maximum of current and requested debounce time.
214 */
215 spin_lock_irqsave(&bank->dbc_lock[port], flags);
216 if (bank->dbc_cnt[port] < debounce_ms) {
217 tegra_gpio_writel(tgi, debounce_ms, GPIO_DBC_CNT(tgi, offset));
218 bank->dbc_cnt[port] = debounce_ms;
219 }
220 spin_unlock_irqrestore(&bank->dbc_lock[port], flags);
221
222 tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), offset, 1);
223
224 return 0;
225}
226
187static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 227static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
188{ 228{
189 struct tegra_gpio_info *tgi = gpiochip_get_data(chip); 229 struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
@@ -350,6 +390,14 @@ static int tegra_gpio_resume(struct device *dev)
350 unsigned int gpio = (b<<5) | (p<<3); 390 unsigned int gpio = (b<<5) | (p<<3);
351 tegra_gpio_writel(tgi, bank->cnf[p], 391 tegra_gpio_writel(tgi, bank->cnf[p],
352 GPIO_CNF(tgi, gpio)); 392 GPIO_CNF(tgi, gpio));
393
394 if (tgi->soc->debounce_supported) {
395 tegra_gpio_writel(tgi, bank->dbc_cnt[p],
396 GPIO_DBC_CNT(tgi, gpio));
397 tegra_gpio_writel(tgi, bank->dbc_enb[p],
398 GPIO_MSK_DBC_EN(tgi, gpio));
399 }
400
353 tegra_gpio_writel(tgi, bank->out[p], 401 tegra_gpio_writel(tgi, bank->out[p],
354 GPIO_OUT(tgi, gpio)); 402 GPIO_OUT(tgi, gpio));
355 tegra_gpio_writel(tgi, bank->oe[p], 403 tegra_gpio_writel(tgi, bank->oe[p],
@@ -385,6 +433,13 @@ static int tegra_gpio_suspend(struct device *dev)
385 GPIO_OUT(tgi, gpio)); 433 GPIO_OUT(tgi, gpio));
386 bank->oe[p] = tegra_gpio_readl(tgi, 434 bank->oe[p] = tegra_gpio_readl(tgi,
387 GPIO_OE(tgi, gpio)); 435 GPIO_OE(tgi, gpio));
436 if (tgi->soc->debounce_supported) {
437 bank->dbc_enb[p] = tegra_gpio_readl(tgi,
438 GPIO_MSK_DBC_EN(tgi, gpio));
439 bank->dbc_enb[p] = (bank->dbc_enb[p] << 8) |
440 bank->dbc_enb[p];
441 }
442
388 bank->int_enb[p] = tegra_gpio_readl(tgi, 443 bank->int_enb[p] = tegra_gpio_readl(tgi,
389 GPIO_INT_ENB(tgi, gpio)); 444 GPIO_INT_ENB(tgi, gpio));
390 bank->int_lvl[p] = tegra_gpio_readl(tgi, 445 bank->int_lvl[p] = tegra_gpio_readl(tgi,
@@ -538,6 +593,9 @@ static int tegra_gpio_probe(struct platform_device *pdev)
538 593
539 platform_set_drvdata(pdev, tgi); 594 platform_set_drvdata(pdev, tgi);
540 595
596 if (config->debounce_supported)
597 tgi->gc.set_debounce = tegra_gpio_set_debounce;
598
541 tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count * 599 tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count *
542 sizeof(*tgi->bank_info), GFP_KERNEL); 600 sizeof(*tgi->bank_info), GFP_KERNEL);
543 if (!tgi->bank_info) 601 if (!tgi->bank_info)
@@ -597,8 +655,10 @@ static int tegra_gpio_probe(struct platform_device *pdev)
597 irq_set_chained_handler_and_data(bank->irq, 655 irq_set_chained_handler_and_data(bank->irq,
598 tegra_gpio_irq_handler, bank); 656 tegra_gpio_irq_handler, bank);
599 657
600 for (j = 0; j < 4; j++) 658 for (j = 0; j < 4; j++) {
601 spin_lock_init(&bank->lvl_lock[j]); 659 spin_lock_init(&bank->lvl_lock[j]);
660 spin_lock_init(&bank->dbc_lock[j]);
661 }
602 } 662 }
603 663
604 tegra_gpio_debuginit(tgi); 664 tegra_gpio_debuginit(tgi);
@@ -616,7 +676,14 @@ static const struct tegra_gpio_soc_config tegra30_gpio_config = {
616 .upper_offset = 0x80, 676 .upper_offset = 0x80,
617}; 677};
618 678
679static const struct tegra_gpio_soc_config tegra210_gpio_config = {
680 .debounce_supported = true,
681 .bank_stride = 0x100,
682 .upper_offset = 0x80,
683};
684
619static const struct of_device_id tegra_gpio_of_match[] = { 685static const struct of_device_id tegra_gpio_of_match[] = {
686 { .compatible = "nvidia,tegra210-gpio", .data = &tegra210_gpio_config },
620 { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, 687 { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
621 { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, 688 { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
622 { }, 689 { },