diff options
author | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2012-09-26 02:57:45 -0400 |
---|---|---|
committer | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2012-11-18 17:35:55 -0500 |
commit | 7ebd7a3ae0dd6e826767df504f7850d935fc3ee9 (patch) | |
tree | fae32ddae5f6228afc1750a65d7a79729cf8dbc2 /drivers/pinctrl/pinctrl-at91.c | |
parent | 32b01a366eb5d7d480570fe05d1dc18170387f5f (diff) |
pinctrl: at91 add deglitch, debounce, pull down and schmitt trigger mux option support
add :
set_deglitch: enable/disable deglitch
set_debounce: enable/disable debounce
set_pulldown: enable/disable pulldown
disable_schmitt_trig: disable schmitt trigger
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Diffstat (limited to 'drivers/pinctrl/pinctrl-at91.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-at91.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 401fc96f577e..0d7e6c3c33a7 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c | |||
@@ -59,6 +59,12 @@ static int gpio_banks; | |||
59 | 59 | ||
60 | #define PULL_UP (1 << 0) | 60 | #define PULL_UP (1 << 0) |
61 | #define MULTI_DRIVE (1 << 1) | 61 | #define MULTI_DRIVE (1 << 1) |
62 | #define DEGLITCH (1 << 2) | ||
63 | #define PULL_DOWN (1 << 3) | ||
64 | #define DIS_SCHMIT (1 << 4) | ||
65 | #define DEBOUNCE (1 << 16) | ||
66 | #define DEBOUNCE_VAL_SHIFT 17 | ||
67 | #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) | ||
62 | 68 | ||
63 | /** | 69 | /** |
64 | * struct at91_pmx_func - describes AT91 pinmux functions | 70 | * struct at91_pmx_func - describes AT91 pinmux functions |
@@ -122,6 +128,14 @@ struct at91_pin_group { | |||
122 | * @mux_B_periph: mux as periph B | 128 | * @mux_B_periph: mux as periph B |
123 | * @mux_C_periph: mux as periph C | 129 | * @mux_C_periph: mux as periph C |
124 | * @mux_D_periph: mux as periph D | 130 | * @mux_D_periph: mux as periph D |
131 | * @get_deglitch: get deglitch status | ||
132 | * @set_deglitch: enable/disable deglitch | ||
133 | * @get_debounce: get debounce status | ||
134 | * @set_debounce: enable/disable debounce | ||
135 | * @get_pulldown: get pulldown status | ||
136 | * @set_pulldown: enable/disable pulldown | ||
137 | * @get_schmitt_trig: get schmitt trigger status | ||
138 | * @disable_schmitt_trig: disable schmitt trigger | ||
125 | * @irq_type: return irq type | 139 | * @irq_type: return irq type |
126 | */ | 140 | */ |
127 | struct at91_pinctrl_mux_ops { | 141 | struct at91_pinctrl_mux_ops { |
@@ -130,6 +144,14 @@ struct at91_pinctrl_mux_ops { | |||
130 | void (*mux_B_periph)(void __iomem *pio, unsigned mask); | 144 | void (*mux_B_periph)(void __iomem *pio, unsigned mask); |
131 | void (*mux_C_periph)(void __iomem *pio, unsigned mask); | 145 | void (*mux_C_periph)(void __iomem *pio, unsigned mask); |
132 | void (*mux_D_periph)(void __iomem *pio, unsigned mask); | 146 | void (*mux_D_periph)(void __iomem *pio, unsigned mask); |
147 | bool (*get_deglitch)(void __iomem *pio, unsigned pin); | ||
148 | void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on); | ||
149 | bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div); | ||
150 | void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div); | ||
151 | bool (*get_pulldown)(void __iomem *pio, unsigned pin); | ||
152 | void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on); | ||
153 | bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); | ||
154 | void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask); | ||
133 | /* irq */ | 155 | /* irq */ |
134 | int (*irq_type)(struct irq_data *d, unsigned type); | 156 | int (*irq_type)(struct irq_data *d, unsigned type); |
135 | }; | 157 | }; |
@@ -386,10 +408,68 @@ static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask) | |||
386 | return select + 1; | 408 | return select + 1; |
387 | } | 409 | } |
388 | 410 | ||
411 | static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin) | ||
412 | { | ||
413 | return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1; | ||
414 | } | ||
415 | |||
416 | static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on) | ||
417 | { | ||
418 | __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); | ||
419 | } | ||
420 | |||
421 | static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on) | ||
422 | { | ||
423 | if (is_on) | ||
424 | __raw_writel(mask, pio + PIO_IFSCDR); | ||
425 | at91_mux_set_deglitch(pio, mask, is_on); | ||
426 | } | ||
427 | |||
428 | static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div) | ||
429 | { | ||
430 | *div = __raw_readl(pio + PIO_SCDR); | ||
431 | |||
432 | return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1; | ||
433 | } | ||
434 | |||
435 | static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask, | ||
436 | bool is_on, u32 div) | ||
437 | { | ||
438 | if (is_on) { | ||
439 | __raw_writel(mask, pio + PIO_IFSCER); | ||
440 | __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR); | ||
441 | __raw_writel(mask, pio + PIO_IFER); | ||
442 | } else { | ||
443 | __raw_writel(mask, pio + PIO_IFDR); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin) | ||
448 | { | ||
449 | return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1; | ||
450 | } | ||
451 | |||
452 | static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on) | ||
453 | { | ||
454 | __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR)); | ||
455 | } | ||
456 | |||
457 | static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask) | ||
458 | { | ||
459 | __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT); | ||
460 | } | ||
461 | |||
462 | static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin) | ||
463 | { | ||
464 | return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1; | ||
465 | } | ||
466 | |||
389 | static struct at91_pinctrl_mux_ops at91rm9200_ops = { | 467 | static struct at91_pinctrl_mux_ops at91rm9200_ops = { |
390 | .get_periph = at91_mux_get_periph, | 468 | .get_periph = at91_mux_get_periph, |
391 | .mux_A_periph = at91_mux_set_A_periph, | 469 | .mux_A_periph = at91_mux_set_A_periph, |
392 | .mux_B_periph = at91_mux_set_B_periph, | 470 | .mux_B_periph = at91_mux_set_B_periph, |
471 | .get_deglitch = at91_mux_get_deglitch, | ||
472 | .set_deglitch = at91_mux_set_deglitch, | ||
393 | .irq_type = gpio_irq_type, | 473 | .irq_type = gpio_irq_type, |
394 | }; | 474 | }; |
395 | 475 | ||
@@ -399,6 +479,14 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = { | |||
399 | .mux_B_periph = at91_mux_pio3_set_B_periph, | 479 | .mux_B_periph = at91_mux_pio3_set_B_periph, |
400 | .mux_C_periph = at91_mux_pio3_set_C_periph, | 480 | .mux_C_periph = at91_mux_pio3_set_C_periph, |
401 | .mux_D_periph = at91_mux_pio3_set_D_periph, | 481 | .mux_D_periph = at91_mux_pio3_set_D_periph, |
482 | .get_deglitch = at91_mux_get_deglitch, | ||
483 | .set_deglitch = at91_mux_pio3_set_deglitch, | ||
484 | .get_debounce = at91_mux_pio3_get_debounce, | ||
485 | .set_debounce = at91_mux_pio3_set_debounce, | ||
486 | .get_pulldown = at91_mux_pio3_get_pulldown, | ||
487 | .set_pulldown = at91_mux_pio3_set_pulldown, | ||
488 | .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, | ||
489 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, | ||
402 | .irq_type = alt_gpio_irq_type, | 490 | .irq_type = alt_gpio_irq_type, |
403 | }; | 491 | }; |
404 | 492 | ||
@@ -624,6 +712,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, | |||
624 | struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); | 712 | struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); |
625 | void __iomem *pio; | 713 | void __iomem *pio; |
626 | unsigned pin; | 714 | unsigned pin; |
715 | int div; | ||
627 | 716 | ||
628 | dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config); | 717 | dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config); |
629 | pio = pin_to_controller(info, pin_to_bank(pin_id)); | 718 | pio = pin_to_controller(info, pin_to_bank(pin_id)); |
@@ -635,6 +724,15 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, | |||
635 | if (at91_mux_get_pullup(pio, pin)) | 724 | if (at91_mux_get_pullup(pio, pin)) |
636 | *config |= PULL_UP; | 725 | *config |= PULL_UP; |
637 | 726 | ||
727 | if (info->ops->get_deglitch && info->ops->get_deglitch(pio, pin)) | ||
728 | *config |= DEGLITCH; | ||
729 | if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div)) | ||
730 | *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT); | ||
731 | if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin)) | ||
732 | *config |= PULL_DOWN; | ||
733 | if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin)) | ||
734 | *config |= DIS_SCHMIT; | ||
735 | |||
638 | return 0; | 736 | return 0; |
639 | } | 737 | } |
640 | 738 | ||
@@ -649,8 +747,21 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, | |||
649 | pio = pin_to_controller(info, pin_to_bank(pin_id)); | 747 | pio = pin_to_controller(info, pin_to_bank(pin_id)); |
650 | mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK); | 748 | mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK); |
651 | 749 | ||
750 | if (config & PULL_UP && config & PULL_DOWN) | ||
751 | return -EINVAL; | ||
752 | |||
652 | at91_mux_set_pullup(pio, mask, config & PULL_UP); | 753 | at91_mux_set_pullup(pio, mask, config & PULL_UP); |
653 | at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE); | 754 | at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE); |
755 | if (info->ops->set_deglitch) | ||
756 | info->ops->set_deglitch(pio, mask, config & DEGLITCH); | ||
757 | if (info->ops->set_debounce) | ||
758 | info->ops->set_debounce(pio, mask, config & DEBOUNCE, | ||
759 | (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT); | ||
760 | if (info->ops->set_pulldown) | ||
761 | info->ops->set_pulldown(pio, mask, config & PULL_DOWN); | ||
762 | if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT) | ||
763 | info->ops->disable_schmitt_trig(pio, mask); | ||
764 | |||
654 | return 0; | 765 | return 0; |
655 | } | 766 | } |
656 | 767 | ||