diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-at91.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-at91.c | 162 |
1 files changed, 161 insertions, 1 deletions
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 4839c36a3a1c..03b748ea3810 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c | |||
@@ -58,11 +58,28 @@ static int gpio_banks; | |||
58 | #define DEGLITCH (1 << 2) | 58 | #define DEGLITCH (1 << 2) |
59 | #define PULL_DOWN (1 << 3) | 59 | #define PULL_DOWN (1 << 3) |
60 | #define DIS_SCHMIT (1 << 4) | 60 | #define DIS_SCHMIT (1 << 4) |
61 | #define DRIVE_STRENGTH_SHIFT 5 | ||
62 | #define DRIVE_STRENGTH_MASK 0x3 | ||
63 | #define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT) | ||
61 | #define DEBOUNCE (1 << 16) | 64 | #define DEBOUNCE (1 << 16) |
62 | #define DEBOUNCE_VAL_SHIFT 17 | 65 | #define DEBOUNCE_VAL_SHIFT 17 |
63 | #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) | 66 | #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) |
64 | 67 | ||
65 | /** | 68 | /** |
69 | * These defines will translated the dt binding settings to our internal | ||
70 | * settings. They are not necessarily the same value as the register setting. | ||
71 | * The actual drive strength current of low, medium and high must be looked up | ||
72 | * from the corresponding device datasheet. This value is different for pins | ||
73 | * that are even in the same banks. It is also dependent on VCC. | ||
74 | * DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive | ||
75 | * strength when there is no dt config for it. | ||
76 | */ | ||
77 | #define DRIVE_STRENGTH_DEFAULT (0 << DRIVE_STRENGTH_SHIFT) | ||
78 | #define DRIVE_STRENGTH_LOW (1 << DRIVE_STRENGTH_SHIFT) | ||
79 | #define DRIVE_STRENGTH_MED (2 << DRIVE_STRENGTH_SHIFT) | ||
80 | #define DRIVE_STRENGTH_HI (3 << DRIVE_STRENGTH_SHIFT) | ||
81 | |||
82 | /** | ||
66 | * struct at91_pmx_func - describes AT91 pinmux functions | 83 | * struct at91_pmx_func - describes AT91 pinmux functions |
67 | * @name: the name of this specific function | 84 | * @name: the name of this specific function |
68 | * @groups: corresponding pin groups | 85 | * @groups: corresponding pin groups |
@@ -148,6 +165,9 @@ struct at91_pinctrl_mux_ops { | |||
148 | void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on); | 165 | void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on); |
149 | bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); | 166 | bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); |
150 | void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask); | 167 | void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask); |
168 | unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin); | ||
169 | void (*set_drivestrength)(void __iomem *pio, unsigned pin, | ||
170 | u32 strength); | ||
151 | /* irq */ | 171 | /* irq */ |
152 | int (*irq_type)(struct irq_data *d, unsigned type); | 172 | int (*irq_type)(struct irq_data *d, unsigned type); |
153 | }; | 173 | }; |
@@ -315,6 +335,30 @@ static unsigned pin_to_mask(unsigned int pin) | |||
315 | return 1 << pin; | 335 | return 1 << pin; |
316 | } | 336 | } |
317 | 337 | ||
338 | static unsigned two_bit_pin_value_shift_amount(unsigned int pin) | ||
339 | { | ||
340 | /* return the shift value for a pin for "two bit" per pin registers, | ||
341 | * i.e. drive strength */ | ||
342 | return 2*((pin >= MAX_NB_GPIO_PER_BANK/2) | ||
343 | ? pin - MAX_NB_GPIO_PER_BANK/2 : pin); | ||
344 | } | ||
345 | |||
346 | static unsigned sama5d3_get_drive_register(unsigned int pin) | ||
347 | { | ||
348 | /* drive strength is split between two registers | ||
349 | * with two bits per pin */ | ||
350 | return (pin >= MAX_NB_GPIO_PER_BANK/2) | ||
351 | ? SAMA5D3_PIO_DRIVER2 : SAMA5D3_PIO_DRIVER1; | ||
352 | } | ||
353 | |||
354 | static unsigned at91sam9x5_get_drive_register(unsigned int pin) | ||
355 | { | ||
356 | /* drive strength is split between two registers | ||
357 | * with two bits per pin */ | ||
358 | return (pin >= MAX_NB_GPIO_PER_BANK/2) | ||
359 | ? AT91SAM9X5_PIO_DRIVER2 : AT91SAM9X5_PIO_DRIVER1; | ||
360 | } | ||
361 | |||
318 | static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask) | 362 | static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask) |
319 | { | 363 | { |
320 | writel_relaxed(mask, pio + PIO_IDR); | 364 | writel_relaxed(mask, pio + PIO_IDR); |
@@ -468,6 +512,79 @@ static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin) | |||
468 | return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1; | 512 | return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1; |
469 | } | 513 | } |
470 | 514 | ||
515 | static inline u32 read_drive_strength(void __iomem *reg, unsigned pin) | ||
516 | { | ||
517 | unsigned tmp = __raw_readl(reg); | ||
518 | |||
519 | tmp = tmp >> two_bit_pin_value_shift_amount(pin); | ||
520 | |||
521 | return tmp & DRIVE_STRENGTH_MASK; | ||
522 | } | ||
523 | |||
524 | static unsigned at91_mux_sama5d3_get_drivestrength(void __iomem *pio, | ||
525 | unsigned pin) | ||
526 | { | ||
527 | unsigned tmp = read_drive_strength(pio + | ||
528 | sama5d3_get_drive_register(pin), pin); | ||
529 | |||
530 | /* SAMA5 strength is 1:1 with our defines, | ||
531 | * except 0 is equivalent to low per datasheet */ | ||
532 | if (!tmp) | ||
533 | tmp = DRIVE_STRENGTH_LOW; | ||
534 | |||
535 | return tmp; | ||
536 | } | ||
537 | |||
538 | static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio, | ||
539 | unsigned pin) | ||
540 | { | ||
541 | unsigned tmp = read_drive_strength(pio + | ||
542 | at91sam9x5_get_drive_register(pin), pin); | ||
543 | |||
544 | /* strength is inverse in SAM9x5s hardware with the pinctrl defines | ||
545 | * hardware: 0 = hi, 1 = med, 2 = low, 3 = rsvd */ | ||
546 | tmp = DRIVE_STRENGTH_HI - tmp; | ||
547 | |||
548 | return tmp; | ||
549 | } | ||
550 | |||
551 | static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength) | ||
552 | { | ||
553 | unsigned tmp = __raw_readl(reg); | ||
554 | unsigned shift = two_bit_pin_value_shift_amount(pin); | ||
555 | |||
556 | tmp &= ~(DRIVE_STRENGTH_MASK << shift); | ||
557 | tmp |= strength << shift; | ||
558 | |||
559 | __raw_writel(tmp, reg); | ||
560 | } | ||
561 | |||
562 | static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio, unsigned pin, | ||
563 | u32 setting) | ||
564 | { | ||
565 | /* do nothing if setting is zero */ | ||
566 | if (!setting) | ||
567 | return; | ||
568 | |||
569 | /* strength is 1 to 1 with setting for SAMA5 */ | ||
570 | set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting); | ||
571 | } | ||
572 | |||
573 | static void at91_mux_sam9x5_set_drivestrength(void __iomem *pio, unsigned pin, | ||
574 | u32 setting) | ||
575 | { | ||
576 | /* do nothing if setting is zero */ | ||
577 | if (!setting) | ||
578 | return; | ||
579 | |||
580 | /* strength is inverse on SAM9x5s with our defines | ||
581 | * 0 = hi, 1 = med, 2 = low, 3 = rsvd */ | ||
582 | setting = DRIVE_STRENGTH_HI - setting; | ||
583 | |||
584 | set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin, | ||
585 | setting); | ||
586 | } | ||
587 | |||
471 | static struct at91_pinctrl_mux_ops at91rm9200_ops = { | 588 | static struct at91_pinctrl_mux_ops at91rm9200_ops = { |
472 | .get_periph = at91_mux_get_periph, | 589 | .get_periph = at91_mux_get_periph, |
473 | .mux_A_periph = at91_mux_set_A_periph, | 590 | .mux_A_periph = at91_mux_set_A_periph, |
@@ -491,6 +608,27 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = { | |||
491 | .set_pulldown = at91_mux_pio3_set_pulldown, | 608 | .set_pulldown = at91_mux_pio3_set_pulldown, |
492 | .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, | 609 | .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, |
493 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, | 610 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, |
611 | .get_drivestrength = at91_mux_sam9x5_get_drivestrength, | ||
612 | .set_drivestrength = at91_mux_sam9x5_set_drivestrength, | ||
613 | .irq_type = alt_gpio_irq_type, | ||
614 | }; | ||
615 | |||
616 | static struct at91_pinctrl_mux_ops sama5d3_ops = { | ||
617 | .get_periph = at91_mux_pio3_get_periph, | ||
618 | .mux_A_periph = at91_mux_pio3_set_A_periph, | ||
619 | .mux_B_periph = at91_mux_pio3_set_B_periph, | ||
620 | .mux_C_periph = at91_mux_pio3_set_C_periph, | ||
621 | .mux_D_periph = at91_mux_pio3_set_D_periph, | ||
622 | .get_deglitch = at91_mux_pio3_get_deglitch, | ||
623 | .set_deglitch = at91_mux_pio3_set_deglitch, | ||
624 | .get_debounce = at91_mux_pio3_get_debounce, | ||
625 | .set_debounce = at91_mux_pio3_set_debounce, | ||
626 | .get_pulldown = at91_mux_pio3_get_pulldown, | ||
627 | .set_pulldown = at91_mux_pio3_set_pulldown, | ||
628 | .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, | ||
629 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, | ||
630 | .get_drivestrength = at91_mux_sama5d3_get_drivestrength, | ||
631 | .set_drivestrength = at91_mux_sama5d3_set_drivestrength, | ||
494 | .irq_type = alt_gpio_irq_type, | 632 | .irq_type = alt_gpio_irq_type, |
495 | }; | 633 | }; |
496 | 634 | ||
@@ -716,6 +854,9 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, | |||
716 | *config |= PULL_DOWN; | 854 | *config |= PULL_DOWN; |
717 | if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin)) | 855 | if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin)) |
718 | *config |= DIS_SCHMIT; | 856 | *config |= DIS_SCHMIT; |
857 | if (info->ops->get_drivestrength) | ||
858 | *config |= (info->ops->get_drivestrength(pio, pin) | ||
859 | << DRIVE_STRENGTH_SHIFT); | ||
719 | 860 | ||
720 | return 0; | 861 | return 0; |
721 | } | 862 | } |
@@ -729,6 +870,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, | |||
729 | void __iomem *pio; | 870 | void __iomem *pio; |
730 | int i; | 871 | int i; |
731 | unsigned long config; | 872 | unsigned long config; |
873 | unsigned pin; | ||
732 | 874 | ||
733 | for (i = 0; i < num_configs; i++) { | 875 | for (i = 0; i < num_configs; i++) { |
734 | config = configs[i]; | 876 | config = configs[i]; |
@@ -737,7 +879,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, | |||
737 | "%s:%d, pin_id=%d, config=0x%lx", | 879 | "%s:%d, pin_id=%d, config=0x%lx", |
738 | __func__, __LINE__, pin_id, config); | 880 | __func__, __LINE__, pin_id, config); |
739 | pio = pin_to_controller(info, pin_to_bank(pin_id)); | 881 | pio = pin_to_controller(info, pin_to_bank(pin_id)); |
740 | mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK); | 882 | pin = pin_id % MAX_NB_GPIO_PER_BANK; |
883 | mask = pin_to_mask(pin); | ||
741 | 884 | ||
742 | if (config & PULL_UP && config & PULL_DOWN) | 885 | if (config & PULL_UP && config & PULL_DOWN) |
743 | return -EINVAL; | 886 | return -EINVAL; |
@@ -753,6 +896,10 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, | |||
753 | info->ops->set_pulldown(pio, mask, config & PULL_DOWN); | 896 | info->ops->set_pulldown(pio, mask, config & PULL_DOWN); |
754 | if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT) | 897 | if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT) |
755 | info->ops->disable_schmitt_trig(pio, mask); | 898 | info->ops->disable_schmitt_trig(pio, mask); |
899 | if (info->ops->set_drivestrength) | ||
900 | info->ops->set_drivestrength(pio, pin, | ||
901 | (config & DRIVE_STRENGTH) | ||
902 | >> DRIVE_STRENGTH_SHIFT); | ||
756 | 903 | ||
757 | } /* for each config */ | 904 | } /* for each config */ |
758 | 905 | ||
@@ -768,6 +915,15 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, | |||
768 | } \ | 915 | } \ |
769 | } while (0) | 916 | } while (0) |
770 | 917 | ||
918 | #define DBG_SHOW_FLAG_MASKED(mask,flag) do { \ | ||
919 | if ((config & mask) == flag) { \ | ||
920 | if (num_conf) \ | ||
921 | seq_puts(s, "|"); \ | ||
922 | seq_puts(s, #flag); \ | ||
923 | num_conf++; \ | ||
924 | } \ | ||
925 | } while (0) | ||
926 | |||
771 | static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, | 927 | static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, |
772 | struct seq_file *s, unsigned pin_id) | 928 | struct seq_file *s, unsigned pin_id) |
773 | { | 929 | { |
@@ -781,6 +937,9 @@ static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, | |||
781 | DBG_SHOW_FLAG(PULL_DOWN); | 937 | DBG_SHOW_FLAG(PULL_DOWN); |
782 | DBG_SHOW_FLAG(DIS_SCHMIT); | 938 | DBG_SHOW_FLAG(DIS_SCHMIT); |
783 | DBG_SHOW_FLAG(DEGLITCH); | 939 | DBG_SHOW_FLAG(DEGLITCH); |
940 | DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_LOW); | ||
941 | DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_MED); | ||
942 | DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_HI); | ||
784 | DBG_SHOW_FLAG(DEBOUNCE); | 943 | DBG_SHOW_FLAG(DEBOUNCE); |
785 | if (config & DEBOUNCE) { | 944 | if (config & DEBOUNCE) { |
786 | val = config >> DEBOUNCE_VAL_SHIFT; | 945 | val = config >> DEBOUNCE_VAL_SHIFT; |
@@ -945,6 +1104,7 @@ static int at91_pinctrl_parse_functions(struct device_node *np, | |||
945 | } | 1104 | } |
946 | 1105 | ||
947 | static struct of_device_id at91_pinctrl_of_match[] = { | 1106 | static struct of_device_id at91_pinctrl_of_match[] = { |
1107 | { .compatible = "atmel,sama5d3-pinctrl", .data = &sama5d3_ops }, | ||
948 | { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops }, | 1108 | { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops }, |
949 | { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops }, | 1109 | { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops }, |
950 | { /* sentinel */ } | 1110 | { /* sentinel */ } |