All of lore.kernel.org
 help / color / mirror / Atom feed
From: mark.roszko@gmail.com (Marek Roszko)
To: linux-arm-kernel@lists.infradead.org
Subject: pinctrl: at91: drive strength control
Date: Tue, 21 Jan 2014 00:52:30 -0500	[thread overview]
Message-ID: <52DE0B1E.90106@gmail.com> (raw)
In-Reply-To: <20140121040922.GN9558@ns203013.ovh.net>

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

  reply	other threads:[~2014-01-21  5:52 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52DE0B1E.90106@gmail.com \
    --to=mark.roszko@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.