* pinctrl: at91: drive strength control
@ 2014-01-21 1:07 Marek Roszko
2014-01-21 2:19 ` Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 1 reply; 11+ messages in thread
From: Marek Roszko @ 2014-01-21 1:07 UTC (permalink / raw)
To: linux-arm-kernel
Hello Nick and Jean-Christophe,
I submit a idea/patch for comments. The current pintctrl driver is missing the ability to set the drive strength in the SAMA5D3s and a few of the SAM9s.
A little feature I myself need for the SAMA5D3s because somebody let an analog engineer do the hardware design.
Issues with this patch I need help with:
1. Atmel for some reason shifted the PIO_DRIVER1 and PIO_DRIVER2 registers by one register address between the SAM9 chips and the SAMA5D3s
i.e. this is the SAM9s
#define PIO_DRIVER1_V1 0x114
#define PIO_DRIVER2_V1 0x118
this is the SAMA5D3s
#define PIO_DRIVER1_V2 0x118
#define PIO_DRIVER2_V2 0x11C
2. Atmel changed the meaning of value of "low", "medium" and "high" drive strengths between the two sets of chips as well.
SAM9s do:
00 = high
01 = medium
10 = low
11 = reserved/undefined
SAMA5D3s do:
00 = low
01 = low
10 = medium
11 = high
3. The SAM9G25, SAM9G35 have the PIO_DRIVER but the SAM9G45 does not have the PIO_DRIVER register as an example of
how oddly the behavior doesn't appear everywhere. This could also be because the datasheets for the G45 and G46 are
not updated to the new style while the others already have been?
Side note: The SAMA5D3 datasheet says the default drive strength is "low" with register values 0x00000000,
in reality the default is "medium" with 0xAAAAAAAA as the default value.
Confirmed with the JLINK debugger and by Atmel support. Not an real issue, just a note when testing.
So the only simple way I see is to #ifdef the SOC type/chip.
There's probably better far better ways I don't know.
---
arch/arm/mach-at91/include/mach/at91_pio.h | 9 +++++
drivers/pinctrl/pinctrl-at91.c | 54 +++++++++++++++++++++++++++-
include/dt-bindings/pinctrl/at91.h | 13 +++++++
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
index 732b11c..28e8801 100644
--- a/arch/arm/mach-at91/include/mach/at91_pio.h
+++ b/arch/arm/mach-at91/include/mach/at91_pio.h
@@ -66,6 +66,15 @@
#define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
#define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
+/*
+ * SoC Specific PIO Address Offsets
+ */
+#define PIO_DRIVER1_V1 0x114
+#define PIO_DRIVER2_V1 0x118
+
+#define PIO_DRIVER1_V2 0x118
+#define PIO_DRIVER2_V2 0x11C
+
#define ABCDSR_PERIPH_A 0x0
#define ABCDSR_PERIPH_B 0x1
#define ABCDSR_PERIPH_C 0x2
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index a7549c4..ccf456e 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -62,10 +62,37 @@ static int gpio_banks;
#define DEGLITCH (1 << 2)
#define PULL_DOWN (1 << 3)
#define DIS_SCHMIT (1 << 4)
+#define SET_DRIVE_STRENGTH (1 << 5)
+#define DRIVE_STRENGTH_SHIFT 6
+#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
#define DEBOUNCE (1 << 16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
+#define DRIVE_STRENGTH_MASK 0x3
+
+#define NUM_PINS_PER_DRIVE_STRENGTH_REG 16
+
+#define TWO_BIT_PIN_TO_SHIFT(pin)\
+ (2*((pin >= NUM_PINS_PER_DRIVE_STRENGTH_REG) ? \
+ pin - NUM_PINS_PER_DRIVE_STRENGTH_REG : pin))
+
+#define TWO_BIT_PIN_TO_MASK(pin)\
+ (DRIVE_STRENGTH_MASK << TWO_BIT_PIN_TO_SHIFT(pin))
+
+#if defined(CONFIG_SOC_SAMA5D3)
+ #define PIO_DRIVER1 PIO_DRIVER1_V2 /* Drive Strength Register 1 */
+ #define PIO_DRIVER2 PIO_DRIVER2_V2 /* Drive Strength Register 2 */
+#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
+ #define PIO_DRIVER1 PIO_DRIVER1_V1 /* Drive Strength Register 1 */
+ #define PIO_DRIVER2 PIO_DRIVER2_V1 /* Drive Strength Register 2 */
+#endif
+
+#if defined(PIO_DRIVER1) && defined(PIO_DRIVER2)
+ #define PIO_DRIVER(pin)\
+ ((pin > NUM_PINS_PER_DRIVE_STRENGTH_REG-1) ? PIO_DRIVER2 : PIO_DRIVER1)
+#endif
+
/**
* struct at91_pmx_func - describes AT91 pinmux functions
* @name: the name of this specific function
@@ -148,6 +175,8 @@ struct at91_pinctrl_mux_ops {
void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
+ int (*get_drivestrength)(void __iomem *pio, unsigned pin);
+ void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
bool (*get_pulldown)(void __iomem *pio, unsigned pin);
void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
@@ -462,6 +491,20 @@ static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is
__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
}
+static int at91_mux_pio3_get_drivestrength(void __iomem *pio, unsigned pin)
+{
+ return (__raw_readl(pio + PIO_DRIVER(pin)) >> TWO_BIT_PIN_TO_SHIFT(pin)) & DRIVE_STRENGTH_MASK;
+}
+
+static void at91_mux_pio3_set_drivestrength(void __iomem *pio, unsigned pin, u32 strength)
+{
+ unsigned tmp = __raw_readl(pio + PIO_DRIVER(pin));
+ tmp &= ~TWO_BIT_PIN_TO_MASK(pin);
+ tmp |= strength << TWO_BIT_PIN_TO_SHIFT(pin);
+
+ __raw_writel(tmp, pio + PIO_DRIVER(pin));
+}
+
static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
{
__raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
@@ -491,6 +534,8 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
.set_deglitch = at91_mux_pio3_set_deglitch,
.get_debounce = at91_mux_pio3_get_debounce,
.set_debounce = at91_mux_pio3_set_debounce,
+ .get_drivestrength = at91_mux_pio3_get_drivestrength,
+ .set_drivestrength = at91_mux_pio3_set_drivestrength,
.get_pulldown = at91_mux_pio3_get_pulldown,
.set_pulldown = at91_mux_pio3_set_pulldown,
.get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
@@ -736,6 +781,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
*config |= DEGLITCH;
if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
*config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
+ if (info->ops->get_drivestrength)
+ *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin) << DRIVE_STRENGTH_SHIFT);
if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
*config |= PULL_DOWN;
if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
@@ -753,6 +800,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
void __iomem *pio;
int i;
unsigned long config;
+ unsigned pin;
for (i = 0; i < num_configs; i++) {
config = configs[i];
@@ -761,7 +809,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
"%s:%d, pin_id=%d, config=0x%lx",
__func__, __LINE__, pin_id, config);
pio = pin_to_controller(info, pin_to_bank(pin_id));
- mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+ pin = pin_id % MAX_NB_GPIO_PER_BANK;
+ mask = pin_to_mask(pin);
if (config & PULL_UP && config & PULL_DOWN)
return -EINVAL;
@@ -773,6 +822,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
if (info->ops->set_debounce)
info->ops->set_debounce(pio, mask, config & DEBOUNCE,
(config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+ if (info->ops->set_drivestrength && config & SET_DRIVE_STRENGTH)
+ info->ops->set_drivestrength(pio, pin,
+ (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
if (info->ops->set_pulldown)
info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
index 0fee6ff..78621a4 100644
--- a/include/dt-bindings/pinctrl/at91.h
+++ b/include/dt-bindings/pinctrl/at91.h
@@ -20,6 +20,19 @@
#define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
+#define AT91_PINCTRL_SET_DRIVE_STRENGTH (1 << 5)
+
+#if defined(CONFIG_SOC_SAMA5D3)
+ #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x2 << 6)
+ #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x1 << 6)
+ #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x0 << 6)
+#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
+ #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 6)
+ #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 6)
+ #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 6)
+#endif
+
+
#define AT91_PIOA 0
#define AT91_PIOB 1
#define AT91_PIOC 2
--
1.7.10.4
--
Mark
^ permalink raw reply related [flat|nested] 11+ messages in thread
* pinctrl: at91: drive strength control
2014-01-21 1:07 pinctrl: at91: drive strength control Marek Roszko
@ 2014-01-21 2:19 ` Jean-Christophe PLAGNIOL-VILLARD
2014-01-21 3:34 ` Mark Roszko
0 siblings, 1 reply; 11+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-01-21 2:19 UTC (permalink / raw)
To: linux-arm-kernel
On 20:07 Mon 20 Jan , Marek Roszko wrote:
> Hello Nick and Jean-Christophe,
>
> I submit a idea/patch for comments. The current pintctrl driver is missing the ability to set the drive strength in the SAMA5D3s and a few of the SAM9s.
> A little feature I myself need for the SAMA5D3s because somebody let an analog engineer do the hardware design.
>
> Issues with this patch I need help with:
> 1. Atmel for some reason shifted the PIO_DRIVER1 and PIO_DRIVER2 registers by one register address between the SAM9 chips and the SAMA5D3s
>
> i.e. this is the SAM9s
> #define PIO_DRIVER1_V1 0x114
> #define PIO_DRIVER2_V1 0x118
>
> this is the SAMA5D3s
> #define PIO_DRIVER1_V2 0x118
> #define PIO_DRIVER2_V2 0x11C
>
>
> 2. Atmel changed the meaning of value of "low", "medium" and "high" drive strengths between the two sets of chips as well.
>
> SAM9s do:
> 00 = high
> 01 = medium
> 10 = low
> 11 = reserved/undefined
>
> SAMA5D3s do:
> 00 = low
> 01 = low
> 10 = medium
> 11 = high
>
> 3. The SAM9G25, SAM9G35 have the PIO_DRIVER but the SAM9G45 does not have the PIO_DRIVER register as an example of
> how oddly the behavior doesn't appear everywhere. This could also be because the datasheets for the G45 and G46 are
> not updated to the new style while the others already have been?
>
> Side note: The SAMA5D3 datasheet says the default drive strength is "low" with register values 0x00000000,
> in reality the default is "medium" with 0xAAAAAAAA as the default value.
> Confirmed with the JLINK debugger and by Atmel support. Not an real issue, just a note when testing.
check the coding style tab for indentatnion, 80 charrs per line max etc...
>
>
> So the only simple way I see is to #ifdef the SOC type/chip.
> There's probably better far better ways I don't know.
>
> ---
> arch/arm/mach-at91/include/mach/at91_pio.h | 9 +++++
> drivers/pinctrl/pinctrl-at91.c | 54 +++++++++++++++++++++++++++-
> include/dt-bindings/pinctrl/at91.h | 13 +++++++
> 3 files changed, 75 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
> index 732b11c..28e8801 100644
> --- a/arch/arm/mach-at91/include/mach/at91_pio.h
> +++ b/arch/arm/mach-at91/include/mach/at91_pio.h
> @@ -66,6 +66,15 @@
> #define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
> #define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
>
> +/*
> + * SoC Specific PIO Address Offsets
> + */
> +#define PIO_DRIVER1_V1 0x114
> +#define PIO_DRIVER2_V1 0x118
> +
> +#define PIO_DRIVER1_V2 0x118
> +#define PIO_DRIVER2_V2 0x11C
> +
> #define ABCDSR_PERIPH_A 0x0
> #define ABCDSR_PERIPH_B 0x1
> #define ABCDSR_PERIPH_C 0x2
> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
> index a7549c4..ccf456e 100644
> --- a/drivers/pinctrl/pinctrl-at91.c
> +++ b/drivers/pinctrl/pinctrl-at91.c
> @@ -62,10 +62,37 @@ static int gpio_banks;
> #define DEGLITCH (1 << 2)
> #define PULL_DOWN (1 << 3)
> #define DIS_SCHMIT (1 << 4)
> +#define SET_DRIVE_STRENGTH (1 << 5)
> +#define DRIVE_STRENGTH_SHIFT 6
> +#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
> #define DEBOUNCE (1 << 16)
> #define DEBOUNCE_VAL_SHIFT 17
> #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
>
> +#define DRIVE_STRENGTH_MASK 0x3
> +
> +#define NUM_PINS_PER_DRIVE_STRENGTH_REG 16
> +
> +#define TWO_BIT_PIN_TO_SHIFT(pin)\
> + (2*((pin >= NUM_PINS_PER_DRIVE_STRENGTH_REG) ? \
> + pin - NUM_PINS_PER_DRIVE_STRENGTH_REG : pin))
> +
> +#define TWO_BIT_PIN_TO_MASK(pin)\
> + (DRIVE_STRENGTH_MASK << TWO_BIT_PIN_TO_SHIFT(pin))
> +
> +#if defined(CONFIG_SOC_SAMA5D3)
> + #define PIO_DRIVER1 PIO_DRIVER1_V2 /* Drive Strength Register 1 */
> + #define PIO_DRIVER2 PIO_DRIVER2_V2 /* Drive Strength Register 2 */
> +#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
> + #define PIO_DRIVER1 PIO_DRIVER1_V1 /* Drive Strength Register 1 */
> + #define PIO_DRIVER2 PIO_DRIVER2_V1 /* Drive Strength Register 2 */
> +#endif
no ifdef this is choose at runtime
> +
> +#if defined(PIO_DRIVER1) && defined(PIO_DRIVER2)
> + #define PIO_DRIVER(pin)\
> + ((pin > NUM_PINS_PER_DRIVE_STRENGTH_REG-1) ? PIO_DRIVER2 : PIO_DRIVER1)
> +#endif
use inline function
> +
> /**
> * struct at91_pmx_func - describes AT91 pinmux functions
> * @name: the name of this specific function
> @@ -148,6 +175,8 @@ struct at91_pinctrl_mux_ops {
> void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
> bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
> void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
> + int (*get_drivestrength)(void __iomem *pio, unsigned pin);
> + void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
> bool (*get_pulldown)(void __iomem *pio, unsigned pin);
> void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
> bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
> @@ -462,6 +491,20 @@ static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is
> __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
> }
>
> +static int at91_mux_pio3_get_drivestrength(void __iomem *pio, unsigned pin)
> +{
> + return (__raw_readl(pio + PIO_DRIVER(pin)) >> TWO_BIT_PIN_TO_SHIFT(pin)) & DRIVE_STRENGTH_MASK;
> +}
> +
> +static void at91_mux_pio3_set_drivestrength(void __iomem *pio, unsigned pin, u32 strength)
> +{
> + unsigned tmp = __raw_readl(pio + PIO_DRIVER(pin));
> + tmp &= ~TWO_BIT_PIN_TO_MASK(pin);
> + tmp |= strength << TWO_BIT_PIN_TO_SHIFT(pin);
> +
> + __raw_writel(tmp, pio + PIO_DRIVER(pin));
> +}
> +
> static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
> {
> __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
> @@ -491,6 +534,8 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> .set_deglitch = at91_mux_pio3_set_deglitch,
> .get_debounce = at91_mux_pio3_get_debounce,
> .set_debounce = at91_mux_pio3_set_debounce,
> + .get_drivestrength = at91_mux_pio3_get_drivestrength,
> + .set_drivestrength = at91_mux_pio3_set_drivestrength,
> .get_pulldown = at91_mux_pio3_get_pulldown,
> .set_pulldown = at91_mux_pio3_set_pulldown,
> .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> @@ -736,6 +781,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
> *config |= DEGLITCH;
> if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
> *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
> + if (info->ops->get_drivestrength)
> + *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin) << DRIVE_STRENGTH_SHIFT);
> if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
> *config |= PULL_DOWN;
> if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
> @@ -753,6 +800,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> void __iomem *pio;
> int i;
> unsigned long config;
> + unsigned pin;
>
> for (i = 0; i < num_configs; i++) {
> config = configs[i];
> @@ -761,7 +809,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> "%s:%d, pin_id=%d, config=0x%lx",
> __func__, __LINE__, pin_id, config);
> pio = pin_to_controller(info, pin_to_bank(pin_id));
> - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
> + pin = pin_id % MAX_NB_GPIO_PER_BANK;
> + mask = pin_to_mask(pin);
>
> if (config & PULL_UP && config & PULL_DOWN)
> return -EINVAL;
> @@ -773,6 +822,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> if (info->ops->set_debounce)
> info->ops->set_debounce(pio, mask, config & DEBOUNCE,
> (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
> + if (info->ops->set_drivestrength && config & SET_DRIVE_STRENGTH)
> + info->ops->set_drivestrength(pio, pin,
> + (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
> if (info->ops->set_pulldown)
> info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
> if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
> diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
> index 0fee6ff..78621a4 100644
> --- a/include/dt-bindings/pinctrl/at91.h
> +++ b/include/dt-bindings/pinctrl/at91.h
> @@ -20,6 +20,19 @@
>
> #define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
>
> +#define AT91_PINCTRL_SET_DRIVE_STRENGTH (1 << 5)
> +
> +#if defined(CONFIG_SOC_SAMA5D3)
> + #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x2 << 6)
> + #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x1 << 6)
> + #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x0 << 6)
> +#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
> + #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 6)
> + #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 6)
> + #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 6)
> +#endif
no only one binding we do not care of the IP details
0 means no drive strength specified
> +
> +
> #define AT91_PIOA 0
> #define AT91_PIOB 1
> #define AT91_PIOC 2
> --
> 1.7.10.4
>
>
>
>
> --
> Mark
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* pinctrl: at91: drive strength control
2014-01-21 2:19 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2014-01-21 3:34 ` Mark Roszko
2014-01-21 4:09 ` Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 1 reply; 11+ messages in thread
From: Mark Roszko @ 2014-01-21 3:34 UTC (permalink / raw)
To: linux-arm-kernel
If I choose it at runtime what's the best way for me to detect the SoC
type to choose the correct register address at runtime? Only way I see
is adding new compatible types for the SAMA5s and the SAM9s with the
registers.
On Mon, Jan 20, 2014 at 9:19 PM, Jean-Christophe PLAGNIOL-VILLARD
<plagnioj@jcrosoft.com> wrote:
> On 20:07 Mon 20 Jan , Marek Roszko wrote:
>> Hello Nick and Jean-Christophe,
>>
>> I submit a idea/patch for comments. The current pintctrl driver is missing the ability to set the drive strength in the SAMA5D3s and a few of the SAM9s.
>> A little feature I myself need for the SAMA5D3s because somebody let an analog engineer do the hardware design.
>>
>> Issues with this patch I need help with:
>> 1. Atmel for some reason shifted the PIO_DRIVER1 and PIO_DRIVER2 registers by one register address between the SAM9 chips and the SAMA5D3s
>>
>> i.e. this is the SAM9s
>> #define PIO_DRIVER1_V1 0x114
>> #define PIO_DRIVER2_V1 0x118
>>
>> this is the SAMA5D3s
>> #define PIO_DRIVER1_V2 0x118
>> #define PIO_DRIVER2_V2 0x11C
>>
>>
>> 2. Atmel changed the meaning of value of "low", "medium" and "high" drive strengths between the two sets of chips as well.
>>
>> SAM9s do:
>> 00 = high
>> 01 = medium
>> 10 = low
>> 11 = reserved/undefined
>>
>> SAMA5D3s do:
>> 00 = low
>> 01 = low
>> 10 = medium
>> 11 = high
>>
>> 3. The SAM9G25, SAM9G35 have the PIO_DRIVER but the SAM9G45 does not have the PIO_DRIVER register as an example of
>> how oddly the behavior doesn't appear everywhere. This could also be because the datasheets for the G45 and G46 are
>> not updated to the new style while the others already have been?
>>
>> Side note: The SAMA5D3 datasheet says the default drive strength is "low" with register values 0x00000000,
>> in reality the default is "medium" with 0xAAAAAAAA as the default value.
>> Confirmed with the JLINK debugger and by Atmel support. Not an real issue, just a note when testing.
>
> check the coding style tab for indentatnion, 80 charrs per line max etc...
>>
>>
>> So the only simple way I see is to #ifdef the SOC type/chip.
>> There's probably better far better ways I don't know.
>>
>> ---
>> arch/arm/mach-at91/include/mach/at91_pio.h | 9 +++++
>> drivers/pinctrl/pinctrl-at91.c | 54 +++++++++++++++++++++++++++-
>> include/dt-bindings/pinctrl/at91.h | 13 +++++++
>> 3 files changed, 75 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
>> index 732b11c..28e8801 100644
>> --- a/arch/arm/mach-at91/include/mach/at91_pio.h
>> +++ b/arch/arm/mach-at91/include/mach/at91_pio.h
>> @@ -66,6 +66,15 @@
>> #define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
>> #define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
>>
>> +/*
>> + * SoC Specific PIO Address Offsets
>> + */
>> +#define PIO_DRIVER1_V1 0x114
>> +#define PIO_DRIVER2_V1 0x118
>> +
>> +#define PIO_DRIVER1_V2 0x118
>> +#define PIO_DRIVER2_V2 0x11C
>> +
>> #define ABCDSR_PERIPH_A 0x0
>> #define ABCDSR_PERIPH_B 0x1
>> #define ABCDSR_PERIPH_C 0x2
>> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
>> index a7549c4..ccf456e 100644
>> --- a/drivers/pinctrl/pinctrl-at91.c
>> +++ b/drivers/pinctrl/pinctrl-at91.c
>> @@ -62,10 +62,37 @@ static int gpio_banks;
>> #define DEGLITCH (1 << 2)
>> #define PULL_DOWN (1 << 3)
>> #define DIS_SCHMIT (1 << 4)
>> +#define SET_DRIVE_STRENGTH (1 << 5)
>> +#define DRIVE_STRENGTH_SHIFT 6
>> +#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
>> #define DEBOUNCE (1 << 16)
>> #define DEBOUNCE_VAL_SHIFT 17
>> #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
>>
>> +#define DRIVE_STRENGTH_MASK 0x3
>> +
>> +#define NUM_PINS_PER_DRIVE_STRENGTH_REG 16
>> +
>> +#define TWO_BIT_PIN_TO_SHIFT(pin)\
>> + (2*((pin >= NUM_PINS_PER_DRIVE_STRENGTH_REG) ? \
>> + pin - NUM_PINS_PER_DRIVE_STRENGTH_REG : pin))
>
>> +
>> +#define TWO_BIT_PIN_TO_MASK(pin)\
>> + (DRIVE_STRENGTH_MASK << TWO_BIT_PIN_TO_SHIFT(pin))
>> +
>> +#if defined(CONFIG_SOC_SAMA5D3)
>> + #define PIO_DRIVER1 PIO_DRIVER1_V2 /* Drive Strength Register 1 */
>> + #define PIO_DRIVER2 PIO_DRIVER2_V2 /* Drive Strength Register 2 */
>> +#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
>> + #define PIO_DRIVER1 PIO_DRIVER1_V1 /* Drive Strength Register 1 */
>> + #define PIO_DRIVER2 PIO_DRIVER2_V1 /* Drive Strength Register 2 */
>> +#endif
> no ifdef this is choose at runtime
>> +
>> +#if defined(PIO_DRIVER1) && defined(PIO_DRIVER2)
>> + #define PIO_DRIVER(pin)\
>> + ((pin > NUM_PINS_PER_DRIVE_STRENGTH_REG-1) ? PIO_DRIVER2 : PIO_DRIVER1)
>> +#endif
> use inline function
>> +
>> /**
>> * struct at91_pmx_func - describes AT91 pinmux functions
>> * @name: the name of this specific function
>> @@ -148,6 +175,8 @@ struct at91_pinctrl_mux_ops {
>> void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
>> bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
>> void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
>> + int (*get_drivestrength)(void __iomem *pio, unsigned pin);
>> + void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
>> bool (*get_pulldown)(void __iomem *pio, unsigned pin);
>> void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
>> bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
>> @@ -462,6 +491,20 @@ static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is
>> __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
>> }
>>
>> +static int at91_mux_pio3_get_drivestrength(void __iomem *pio, unsigned pin)
>> +{
>> + return (__raw_readl(pio + PIO_DRIVER(pin)) >> TWO_BIT_PIN_TO_SHIFT(pin)) & DRIVE_STRENGTH_MASK;
>> +}
>> +
>> +static void at91_mux_pio3_set_drivestrength(void __iomem *pio, unsigned pin, u32 strength)
>> +{
>> + unsigned tmp = __raw_readl(pio + PIO_DRIVER(pin));
>> + tmp &= ~TWO_BIT_PIN_TO_MASK(pin);
>> + tmp |= strength << TWO_BIT_PIN_TO_SHIFT(pin);
>> +
>> + __raw_writel(tmp, pio + PIO_DRIVER(pin));
>> +}
>> +
>> static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
>> {
>> __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
>> @@ -491,6 +534,8 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
>> .set_deglitch = at91_mux_pio3_set_deglitch,
>> .get_debounce = at91_mux_pio3_get_debounce,
>> .set_debounce = at91_mux_pio3_set_debounce,
>> + .get_drivestrength = at91_mux_pio3_get_drivestrength,
>> + .set_drivestrength = at91_mux_pio3_set_drivestrength,
>> .get_pulldown = at91_mux_pio3_get_pulldown,
>> .set_pulldown = at91_mux_pio3_set_pulldown,
>> .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
>> @@ -736,6 +781,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
>> *config |= DEGLITCH;
>> if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
>> *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
>> + if (info->ops->get_drivestrength)
>> + *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin) << DRIVE_STRENGTH_SHIFT);
>> if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
>> *config |= PULL_DOWN;
>> if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
>> @@ -753,6 +800,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
>> void __iomem *pio;
>> int i;
>> unsigned long config;
>> + unsigned pin;
>>
>> for (i = 0; i < num_configs; i++) {
>> config = configs[i];
>> @@ -761,7 +809,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
>> "%s:%d, pin_id=%d, config=0x%lx",
>> __func__, __LINE__, pin_id, config);
>> pio = pin_to_controller(info, pin_to_bank(pin_id));
>> - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
>> + pin = pin_id % MAX_NB_GPIO_PER_BANK;
>> + mask = pin_to_mask(pin);
>>
>> if (config & PULL_UP && config & PULL_DOWN)
>> return -EINVAL;
>> @@ -773,6 +822,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
>> if (info->ops->set_debounce)
>> info->ops->set_debounce(pio, mask, config & DEBOUNCE,
>> (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
>> + if (info->ops->set_drivestrength && config & SET_DRIVE_STRENGTH)
>> + info->ops->set_drivestrength(pio, pin,
>> + (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
>> if (info->ops->set_pulldown)
>> info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
>> if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
>> diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
>> index 0fee6ff..78621a4 100644
>> --- a/include/dt-bindings/pinctrl/at91.h
>> +++ b/include/dt-bindings/pinctrl/at91.h
>> @@ -20,6 +20,19 @@
>>
>> #define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
>>
>> +#define AT91_PINCTRL_SET_DRIVE_STRENGTH (1 << 5)
>> +
>> +#if defined(CONFIG_SOC_SAMA5D3)
>> + #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x2 << 6)
>> + #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x1 << 6)
>> + #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x0 << 6)
>> +#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
>> + #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 6)
>> + #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 6)
>> + #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 6)
>> +#endif
>
> no only one binding we do not care of the IP details
>
> 0 means no drive strength specified
>> +
>> +
>> #define AT91_PIOA 0
>> #define AT91_PIOB 1
>> #define AT91_PIOC 2
>> --
>> 1.7.10.4
>>
>>
>>
>>
>> --
>> Mark
>>
>>
--
Mark
^ permalink raw reply [flat|nested] 11+ messages in thread
* pinctrl: at91: drive strength control
2014-01-21 3:34 ` Mark Roszko
@ 2014-01-21 4:09 ` Jean-Christophe PLAGNIOL-VILLARD
2014-01-21 5:52 ` Marek Roszko
0 siblings, 1 reply; 11+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-01-21 4:09 UTC (permalink / raw)
To: linux-arm-kernel
On 22:34 Mon 20 Jan , Mark Roszko wrote:
> If I choose it at runtime what's the best way for me to detect the SoC
> type to choose the correct register address at runtime? Only way I see
> is adding new compatible types for the SAMA5s and the SAM9s with the
> registers.
>
we could do it via cpu_is as a check as we may have older dts
but it's better to do it via compatible
> On Mon, Jan 20, 2014 at 9:19 PM, Jean-Christophe PLAGNIOL-VILLARD
> <plagnioj@jcrosoft.com> wrote:
> > On 20:07 Mon 20 Jan , Marek Roszko wrote:
> >> Hello Nick and Jean-Christophe,
> >>
> >> I submit a idea/patch for comments. The current pintctrl driver is missing the ability to set the drive strength in the SAMA5D3s and a few of the SAM9s.
> >> A little feature I myself need for the SAMA5D3s because somebody let an analog engineer do the hardware design.
> >>
> >> Issues with this patch I need help with:
> >> 1. Atmel for some reason shifted the PIO_DRIVER1 and PIO_DRIVER2 registers by one register address between the SAM9 chips and the SAMA5D3s
> >>
> >> i.e. this is the SAM9s
> >> #define PIO_DRIVER1_V1 0x114
> >> #define PIO_DRIVER2_V1 0x118
> >>
> >> this is the SAMA5D3s
> >> #define PIO_DRIVER1_V2 0x118
> >> #define PIO_DRIVER2_V2 0x11C
> >>
> >>
> >> 2. Atmel changed the meaning of value of "low", "medium" and "high" drive strengths between the two sets of chips as well.
> >>
> >> SAM9s do:
> >> 00 = high
> >> 01 = medium
> >> 10 = low
> >> 11 = reserved/undefined
> >>
> >> SAMA5D3s do:
> >> 00 = low
> >> 01 = low
> >> 10 = medium
> >> 11 = high
> >>
> >> 3. The SAM9G25, SAM9G35 have the PIO_DRIVER but the SAM9G45 does not have the PIO_DRIVER register as an example of
> >> how oddly the behavior doesn't appear everywhere. This could also be because the datasheets for the G45 and G46 are
> >> not updated to the new style while the others already have been?
> >>
> >> Side note: The SAMA5D3 datasheet says the default drive strength is "low" with register values 0x00000000,
> >> in reality the default is "medium" with 0xAAAAAAAA as the default value.
> >> Confirmed with the JLINK debugger and by Atmel support. Not an real issue, just a note when testing.
> >
> > check the coding style tab for indentatnion, 80 charrs per line max etc...
> >>
> >>
> >> So the only simple way I see is to #ifdef the SOC type/chip.
> >> There's probably better far better ways I don't know.
> >>
> >> ---
> >> arch/arm/mach-at91/include/mach/at91_pio.h | 9 +++++
> >> drivers/pinctrl/pinctrl-at91.c | 54 +++++++++++++++++++++++++++-
> >> include/dt-bindings/pinctrl/at91.h | 13 +++++++
> >> 3 files changed, 75 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
> >> index 732b11c..28e8801 100644
> >> --- a/arch/arm/mach-at91/include/mach/at91_pio.h
> >> +++ b/arch/arm/mach-at91/include/mach/at91_pio.h
> >> @@ -66,6 +66,15 @@
> >> #define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
> >> #define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
> >>
> >> +/*
> >> + * SoC Specific PIO Address Offsets
> >> + */
> >> +#define PIO_DRIVER1_V1 0x114
> >> +#define PIO_DRIVER2_V1 0x118
> >> +
> >> +#define PIO_DRIVER1_V2 0x118
> >> +#define PIO_DRIVER2_V2 0x11C
> >> +
> >> #define ABCDSR_PERIPH_A 0x0
> >> #define ABCDSR_PERIPH_B 0x1
> >> #define ABCDSR_PERIPH_C 0x2
> >> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
> >> index a7549c4..ccf456e 100644
> >> --- a/drivers/pinctrl/pinctrl-at91.c
> >> +++ b/drivers/pinctrl/pinctrl-at91.c
> >> @@ -62,10 +62,37 @@ static int gpio_banks;
> >> #define DEGLITCH (1 << 2)
> >> #define PULL_DOWN (1 << 3)
> >> #define DIS_SCHMIT (1 << 4)
> >> +#define SET_DRIVE_STRENGTH (1 << 5)
> >> +#define DRIVE_STRENGTH_SHIFT 6
> >> +#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
> >> #define DEBOUNCE (1 << 16)
> >> #define DEBOUNCE_VAL_SHIFT 17
> >> #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
> >>
> >> +#define DRIVE_STRENGTH_MASK 0x3
> >> +
> >> +#define NUM_PINS_PER_DRIVE_STRENGTH_REG 16
> >> +
> >> +#define TWO_BIT_PIN_TO_SHIFT(pin)\
> >> + (2*((pin >= NUM_PINS_PER_DRIVE_STRENGTH_REG) ? \
> >> + pin - NUM_PINS_PER_DRIVE_STRENGTH_REG : pin))
> >
> >> +
> >> +#define TWO_BIT_PIN_TO_MASK(pin)\
> >> + (DRIVE_STRENGTH_MASK << TWO_BIT_PIN_TO_SHIFT(pin))
> >> +
> >> +#if defined(CONFIG_SOC_SAMA5D3)
> >> + #define PIO_DRIVER1 PIO_DRIVER1_V2 /* Drive Strength Register 1 */
> >> + #define PIO_DRIVER2 PIO_DRIVER2_V2 /* Drive Strength Register 2 */
> >> +#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
> >> + #define PIO_DRIVER1 PIO_DRIVER1_V1 /* Drive Strength Register 1 */
> >> + #define PIO_DRIVER2 PIO_DRIVER2_V1 /* Drive Strength Register 2 */
> >> +#endif
> > no ifdef this is choose at runtime
> >> +
> >> +#if defined(PIO_DRIVER1) && defined(PIO_DRIVER2)
> >> + #define PIO_DRIVER(pin)\
> >> + ((pin > NUM_PINS_PER_DRIVE_STRENGTH_REG-1) ? PIO_DRIVER2 : PIO_DRIVER1)
> >> +#endif
> > use inline function
> >> +
> >> /**
> >> * struct at91_pmx_func - describes AT91 pinmux functions
> >> * @name: the name of this specific function
> >> @@ -148,6 +175,8 @@ struct at91_pinctrl_mux_ops {
> >> void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
> >> bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
> >> void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
> >> + int (*get_drivestrength)(void __iomem *pio, unsigned pin);
> >> + void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
> >> bool (*get_pulldown)(void __iomem *pio, unsigned pin);
> >> void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
> >> bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
> >> @@ -462,6 +491,20 @@ static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is
> >> __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
> >> }
> >>
> >> +static int at91_mux_pio3_get_drivestrength(void __iomem *pio, unsigned pin)
> >> +{
> >> + return (__raw_readl(pio + PIO_DRIVER(pin)) >> TWO_BIT_PIN_TO_SHIFT(pin)) & DRIVE_STRENGTH_MASK;
> >> +}
> >> +
> >> +static void at91_mux_pio3_set_drivestrength(void __iomem *pio, unsigned pin, u32 strength)
> >> +{
> >> + unsigned tmp = __raw_readl(pio + PIO_DRIVER(pin));
> >> + tmp &= ~TWO_BIT_PIN_TO_MASK(pin);
> >> + tmp |= strength << TWO_BIT_PIN_TO_SHIFT(pin);
> >> +
> >> + __raw_writel(tmp, pio + PIO_DRIVER(pin));
> >> +}
> >> +
> >> static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
> >> {
> >> __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
> >> @@ -491,6 +534,8 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> >> .set_deglitch = at91_mux_pio3_set_deglitch,
> >> .get_debounce = at91_mux_pio3_get_debounce,
> >> .set_debounce = at91_mux_pio3_set_debounce,
> >> + .get_drivestrength = at91_mux_pio3_get_drivestrength,
> >> + .set_drivestrength = at91_mux_pio3_set_drivestrength,
> >> .get_pulldown = at91_mux_pio3_get_pulldown,
> >> .set_pulldown = at91_mux_pio3_set_pulldown,
> >> .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> >> @@ -736,6 +781,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
> >> *config |= DEGLITCH;
> >> if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
> >> *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
> >> + if (info->ops->get_drivestrength)
> >> + *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin) << DRIVE_STRENGTH_SHIFT);
> >> if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
> >> *config |= PULL_DOWN;
> >> if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
> >> @@ -753,6 +800,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> >> void __iomem *pio;
> >> int i;
> >> unsigned long config;
> >> + unsigned pin;
> >>
> >> for (i = 0; i < num_configs; i++) {
> >> config = configs[i];
> >> @@ -761,7 +809,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> >> "%s:%d, pin_id=%d, config=0x%lx",
> >> __func__, __LINE__, pin_id, config);
> >> pio = pin_to_controller(info, pin_to_bank(pin_id));
> >> - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
> >> + pin = pin_id % MAX_NB_GPIO_PER_BANK;
> >> + mask = pin_to_mask(pin);
> >>
> >> if (config & PULL_UP && config & PULL_DOWN)
> >> return -EINVAL;
> >> @@ -773,6 +822,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> >> if (info->ops->set_debounce)
> >> info->ops->set_debounce(pio, mask, config & DEBOUNCE,
> >> (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
> >> + if (info->ops->set_drivestrength && config & SET_DRIVE_STRENGTH)
> >> + info->ops->set_drivestrength(pio, pin,
> >> + (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
> >> if (info->ops->set_pulldown)
> >> info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
> >> if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
> >> diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
> >> index 0fee6ff..78621a4 100644
> >> --- a/include/dt-bindings/pinctrl/at91.h
> >> +++ b/include/dt-bindings/pinctrl/at91.h
> >> @@ -20,6 +20,19 @@
> >>
> >> #define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
> >>
> >> +#define AT91_PINCTRL_SET_DRIVE_STRENGTH (1 << 5)
> >> +
> >> +#if defined(CONFIG_SOC_SAMA5D3)
> >> + #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x2 << 6)
> >> + #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x1 << 6)
> >> + #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x0 << 6)
> >> +#elif defined(CONFIG_SOC_AT91SAM9X5) || defined(SOC_AT91SAM9G35) || defined(SOC_AT91SAM9G25)
> >> + #define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 6)
> >> + #define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 6)
> >> + #define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 6)
> >> +#endif
> >
> > no only one binding we do not care of the IP details
> >
> > 0 means no drive strength specified
> >> +
> >> +
> >> #define AT91_PIOA 0
> >> #define AT91_PIOB 1
> >> #define AT91_PIOC 2
> >> --
> >> 1.7.10.4
> >>
> >>
> >>
> >>
> >> --
> >> Mark
> >>
> >>
>
>
>
> --
> Mark
^ permalink raw reply [flat|nested] 11+ messages in thread
* pinctrl: at91: drive strength control
2014-01-21 4:09 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2014-01-21 5:52 ` Marek Roszko
2014-01-21 6:06 ` Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 1 reply; 11+ messages in thread
From: Marek Roszko @ 2014-01-21 5:52 UTC (permalink / raw)
To: linux-arm-kernel
Alright, added a SAMA5D3 compatible type and gave it's own drive
strength ops. Moved the defines to inline funcs. Made the bindings
independent of soc.
Hopefully tabs appear this time, I haven't figured out the whole mailing
list - email client thing and finding a client that doesn't convert
spaces/tabs is hard.
---
arch/arm/mach-at91/include/mach/at91sam9x5.h | 3 +
arch/arm/mach-at91/include/mach/sama5d3.h | 3 +
drivers/pinctrl/pinctrl-at91.c | 123
+++++++++++++++++++++++++-
include/dt-bindings/pinctrl/at91.h | 5 ++
4 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h
b/arch/arm/mach-at91/include/mach/at91sam9x5.h
index 2fc76c4..2efeb0a 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9x5.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h
@@ -59,6 +59,9 @@
*/
#define AT91SAM9X5_BASE_RTC 0xfffffeb0
+#define AT91SAM9X5_PIO_DRIVER1 0x114 /*PIO Driver 1 register offset*/
+#define AT91SAM9X5_PIO_DRIVER2 0x118 /*PIO Driver 2 register offset*/
+
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h
b/arch/arm/mach-at91/include/mach/sama5d3.h
index 25613d8..5d434f9 100644
--- a/arch/arm/mach-at91/include/mach/sama5d3.h
+++ b/arch/arm/mach-at91/include/mach/sama5d3.h
@@ -77,6 +77,9 @@
*/
#define SAMA5D3_BASE_RTC 0xfffffeb0
+#define SAMA5D3_PIO_DRIVER1 0x118 /*PIO Driver 1 register offset*/
+#define SAMA5D3_PIO_DRIVER2 0x11C /*PIO Driver 2 register offset*/
+
/*
* Internal Memory
*/
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index a7549c4..984c3be 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -62,10 +62,21 @@ static int gpio_banks;
#define DEGLITCH (1 << 2)
#define PULL_DOWN (1 << 3)
#define DIS_SCHMIT (1 << 4)
+#define DRIVE_STRENGTH_SHIFT 5
+#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
#define DEBOUNCE (1 << 16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
+#define DRIVE_STRENGTH_DEFAULT (0x0 << 5)
+#define DRIVE_STRENGTH_LOW (0x1 << 5)
+#define DRIVE_STRENGTH_MED (0x2 << 5)
+#define DRIVE_STRENGTH_HI (0x3 << 5)
+
+
+#define DRIVE_STRENGTH_MASK 0x3
+#define NUM_PINS_PER_DIVIDED_REGS 16
+
/**
* struct at91_pmx_func - describes AT91 pinmux functions
* @name: the name of this specific function
@@ -148,6 +159,8 @@ struct at91_pinctrl_mux_ops {
void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32
div);
+ unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin);
+ void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
bool (*get_pulldown)(void __iomem *pio, unsigned pin);
void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
@@ -319,6 +332,22 @@ static unsigned pin_to_mask(unsigned int pin)
return 1 << pin;
}?
+static inline int two_bit_pin_value_shift(unsigned pin)
+{
+ return 2*((pin >= NUM_PINS_PER_DIVIDED_REGS) ? pin -
NUM_PINS_PER_DIVIDED_REGS : pin);
+}
+
+
+static unsigned sama5d3_get_drive_register(unsigned int pin)
+{
+ return (pin > NUM_PINS_PER_DIVIDED_REGS-1) ? SAMA5D3_PIO_DRIVER2 :
SAMA5D3_PIO_DRIVER1;
+}
+
+static unsigned at91sam9x5_get_drive_register(unsigned int pin)
+{
+ return (pin > NUM_PINS_PER_DIVIDED_REGS-1) ? AT91SAM9X5_PIO_DRIVER2 :
AT91SAM9X5_PIO_DRIVER1;
+}
+
static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
{
writel_relaxed(mask, pio + PIO_IDR);
@@ -462,6 +491,67 @@ static void at91_mux_pio3_set_pulldown(void __iomem
*pio, unsigned mask, bool is
__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
}?
+static inline u32 read_drive_strength(void __iomem *reg, unsigned pin)
+{
+ return (__raw_readl(reg)
+ >> two_bit_pin_value_shift(pin)) & DRIVE_STRENGTH_MASK;
+}
+
+static unsigned at91_mux_sama5d3_get_drivestrength(void __iomem *pio,
unsigned pin)
+{
+ unsigned tmp = read_drive_strength(pio +
sama5d3_get_drive_register(pin), pin);
+
+ if (!tmp)
+ tmp = DRIVE_STRENGTH_LOW;
+
+ return tmp;
+}
+
+static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio,
unsigned pin)
+{
+ unsigned tmp = read_drive_strength(pio +
at91sam9x5_get_drive_register(pin), pin);
+
+ /*inverse settings*/
+ tmp = DRIVE_STRENGTH_HI - tmp;
+
+ return tmp;
+}
+
+static void set_drive_strength(void __iomem *reg, unsigned pin, u32
strength)
+{
+ unsigned tmp = __raw_readl(reg);
+
+ tmp &= ~(DRIVE_STRENGTH_MASK << two_bit_pin_value_shift(pin));
+ tmp |= strength << two_bit_pin_value_shift(pin);
+
+ __raw_writel(tmp, reg);
+}
+
+static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio,
unsigned pin,
+ u32 setting)
+{
+ /* do nothing if setting is zero */
+ if (!setting)
+ return;
+
+ /* strength is 1 to 1 with setting for SAMA5 */
+ set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting);
+}
+
+static void at91_mux_sam9x5_set_drivestrength(void __iomem *pio,
unsigned pin,
+ u32 setting)
+{
+ /* do nothing if setting is zero */
+ if (!setting)
+ return;
+
+ /* strength is inverse on SAM9s, 0 = hi, 1 = med, 2 = low, 3 = rsvd */
+ setting = DRIVE_STRENGTH_HI - setting;
+
+ set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin,
setting);
+}
+
+
static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio,
unsigned mask)
{
__raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
@@ -491,6 +581,8 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
.set_deglitch = at91_mux_pio3_set_deglitch,
.get_debounce = at91_mux_pio3_get_debounce,
.set_debounce = at91_mux_pio3_set_debounce,
+ .get_drivestrength = at91_mux_sam9x5_get_drivestrength,
+ .set_drivestrength = at91_mux_sam9x5_set_drivestrength,
.get_pulldown = at91_mux_pio3_get_pulldown,
.set_pulldown = at91_mux_pio3_set_pulldown,
.get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
@@ -498,6 +590,26 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
.irq_type = alt_gpio_irq_type,
};
+static struct at91_pinctrl_mux_ops sama5d3_ops = {
+ .get_periph = at91_mux_pio3_get_periph,
+ .mux_A_periph = at91_mux_pio3_set_A_periph,
+ .mux_B_periph = at91_mux_pio3_set_B_periph,
+ .mux_C_periph = at91_mux_pio3_set_C_periph,
+ .mux_D_periph = at91_mux_pio3_set_D_periph,
+ .get_deglitch = at91_mux_pio3_get_deglitch,
+ .set_deglitch = at91_mux_pio3_set_deglitch,
+ .get_debounce = at91_mux_pio3_get_debounce,
+ .set_debounce = at91_mux_pio3_set_debounce,
+ .get_drivestrength = at91_mux_sama5d3_get_drivestrength,
+ .set_drivestrength = at91_mux_sama5d3_set_drivestrength,
+ .get_pulldown = at91_mux_pio3_get_pulldown,
+ .set_pulldown = at91_mux_pio3_set_pulldown,
+ .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+ .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+ .irq_type = alt_gpio_irq_type,
+};
+
+
static void at91_pin_dbg(const struct device *dev, const struct
at91_pmx_pin *pin)
{
if (pin->mux) {
@@ -736,6 +848,9 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
*config |= DEGLITCH;
if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
*config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
+ if (info->ops->get_drivestrength)
+ *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin)
+ << DRIVE_STRENGTH_SHIFT);
if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
*config |= PULL_DOWN;
if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
@@ -753,6 +868,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
void __iomem *pio;
int i;
unsigned long config;
+ unsigned pin;
for (i = 0; i < num_configs; i++) {
config = configs[i];
@@ -761,7 +877,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
"%s:%d, pin_id=%d, config=0x%lx",
__func__, __LINE__, pin_id, config);
pio = pin_to_controller(info, pin_to_bank(pin_id));
- mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+ pin = pin_id % MAX_NB_GPIO_PER_BANK;
+ mask = pin_to_mask(pin);
if (config & PULL_UP && config & PULL_DOWN)
return -EINVAL;
@@ -773,6 +890,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
if (info->ops->set_debounce)
info->ops->set_debounce(pio, mask, config & DEBOUNCE,
(config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+ if (info->ops->set_drivestrength)
+ info->ops->set_drivestrength(pio, pin,
+ (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
if (info->ops->set_pulldown)
info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
@@ -1551,6 +1671,7 @@ static void at91_gpio_probe_fixup(void)
static struct of_device_id at91_gpio_of_match[] = {
{ .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
+ { .compatible = "atmel,sama5d3-gpio", .data = &sama5d3_ops, },
{ .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
{ /* sentinel */ }
};
diff --git a/include/dt-bindings/pinctrl/at91.h
b/include/dt-bindings/pinctrl/at91.h
index 0fee6ff..af71ebb 100644
--- a/include/dt-bindings/pinctrl/at91.h
+++ b/include/dt-bindings/pinctrl/at91.h
@@ -20,6 +20,11 @@
#define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP |
AT91_PINCTRL_DEGLITCH)
+#define AT91_PINCTRL_DRIVE_STRENGTH_DEFAULT (0x0 << 5)
+#define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 5)
+#define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 5)
+#define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 5)
+
#define AT91_PIOA 0
#define AT91_PIOB 1
#define AT91_PIOC 2
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* pinctrl: at91: drive strength control
2014-01-21 5:52 ` Marek Roszko
@ 2014-01-21 6:06 ` Jean-Christophe PLAGNIOL-VILLARD
2014-01-21 6:33 ` [PATCH] pinctrl:at91:add drive strength configuration Marek Roszko
0 siblings, 1 reply; 11+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-01-21 6:06 UTC (permalink / raw)
To: linux-arm-kernel
please put a better commemt
On 00:52 Tue 21 Jan , Marek Roszko wrote:
> Alright, added a SAMA5D3 compatible type and gave it's own drive
> strength ops. Moved the defines to inline funcs. Made the bindings
> independent of soc.
>
> Hopefully tabs appear this time, I haven't figured out the whole mailing
> list - email client thing and finding a client that doesn't convert
> spaces/tabs is hard.
those comments
>
> ---
come here fater the ---
please use git send-email or we can not even apply the patch
> arch/arm/mach-at91/include/mach/at91sam9x5.h | 3 +
> arch/arm/mach-at91/include/mach/sama5d3.h | 3 +
> drivers/pinctrl/pinctrl-at91.c | 123
> +++++++++++++++++++++++++-
> include/dt-bindings/pinctrl/at91.h | 5 ++
> 4 files changed, 133 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h
> b/arch/arm/mach-at91/include/mach/at91sam9x5.h
> index 2fc76c4..2efeb0a 100644
> --- a/arch/arm/mach-at91/include/mach/at91sam9x5.h
> +++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h
> @@ -59,6 +59,9 @@
> */
> #define AT91SAM9X5_BASE_RTC 0xfffffeb0
>
> +#define AT91SAM9X5_PIO_DRIVER1 0x114 /*PIO Driver 1 register offset*/
> +#define AT91SAM9X5_PIO_DRIVER2 0x118 /*PIO Driver 2 register offset*/
move this in at91_pio.h
> +
> /*
> * Internal Memory.
> */
> diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h
> b/arch/arm/mach-at91/include/mach/sama5d3.h
> index 25613d8..5d434f9 100644
> --- a/arch/arm/mach-at91/include/mach/sama5d3.h
> +++ b/arch/arm/mach-at91/include/mach/sama5d3.h
> @@ -77,6 +77,9 @@
> */
> #define SAMA5D3_BASE_RTC 0xfffffeb0
>
> +#define SAMA5D3_PIO_DRIVER1 0x118 /*PIO Driver 1 register offset*/
> +#define SAMA5D3_PIO_DRIVER2 0x11C /*PIO Driver 2 register offset*/
> +
ditto
> /*
> * Internal Memory
> */
> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
> index a7549c4..984c3be 100644
> --- a/drivers/pinctrl/pinctrl-at91.c
> +++ b/drivers/pinctrl/pinctrl-at91.c
> @@ -62,10 +62,21 @@ static int gpio_banks;
> #define DEGLITCH (1 << 2)
> #define PULL_DOWN (1 << 3)
> #define DIS_SCHMIT (1 << 4)
> +#define DRIVE_STRENGTH_SHIFT 5
> +#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
> #define DEBOUNCE (1 << 16)
> #define DEBOUNCE_VAL_SHIFT 17
> #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
>
> +#define DRIVE_STRENGTH_DEFAULT (0x0 << 5)
> +#define DRIVE_STRENGTH_LOW (0x1 << 5)
> +#define DRIVE_STRENGTH_MED (0x2 << 5)
> +#define DRIVE_STRENGTH_HI (0x3 << 5)
> +
> +
> +#define DRIVE_STRENGTH_MASK 0x3
> +#define NUM_PINS_PER_DIVIDED_REGS 16
> +
> /**
> * struct at91_pmx_func - describes AT91 pinmux functions
> * @name: the name of this specific function
> @@ -148,6 +159,8 @@ struct at91_pinctrl_mux_ops {
> void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
> bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
> void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32
> div);
> + unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin);
> + void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
> bool (*get_pulldown)(void __iomem *pio, unsigned pin);
> void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
> bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
> @@ -319,6 +332,22 @@ static unsigned pin_to_mask(unsigned int pin)
> return 1 << pin;
> }?
??
>
> +static inline int two_bit_pin_value_shift(unsigned pin)
> +{
> + return 2*((pin >= NUM_PINS_PER_DIVIDED_REGS) ? pin -
2 * (
> NUM_PINS_PER_DIVIDED_REGS : pin);
> +}
> +
> +
one line
> +static unsigned sama5d3_get_drive_register(unsigned int pin)
> +{
> + return (pin > NUM_PINS_PER_DIVIDED_REGS-1) ? SAMA5D3_PIO_DRIVER2 :
S - 1
> SAMA5D3_PIO_DRIVER1;
> +}
> +
> +static unsigned at91sam9x5_get_drive_register(unsigned int pin)
> +{
> + return (pin > NUM_PINS_PER_DIVIDED_REGS-1) ? AT91SAM9X5_PIO_DRIVER2 :
> AT91SAM9X5_PIO_DRIVER1;
> +}
> +
> static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
> {
> writel_relaxed(mask, pio + PIO_IDR);
> @@ -462,6 +491,67 @@ static void at91_mux_pio3_set_pulldown(void __iomem
> *pio, unsigned mask, bool is
> __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
> }?
>
???
> +static inline u32 read_drive_strength(void __iomem *reg, unsigned pin)
> +{
> + return (__raw_readl(reg)
> + >> two_bit_pin_value_shift(pin)) & DRIVE_STRENGTH_MASK;
use a temp val to make the code readable
> +}
> +
> +static unsigned at91_mux_sama5d3_get_drivestrength(void __iomem *pio,
> unsigned pin)
> +{
> + unsigned tmp = read_drive_strength(pio +
> sama5d3_get_drive_register(pin), pin);
> +
> + if (!tmp)
> + tmp = DRIVE_STRENGTH_LOW;
> +
> + return tmp;
> +}
> +
> +static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio,
> unsigned pin)
> +{
> + unsigned tmp = read_drive_strength(pio +
> at91sam9x5_get_drive_register(pin), pin);
> +
> + /*inverse settings*/
> + tmp = DRIVE_STRENGTH_HI - tmp;
> +
> + return tmp;
> +}
> +
> +static void set_drive_strength(void __iomem *reg, unsigned pin, u32
> strength)
> +{
> + unsigned tmp = __raw_readl(reg);
> +
> + tmp &= ~(DRIVE_STRENGTH_MASK << two_bit_pin_value_shift(pin));
> + tmp |= strength << two_bit_pin_value_shift(pin);
> +
> + __raw_writel(tmp, reg);
> +}
> +
> +static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio,
> unsigned pin,
> + u32 setting)
> +{
> + /* do nothing if setting is zero */
> + if (!setting)
> + return;
> +
> + /* strength is 1 to 1 with setting for SAMA5 */
> + set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting);
> +}
> +
> +static void at91_mux_sam9x5_set_drivestrength(void __iomem *pio,
> unsigned pin,
> + u32 setting)
> +{
> + /* do nothing if setting is zero */
> + if (!setting)
> + return;
> +
> + /* strength is inverse on SAM9s, 0 = hi, 1 = med, 2 = low, 3 = rsvd */
> + setting = DRIVE_STRENGTH_HI - setting;
> +
> + set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin,
> setting);
> +}
> +
> +
> static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio,
> unsigned mask)
> {
> __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
> @@ -491,6 +581,8 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> .set_deglitch = at91_mux_pio3_set_deglitch,
> .get_debounce = at91_mux_pio3_get_debounce,
> .set_debounce = at91_mux_pio3_set_debounce,
> + .get_drivestrength = at91_mux_sam9x5_get_drivestrength,
> + .set_drivestrength = at91_mux_sam9x5_set_drivestrength,
> .get_pulldown = at91_mux_pio3_get_pulldown,
> .set_pulldown = at91_mux_pio3_set_pulldown,
> .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> @@ -498,6 +590,26 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> .irq_type = alt_gpio_irq_type,
> };
>
> +static struct at91_pinctrl_mux_ops sama5d3_ops = {
> + .get_periph = at91_mux_pio3_get_periph,
> + .mux_A_periph = at91_mux_pio3_set_A_periph,
> + .mux_B_periph = at91_mux_pio3_set_B_periph,
> + .mux_C_periph = at91_mux_pio3_set_C_periph,
> + .mux_D_periph = at91_mux_pio3_set_D_periph,
> + .get_deglitch = at91_mux_pio3_get_deglitch,
> + .set_deglitch = at91_mux_pio3_set_deglitch,
> + .get_debounce = at91_mux_pio3_get_debounce,
> + .set_debounce = at91_mux_pio3_set_debounce,
> + .get_drivestrength = at91_mux_sama5d3_get_drivestrength,
> + .set_drivestrength = at91_mux_sama5d3_set_drivestrength,
> + .get_pulldown = at91_mux_pio3_get_pulldown,
> + .set_pulldown = at91_mux_pio3_set_pulldown,
> + .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> + .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
> + .irq_type = alt_gpio_irq_type,
> +};
> +
> +
> static void at91_pin_dbg(const struct device *dev, const struct
> at91_pmx_pin *pin)
> {
> if (pin->mux) {
> @@ -736,6 +848,9 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
> *config |= DEGLITCH;
> if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
> *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
> + if (info->ops->get_drivestrength)
> + *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin)
> + << DRIVE_STRENGTH_SHIFT);
> if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
> *config |= PULL_DOWN;
> if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
> @@ -753,6 +868,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> void __iomem *pio;
> int i;
> unsigned long config;
> + unsigned pin;
>
> for (i = 0; i < num_configs; i++) {
> config = configs[i];
> @@ -761,7 +877,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> "%s:%d, pin_id=%d, config=0x%lx",
> __func__, __LINE__, pin_id, config);
> pio = pin_to_controller(info, pin_to_bank(pin_id));
> - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
> + pin = pin_id % MAX_NB_GPIO_PER_BANK;
> + mask = pin_to_mask(pin);
>
> if (config & PULL_UP && config & PULL_DOWN)
> return -EINVAL;
> @@ -773,6 +890,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> if (info->ops->set_debounce)
> info->ops->set_debounce(pio, mask, config & DEBOUNCE,
> (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
> + if (info->ops->set_drivestrength)
> + info->ops->set_drivestrength(pio, pin,
> + (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
> if (info->ops->set_pulldown)
> info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
> if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
> @@ -1551,6 +1671,7 @@ static void at91_gpio_probe_fixup(void)
>
> static struct of_device_id at91_gpio_of_match[] = {
> { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
> + { .compatible = "atmel,sama5d3-gpio", .data = &sama5d3_ops, },
you must update the binding too
and the dts
> { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
> { /* sentinel */ }
> };
> diff --git a/include/dt-bindings/pinctrl/at91.h
> b/include/dt-bindings/pinctrl/at91.h
> index 0fee6ff..af71ebb 100644
> --- a/include/dt-bindings/pinctrl/at91.h
> +++ b/include/dt-bindings/pinctrl/at91.h
> @@ -20,6 +20,11 @@
>
> #define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP |
> AT91_PINCTRL_DEGLITCH)
>
> +#define AT91_PINCTRL_DRIVE_STRENGTH_DEFAULT (0x0 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 5)
> +
> #define AT91_PIOA 0
> #define AT91_PIOB 1
> #define AT91_PIOC 2
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] pinctrl:at91:add drive strength configuration
2014-01-21 6:06 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2014-01-21 6:33 ` Marek Roszko
2014-02-07 8:41 ` Jean-Christophe PLAGNIOL-VILLARD
2014-02-10 9:38 ` Linus Walleij
0 siblings, 2 replies; 11+ messages in thread
From: Marek Roszko @ 2014-01-21 6:33 UTC (permalink / raw)
To: linux-arm-kernel
The SAMA5 and most SAM9xGs(baring a few exceptions like the SAM945G) have drive
control registers that allow configuring the output current of the gpio pins between
three predefined levels of low,medium and high drive.
This patch adds four new dt-bindings that allow setting the strength via the device tree.
Added set/get drive strength to pinctrl ops table.
A sama5d3-gpio of id entry was made to set the set/get drive strength function for the
sam5d3s which unforunately have different register addresses and strength-to-value
map than the sam9s.
Added PIO_DRIVER1/2 defines in at91_pio.h prefixed with the target SoC.
---
arch/arm/boot/dts/sama5d3.dtsi | 10 +--
arch/arm/mach-at91/include/mach/at91_pio.h | 7 ++
drivers/pinctrl/pinctrl-at91.c | 131 +++++++++++++++++++++++++++-
include/dt-bindings/pinctrl/at91.h | 5 ++
4 files changed, 147 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index 5cdaba4..5576330 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -619,7 +619,7 @@
pioA: gpio at fffff200 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff200 0x100>;
interrupts = <6 IRQ_TYPE_LEVEL_HIGH 1>;
#gpio-cells = <2>;
@@ -629,7 +629,7 @@
};
pioB: gpio at fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x100>;
interrupts = <7 IRQ_TYPE_LEVEL_HIGH 1>;
#gpio-cells = <2>;
@@ -639,7 +639,7 @@
};
pioC: gpio at fffff600 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff600 0x100>;
interrupts = <8 IRQ_TYPE_LEVEL_HIGH 1>;
#gpio-cells = <2>;
@@ -649,7 +649,7 @@
};
pioD: gpio at fffff800 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff800 0x100>;
interrupts = <9 IRQ_TYPE_LEVEL_HIGH 1>;
#gpio-cells = <2>;
@@ -659,7 +659,7 @@
};
pioE: gpio at fffffa00 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffffa00 0x100>;
interrupts = <10 IRQ_TYPE_LEVEL_HIGH 1>;
#gpio-cells = <2>;
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
index 732b11c..b1e6380 100644
--- a/arch/arm/mach-at91/include/mach/at91_pio.h
+++ b/arch/arm/mach-at91/include/mach/at91_pio.h
@@ -66,6 +66,13 @@
#define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
#define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
+
+#define SAMA5D3_PIO_DRIVER1 0x118 /*PIO Driver 1 register offset*/
+#define SAMA5D3_PIO_DRIVER2 0x11C /*PIO Driver 2 register offset*/
+
+#define AT91SAM9X5_PIO_DRIVER1 0x114 /*PIO Driver 1 register offset*/
+#define AT91SAM9X5_PIO_DRIVER2 0x118 /*PIO Driver 2 register offset*/
+
#define ABCDSR_PERIPH_A 0x0
#define ABCDSR_PERIPH_B 0x1
#define ABCDSR_PERIPH_C 0x2
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index a7549c4..d79e085 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -62,10 +62,21 @@ static int gpio_banks;
#define DEGLITCH (1 << 2)
#define PULL_DOWN (1 << 3)
#define DIS_SCHMIT (1 << 4)
+#define DRIVE_STRENGTH_SHIFT 5
+#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
#define DEBOUNCE (1 << 16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
+#define DRIVE_STRENGTH_DEFAULT (0x0 << 5)
+#define DRIVE_STRENGTH_LOW (0x1 << 5)
+#define DRIVE_STRENGTH_MED (0x2 << 5)
+#define DRIVE_STRENGTH_HI (0x3 << 5)
+
+
+#define DRIVE_STRENGTH_MASK 0x3
+#define NUM_PINS_PER_DIVIDED_REGS 16
+
/**
* struct at91_pmx_func - describes AT91 pinmux functions
* @name: the name of this specific function
@@ -148,6 +159,8 @@ struct at91_pinctrl_mux_ops {
void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
+ unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin);
+ void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
bool (*get_pulldown)(void __iomem *pio, unsigned pin);
void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
@@ -319,6 +332,24 @@ static unsigned pin_to_mask(unsigned int pin)
return 1 << pin;
}
+static inline int two_bit_pin_value_shift(unsigned pin)
+{
+ return 2*((pin >= NUM_PINS_PER_DIVIDED_REGS)
+ ? pin - NUM_PINS_PER_DIVIDED_REGS : pin);
+}
+
+static unsigned sama5d3_get_drive_register(unsigned int pin)
+{
+ return (pin > NUM_PINS_PER_DIVIDED_REGS-1)
+ ? SAMA5D3_PIO_DRIVER2: SAMA5D3_PIO_DRIVER1;
+}
+
+static unsigned at91sam9x5_get_drive_register(unsigned int pin)
+{
+ return (pin > NUM_PINS_PER_DIVIDED_REGS-1)
+ ? AT91SAM9X5_PIO_DRIVER2: AT91SAM9X5_PIO_DRIVER1;
+}
+
static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
{
writel_relaxed(mask, pio + PIO_IDR);
@@ -462,6 +493,73 @@ static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is
__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
}
+static inline u32 read_drive_strength(void __iomem *reg, unsigned pin)
+{
+ unsigned tmp = __raw_readl(reg);
+ tmp = tmp >> two_bit_pin_value_shift(pin)
+
+ return tmp & DRIVE_STRENGTH_MASK;
+}
+
+static unsigned at91_mux_sama5d3_get_drivestrength(void __iomem *pio, unsigned pin)
+{
+ unsigned tmp = read_drive_strength(pio + sama5d3_get_drive_register(pin), pin);
+
+ /*value of 0 = low, all other values are 1 to 1*/
+ if (!tmp)
+ tmp = DRIVE_STRENGTH_LOW;
+
+ return tmp;
+}
+
+static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio, unsigned pin)
+{
+ unsigned tmp = read_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin);
+
+ /*
+ * inverse the setting for dt defines
+ * 0 = hi, 1 = med, 2 = low, 3 = rsvd
+ */
+ tmp = DRIVE_STRENGTH_HI - tmp;
+
+ return tmp;
+}
+
+static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength)
+{
+ unsigned tmp = __raw_readl(reg);
+
+ tmp &= ~(DRIVE_STRENGTH_MASK << two_bit_pin_value_shift(pin));
+ tmp |= strength << two_bit_pin_value_shift(pin);
+
+ __raw_writel(tmp, reg);
+}
+
+static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio, unsigned pin,
+ u32 setting)
+{
+ /* do nothing if setting is zero */
+ if (!setting)
+ return;
+
+ /* strength is 1 to 1 with setting for SAMA5 */
+ set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting);
+}
+
+static void at91_mux_sam9x5_set_drivestrength(void __iomem *pio, unsigned pin,
+ u32 setting)
+{
+ /* do nothing if setting is zero */
+ if (!setting)
+ return;
+
+ /* strength is inverse on SAM9s, 0 = hi, 1 = med, 2 = low, 3 = rsvd */
+ setting = DRIVE_STRENGTH_HI - setting;
+
+ set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin, setting);
+}
+
+
static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
{
__raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
@@ -491,6 +589,27 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
.set_deglitch = at91_mux_pio3_set_deglitch,
.get_debounce = at91_mux_pio3_get_debounce,
.set_debounce = at91_mux_pio3_set_debounce,
+ .get_drivestrength = at91_mux_sam9x5_get_drivestrength,
+ .set_drivestrength = at91_mux_sam9x5_set_drivestrength,
+ .get_pulldown = at91_mux_pio3_get_pulldown,
+ .set_pulldown = at91_mux_pio3_set_pulldown,
+ .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+ .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+ .irq_type = alt_gpio_irq_type,
+};
+
+static struct at91_pinctrl_mux_ops sama5d3_ops = {
+ .get_periph = at91_mux_pio3_get_periph,
+ .mux_A_periph = at91_mux_pio3_set_A_periph,
+ .mux_B_periph = at91_mux_pio3_set_B_periph,
+ .mux_C_periph = at91_mux_pio3_set_C_periph,
+ .mux_D_periph = at91_mux_pio3_set_D_periph,
+ .get_deglitch = at91_mux_pio3_get_deglitch,
+ .set_deglitch = at91_mux_pio3_set_deglitch,
+ .get_debounce = at91_mux_pio3_get_debounce,
+ .set_debounce = at91_mux_pio3_set_debounce,
+ .get_drivestrength = at91_mux_sama5d3_get_drivestrength,
+ .set_drivestrength = at91_mux_sama5d3_set_drivestrength,
.get_pulldown = at91_mux_pio3_get_pulldown,
.set_pulldown = at91_mux_pio3_set_pulldown,
.get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
@@ -498,6 +617,7 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
.irq_type = alt_gpio_irq_type,
};
+
static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
{
if (pin->mux) {
@@ -736,6 +856,9 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
*config |= DEGLITCH;
if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
*config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
+ if (info->ops->get_drivestrength)
+ *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin)
+ << DRIVE_STRENGTH_SHIFT);
if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
*config |= PULL_DOWN;
if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
@@ -753,6 +876,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
void __iomem *pio;
int i;
unsigned long config;
+ unsigned pin;
for (i = 0; i < num_configs; i++) {
config = configs[i];
@@ -761,7 +885,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
"%s:%d, pin_id=%d, config=0x%lx",
__func__, __LINE__, pin_id, config);
pio = pin_to_controller(info, pin_to_bank(pin_id));
- mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+ pin = pin_id % MAX_NB_GPIO_PER_BANK;
+ mask = pin_to_mask(pin);
if (config & PULL_UP && config & PULL_DOWN)
return -EINVAL;
@@ -773,6 +898,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
if (info->ops->set_debounce)
info->ops->set_debounce(pio, mask, config & DEBOUNCE,
(config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+ if (info->ops->set_drivestrength)
+ info->ops->set_drivestrength(pio, pin,
+ (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
if (info->ops->set_pulldown)
info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
@@ -1551,6 +1679,7 @@ static void at91_gpio_probe_fixup(void)
static struct of_device_id at91_gpio_of_match[] = {
{ .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
+ { .compatible = "atmel,sama5d3-gpio", .data = &sama5d3_ops, },
{ .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
{ /* sentinel */ }
};
diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
index 0fee6ff..af71ebb 100644
--- a/include/dt-bindings/pinctrl/at91.h
+++ b/include/dt-bindings/pinctrl/at91.h
@@ -20,6 +20,11 @@
#define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
+#define AT91_PINCTRL_DRIVE_STRENGTH_DEFAULT (0x0 << 5)
+#define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 5)
+#define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 5)
+#define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 5)
+
#define AT91_PIOA 0
#define AT91_PIOB 1
#define AT91_PIOC 2
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH] pinctrl:at91:add drive strength configuration
2014-01-21 6:33 ` [PATCH] pinctrl:at91:add drive strength configuration Marek Roszko
@ 2014-02-07 8:41 ` Jean-Christophe PLAGNIOL-VILLARD
2014-02-10 9:38 ` Linus Walleij
1 sibling, 0 replies; 11+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 8:41 UTC (permalink / raw)
To: linux-arm-kernel
On 01:33 Tue 21 Jan , Marek Roszko wrote:
> The SAMA5 and most SAM9xGs(baring a few exceptions like the SAM945G) have drive
> control registers that allow configuring the output current of the gpio pins between
> three predefined levels of low,medium and high drive.
>
> This patch adds four new dt-bindings that allow setting the strength via the device tree.
> Added set/get drive strength to pinctrl ops table.
> A sama5d3-gpio of id entry was made to set the set/get drive strength function for the
> sam5d3s which unforunately have different register addresses and strength-to-value
> map than the sam9s.
> Added PIO_DRIVER1/2 defines in at91_pio.h prefixed with the target SoC.
missing the SoB so we can not apply it
otherwise
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
and please split the patch in 2 dt and driver
Best Regards,
J.
> ---
> arch/arm/boot/dts/sama5d3.dtsi | 10 +--
> arch/arm/mach-at91/include/mach/at91_pio.h | 7 ++
> drivers/pinctrl/pinctrl-at91.c | 131 +++++++++++++++++++++++++++-
> include/dt-bindings/pinctrl/at91.h | 5 ++
> 4 files changed, 147 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
> index 5cdaba4..5576330 100644
> --- a/arch/arm/boot/dts/sama5d3.dtsi
> +++ b/arch/arm/boot/dts/sama5d3.dtsi
> @@ -619,7 +619,7 @@
>
>
> pioA: gpio at fffff200 {
> - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
> + compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
> reg = <0xfffff200 0x100>;
> interrupts = <6 IRQ_TYPE_LEVEL_HIGH 1>;
> #gpio-cells = <2>;
> @@ -629,7 +629,7 @@
> };
>
> pioB: gpio at fffff400 {
> - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
> + compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
> reg = <0xfffff400 0x100>;
> interrupts = <7 IRQ_TYPE_LEVEL_HIGH 1>;
> #gpio-cells = <2>;
> @@ -639,7 +639,7 @@
> };
>
> pioC: gpio at fffff600 {
> - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
> + compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
> reg = <0xfffff600 0x100>;
> interrupts = <8 IRQ_TYPE_LEVEL_HIGH 1>;
> #gpio-cells = <2>;
> @@ -649,7 +649,7 @@
> };
>
> pioD: gpio at fffff800 {
> - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
> + compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
> reg = <0xfffff800 0x100>;
> interrupts = <9 IRQ_TYPE_LEVEL_HIGH 1>;
> #gpio-cells = <2>;
> @@ -659,7 +659,7 @@
> };
>
> pioE: gpio at fffffa00 {
> - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
> + compatible = "atmel,sama5d3-gpio", "atmel,at91rm9200-gpio";
> reg = <0xfffffa00 0x100>;
> interrupts = <10 IRQ_TYPE_LEVEL_HIGH 1>;
> #gpio-cells = <2>;
> diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
> index 732b11c..b1e6380 100644
> --- a/arch/arm/mach-at91/include/mach/at91_pio.h
> +++ b/arch/arm/mach-at91/include/mach/at91_pio.h
> @@ -66,6 +66,13 @@
> #define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */
> #define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */
>
> +
> +#define SAMA5D3_PIO_DRIVER1 0x118 /*PIO Driver 1 register offset*/
> +#define SAMA5D3_PIO_DRIVER2 0x11C /*PIO Driver 2 register offset*/
> +
> +#define AT91SAM9X5_PIO_DRIVER1 0x114 /*PIO Driver 1 register offset*/
> +#define AT91SAM9X5_PIO_DRIVER2 0x118 /*PIO Driver 2 register offset*/
> +
> #define ABCDSR_PERIPH_A 0x0
> #define ABCDSR_PERIPH_B 0x1
> #define ABCDSR_PERIPH_C 0x2
> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
> index a7549c4..d79e085 100644
> --- a/drivers/pinctrl/pinctrl-at91.c
> +++ b/drivers/pinctrl/pinctrl-at91.c
> @@ -62,10 +62,21 @@ static int gpio_banks;
> #define DEGLITCH (1 << 2)
> #define PULL_DOWN (1 << 3)
> #define DIS_SCHMIT (1 << 4)
> +#define DRIVE_STRENGTH_SHIFT 5
> +#define DRIVE_STRENGTH (0x3 << DRIVE_STRENGTH_SHIFT)
> #define DEBOUNCE (1 << 16)
> #define DEBOUNCE_VAL_SHIFT 17
> #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
>
> +#define DRIVE_STRENGTH_DEFAULT (0x0 << 5)
> +#define DRIVE_STRENGTH_LOW (0x1 << 5)
> +#define DRIVE_STRENGTH_MED (0x2 << 5)
> +#define DRIVE_STRENGTH_HI (0x3 << 5)
> +
> +
> +#define DRIVE_STRENGTH_MASK 0x3
> +#define NUM_PINS_PER_DIVIDED_REGS 16
> +
> /**
> * struct at91_pmx_func - describes AT91 pinmux functions
> * @name: the name of this specific function
> @@ -148,6 +159,8 @@ struct at91_pinctrl_mux_ops {
> void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
> bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
> void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
> + unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin);
> + void (*set_drivestrength)(void __iomem *pio, unsigned pin, u32 strength);
> bool (*get_pulldown)(void __iomem *pio, unsigned pin);
> void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
> bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
> @@ -319,6 +332,24 @@ static unsigned pin_to_mask(unsigned int pin)
> return 1 << pin;
> }
>
> +static inline int two_bit_pin_value_shift(unsigned pin)
> +{
> + return 2*((pin >= NUM_PINS_PER_DIVIDED_REGS)
> + ? pin - NUM_PINS_PER_DIVIDED_REGS : pin);
> +}
> +
> +static unsigned sama5d3_get_drive_register(unsigned int pin)
> +{
> + return (pin > NUM_PINS_PER_DIVIDED_REGS-1)
> + ? SAMA5D3_PIO_DRIVER2: SAMA5D3_PIO_DRIVER1;
> +}
> +
> +static unsigned at91sam9x5_get_drive_register(unsigned int pin)
> +{
> + return (pin > NUM_PINS_PER_DIVIDED_REGS-1)
> + ? AT91SAM9X5_PIO_DRIVER2: AT91SAM9X5_PIO_DRIVER1;
> +}
> +
> static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
> {
> writel_relaxed(mask, pio + PIO_IDR);
> @@ -462,6 +493,73 @@ static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is
> __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
> }
>
> +static inline u32 read_drive_strength(void __iomem *reg, unsigned pin)
> +{
> + unsigned tmp = __raw_readl(reg);
> + tmp = tmp >> two_bit_pin_value_shift(pin)
> +
> + return tmp & DRIVE_STRENGTH_MASK;
> +}
> +
> +static unsigned at91_mux_sama5d3_get_drivestrength(void __iomem *pio, unsigned pin)
> +{
> + unsigned tmp = read_drive_strength(pio + sama5d3_get_drive_register(pin), pin);
> +
> + /*value of 0 = low, all other values are 1 to 1*/
> + if (!tmp)
> + tmp = DRIVE_STRENGTH_LOW;
> +
> + return tmp;
> +}
> +
> +static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio, unsigned pin)
> +{
> + unsigned tmp = read_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin);
> +
> + /*
> + * inverse the setting for dt defines
> + * 0 = hi, 1 = med, 2 = low, 3 = rsvd
> + */
> + tmp = DRIVE_STRENGTH_HI - tmp;
> +
> + return tmp;
> +}
> +
> +static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength)
> +{
> + unsigned tmp = __raw_readl(reg);
> +
> + tmp &= ~(DRIVE_STRENGTH_MASK << two_bit_pin_value_shift(pin));
> + tmp |= strength << two_bit_pin_value_shift(pin);
> +
> + __raw_writel(tmp, reg);
> +}
> +
> +static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio, unsigned pin,
> + u32 setting)
> +{
> + /* do nothing if setting is zero */
> + if (!setting)
> + return;
> +
> + /* strength is 1 to 1 with setting for SAMA5 */
> + set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting);
> +}
> +
> +static void at91_mux_sam9x5_set_drivestrength(void __iomem *pio, unsigned pin,
> + u32 setting)
> +{
> + /* do nothing if setting is zero */
> + if (!setting)
> + return;
> +
> + /* strength is inverse on SAM9s, 0 = hi, 1 = med, 2 = low, 3 = rsvd */
> + setting = DRIVE_STRENGTH_HI - setting;
> +
> + set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin, setting);
> +}
> +
> +
> static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
> {
> __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
> @@ -491,6 +589,27 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> .set_deglitch = at91_mux_pio3_set_deglitch,
> .get_debounce = at91_mux_pio3_get_debounce,
> .set_debounce = at91_mux_pio3_set_debounce,
> + .get_drivestrength = at91_mux_sam9x5_get_drivestrength,
> + .set_drivestrength = at91_mux_sam9x5_set_drivestrength,
> + .get_pulldown = at91_mux_pio3_get_pulldown,
> + .set_pulldown = at91_mux_pio3_set_pulldown,
> + .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> + .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
> + .irq_type = alt_gpio_irq_type,
> +};
> +
> +static struct at91_pinctrl_mux_ops sama5d3_ops = {
> + .get_periph = at91_mux_pio3_get_periph,
> + .mux_A_periph = at91_mux_pio3_set_A_periph,
> + .mux_B_periph = at91_mux_pio3_set_B_periph,
> + .mux_C_periph = at91_mux_pio3_set_C_periph,
> + .mux_D_periph = at91_mux_pio3_set_D_periph,
> + .get_deglitch = at91_mux_pio3_get_deglitch,
> + .set_deglitch = at91_mux_pio3_set_deglitch,
> + .get_debounce = at91_mux_pio3_get_debounce,
> + .set_debounce = at91_mux_pio3_set_debounce,
> + .get_drivestrength = at91_mux_sama5d3_get_drivestrength,
> + .set_drivestrength = at91_mux_sama5d3_set_drivestrength,
> .get_pulldown = at91_mux_pio3_get_pulldown,
> .set_pulldown = at91_mux_pio3_set_pulldown,
> .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> @@ -498,6 +617,7 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> .irq_type = alt_gpio_irq_type,
> };
>
> +
> static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
> {
> if (pin->mux) {
> @@ -736,6 +856,9 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
> *config |= DEGLITCH;
> if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
> *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
> + if (info->ops->get_drivestrength)
> + *config |= DRIVE_STRENGTH | (info->ops->get_drivestrength(pio, pin)
> + << DRIVE_STRENGTH_SHIFT);
> if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
> *config |= PULL_DOWN;
> if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
> @@ -753,6 +876,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> void __iomem *pio;
> int i;
> unsigned long config;
> + unsigned pin;
>
> for (i = 0; i < num_configs; i++) {
> config = configs[i];
> @@ -761,7 +885,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> "%s:%d, pin_id=%d, config=0x%lx",
> __func__, __LINE__, pin_id, config);
> pio = pin_to_controller(info, pin_to_bank(pin_id));
> - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
> + pin = pin_id % MAX_NB_GPIO_PER_BANK;
> + mask = pin_to_mask(pin);
>
> if (config & PULL_UP && config & PULL_DOWN)
> return -EINVAL;
> @@ -773,6 +898,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
> if (info->ops->set_debounce)
> info->ops->set_debounce(pio, mask, config & DEBOUNCE,
> (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
> + if (info->ops->set_drivestrength)
> + info->ops->set_drivestrength(pio, pin,
> + (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
> if (info->ops->set_pulldown)
> info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
> if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
> @@ -1551,6 +1679,7 @@ static void at91_gpio_probe_fixup(void)
>
> static struct of_device_id at91_gpio_of_match[] = {
> { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
> + { .compatible = "atmel,sama5d3-gpio", .data = &sama5d3_ops, },
> { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
> { /* sentinel */ }
> };
> diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
> index 0fee6ff..af71ebb 100644
> --- a/include/dt-bindings/pinctrl/at91.h
> +++ b/include/dt-bindings/pinctrl/at91.h
> @@ -20,6 +20,11 @@
>
> #define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
>
> +#define AT91_PINCTRL_DRIVE_STRENGTH_DEFAULT (0x0 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 5)
> +
> #define AT91_PIOA 0
> #define AT91_PIOB 1
> #define AT91_PIOC 2
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] pinctrl:at91:add drive strength configuration
2014-01-21 6:33 ` [PATCH] pinctrl:at91:add drive strength configuration Marek Roszko
2014-02-07 8:41 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2014-02-10 9:38 ` Linus Walleij
2014-03-13 2:28 ` Mark Roszko
1 sibling, 1 reply; 11+ messages in thread
From: Linus Walleij @ 2014-02-10 9:38 UTC (permalink / raw)
To: linux-arm-kernel
I agree with J-C that the patch shall be split in one for the DT changes and one
for the driver changes (that I will apply to the pinctrl tree).
On Tue, Jan 21, 2014 at 7:33 AM, Marek Roszko <mark.roszko@gmail.com> wrote:
> The SAMA5 and most SAM9xGs(baring a few exceptions like the SAM945G) have drive
> control registers that allow configuring the output current of the gpio pins between
> three predefined levels of low,medium and high drive.
Can we get to know a bit more about default/low/medium and high?
I.e. this:
> +#define DRIVE_STRENGTH_DEFAULT (0x0 << 5)
> +#define DRIVE_STRENGTH_LOW (0x1 << 5)
> +#define DRIVE_STRENGTH_MED (0x2 << 5)
> +#define DRIVE_STRENGTH_HI (0x3 << 5)
(...)
> +static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio, unsigned pin)
> +{
> + unsigned tmp = read_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin);
> +
> + /*
> + * inverse the setting for dt defines
> + * 0 = hi, 1 = med, 2 = low, 3 = rsvd
But in the defines ... 3-3=0 means "default" not
"reserved"?
> + */
> + tmp = DRIVE_STRENGTH_HI - tmp;
(...)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_DEFAULT (0x0 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 5)
> +#define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 5)
So I guess "default" is some HW-defined driver strength decided when
synthesizing the block? (Document the answer in the bindings or
something.)
What I'm after is if this is drive strength in the sense of
"number of driver stages" i.e. a number of extra mA per
strength increase, usuall in 2mA or 4mA increases, so e.g.
LOW=2mA, mid=4mA, high=6mA or if it's actually a
slew rate thing designed for restricing the noise in silicon
and/or electronics by providing a less steep slope containing
less overtones. (This is usually done by another construction.)
Which one is it?
You also already have this:
#define AT91_PINCTRL_MULTI_DRIVE (1 << 1)
How does these different things relate? Do you have to set
MULTI_DRIVE for the settings to work? Or is it leftover cruft?
Or what is it?
Also take this opportunity to update:
Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
To document all these funny defines and what they are used for.
The bindings changes should be part of the pinctrl driver patch.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] pinctrl:at91:add drive strength configuration
2014-02-10 9:38 ` Linus Walleij
@ 2014-03-13 2:28 ` Mark Roszko
2014-03-14 9:44 ` Linus Walleij
0 siblings, 1 reply; 11+ messages in thread
From: Mark Roszko @ 2014-03-13 2:28 UTC (permalink / raw)
To: linux-arm-kernel
>Can we get to know a bit more about default/low/medium and high?
Default is whatever the reset setting of the pins are. It's just a
placeholder for "do nothing" to alter the drive strength config. The
two groups of Atmel chips(SAMA5 and SAM9G series) have different reset
settings, i.e. the SAMA5 are "medium" while the SAM9Gs are "low".
Low, medium, high I can't really add much more than "see datasheet",
there are predefined output currents depending on pin and drive
strength configuration(low, medium,high).
>What I'm after is if this is drive strength in the sense of
>"number of driver stages" i.e. a number of extra mA per
>strength increase, usuall in 2mA or 4mA increases, so e.g.
>LOW=2mA, mid=4mA, high=6mA or if it's actually a
>slew rate thing designed for restricing the noise in silicon
>and/or electronics by providing a less steep slope containing
>less overtones. (This is usually done by another construction.)
>Which one is it?
The drive strength increases the output current capability of a pin.
Unfortunately the pins differ how they change as well, i.e. on a
SAMA5, PC0-PC14 will change from 8,26,38 mA (low,medium,high) while
PB0-PB27 will change 3,6,7 mA respectively.
>How does these different things relate? Do you have to set
>MULTI_DRIVE for the settings to work? Or is it leftover cruft?
>Or what is it?
MULTI_DRIVE is the term for Atmel's open-drain GPIO configuration per pin.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] pinctrl:at91:add drive strength configuration
2014-03-13 2:28 ` Mark Roszko
@ 2014-03-14 9:44 ` Linus Walleij
0 siblings, 0 replies; 11+ messages in thread
From: Linus Walleij @ 2014-03-14 9:44 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 13, 2014 at 3:28 AM, Mark Roszko <mark.roszko@gmail.com> wrote:
>>What I'm after is if this is drive strength in the sense of
>>"number of driver stages" i.e. a number of extra mA per
>>strength increase, usuall in 2mA or 4mA increases, so e.g.
>>LOW=2mA, mid=4mA, high=6mA or if it's actually a
>>slew rate thing designed for restricing the noise in silicon
>>and/or electronics by providing a less steep slope containing
>>less overtones. (This is usually done by another construction.)
>>Which one is it?
>
> The drive strength increases the output current capability of a pin.
> Unfortunately the pins differ how they change as well, i.e. on a
> SAMA5, PC0-PC14 will change from 8,26,38 mA (low,medium,high) while
> PB0-PB27 will change 3,6,7 mA respectively.
First I'd like you to document exactly that above the #defines
in the driver
#define AT91_PINCTRL_DRIVE_STRENGTH_LOW
etc.
So this adds more magic to these 3 bits in the config word,
oh well I guess we have to live with this unless you switch over
to generic pin config any time soon.
>>How does these different things relate? Do you have to set
>>MULTI_DRIVE for the settings to work? Or is it leftover cruft?
>>Or what is it?
>
> MULTI_DRIVE is the term for Atmel's open-drain GPIO configuration per pin.
Hm. That could need a specific comment/documentation entry
I think. (Separate patch.)
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-03-14 9:44 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-21 1:07 pinctrl: at91: drive strength control Marek Roszko
2014-01-21 2:19 ` Jean-Christophe PLAGNIOL-VILLARD
2014-01-21 3:34 ` Mark Roszko
2014-01-21 4:09 ` Jean-Christophe PLAGNIOL-VILLARD
2014-01-21 5:52 ` Marek Roszko
2014-01-21 6:06 ` Jean-Christophe PLAGNIOL-VILLARD
2014-01-21 6:33 ` [PATCH] pinctrl:at91:add drive strength configuration Marek Roszko
2014-02-07 8:41 ` Jean-Christophe PLAGNIOL-VILLARD
2014-02-10 9:38 ` Linus Walleij
2014-03-13 2:28 ` Mark Roszko
2014-03-14 9:44 ` Linus Walleij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).