All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masahiro Yamada <yamada.masahiro@socionext.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 5/7] pinctrl: uniphier: support drive-strength configuration
Date: Sat,  5 May 2018 19:53:55 +0900	[thread overview]
Message-ID: <1525517637-17603-6-git-send-email-yamada.masahiro@socionext.com> (raw)
In-Reply-To: <1525517637-17603-1-git-send-email-yamada.masahiro@socionext.com>

This allows our DT to specify drive-strength property.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 101 +++++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  44 ++++++++--
 2 files changed, 140 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 03103b3..39b5366 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -17,6 +17,9 @@
 
 #define UNIPHIER_PINCTRL_PINMUX_BASE	0x1000
 #define UNIPHIER_PINCTRL_LOAD_PINMUX	0x1700
+#define UNIPHIER_PINCTRL_DRVCTRL_BASE	0x1800
+#define UNIPHIER_PINCTRL_DRV2CTRL_BASE	0x1900
+#define UNIPHIER_PINCTRL_DRV3CTRL_BASE	0x1980
 #define UNIPHIER_PINCTRL_PUPDCTRL_BASE	0x1a00
 #define UNIPHIER_PINCTRL_IECTRL		0x1d00
 
@@ -142,10 +145,25 @@ static const struct pinconf_param uniphier_pinconf_params[] = {
 	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
 	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
 	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
 	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
 	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
 };
 
+static const struct uniphier_pinctrl_pin *
+uniphier_pinctrl_pin_get(struct uniphier_pinctrl_priv *priv, unsigned int pin)
+{
+	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
+	int pins_count = priv->socdata->pins_count;
+	int i;
+
+	for (i = 0; i < pins_count; i++)
+		if (pins[i].number == pin)
+			return &pins[i];
+
+	return NULL;
+}
+
 static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
 				     unsigned int param, unsigned int arg)
 {
@@ -186,6 +204,86 @@ static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
 	return 0;
 }
 
+static const unsigned int uniphier_pinconf_drv_strengths_1bit[] = {
+	4, 8,
+};
+
+static const unsigned int uniphier_pinconf_drv_strengths_2bit[] = {
+	8, 12, 16, 20,
+};
+
+static const unsigned int uniphier_pinconf_drv_strengths_3bit[] = {
+	4, 5, 7, 9, 11, 12, 14, 16,
+};
+
+static int uniphier_pinconf_drive_set(struct udevice *dev, unsigned int pin,
+				      unsigned int strength)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct uniphier_pinctrl_pin *desc;
+	const unsigned int *strengths;
+	unsigned int base, stride, width, drvctrl, reg, shift;
+	u32 val, mask, tmp;
+
+	desc = uniphier_pinctrl_pin_get(priv, pin);
+	if (WARN_ON(!desc))
+		return -EINVAL;
+
+	switch (uniphier_pin_get_drv_type(desc->data)) {
+	case UNIPHIER_PIN_DRV_1BIT:
+		strengths = uniphier_pinconf_drv_strengths_1bit;
+		base = UNIPHIER_PINCTRL_DRVCTRL_BASE;
+		stride = 1;
+		width = 1;
+		break;
+	case UNIPHIER_PIN_DRV_2BIT:
+		strengths = uniphier_pinconf_drv_strengths_2bit;
+		base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
+		stride = 2;
+		width = 2;
+		break;
+	case UNIPHIER_PIN_DRV_3BIT:
+		strengths = uniphier_pinconf_drv_strengths_3bit;
+		base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
+		stride = 4;
+		width = 3;
+		break;
+	default:
+		/* drive strength control is not supported for this pin */
+		return -EINVAL;
+	}
+
+	drvctrl = uniphier_pin_get_drvctrl(desc->data);
+	drvctrl *= stride;
+
+	reg = base + drvctrl / 32 * 4;
+	shift = drvctrl % 32;
+	mask = (1U << width) - 1;
+
+	for (val = 0; val <= mask; val++) {
+		if (strengths[val] > strength)
+			break;
+	}
+
+	if (val == 0) {
+		dev_err(dev, "unsupported drive strength %u mA for pin %s\n",
+			strength, desc->name);
+		return -EINVAL;
+	}
+
+	if (!mask)
+		return 0;
+
+	val--;
+
+	tmp = readl(priv->base + reg);
+	tmp &= ~(mask << shift);
+	tmp |= (mask & val) << shift;
+	writel(tmp, priv->base + reg);
+
+	return 0;
+}
+
 static int uniphier_pinconf_set(struct udevice *dev, unsigned int pin,
 				unsigned int param, unsigned int arg)
 {
@@ -198,6 +296,9 @@ static int uniphier_pinconf_set(struct udevice *dev, unsigned int pin,
 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 		ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
 		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		ret = uniphier_pinconf_drive_set(dev, pin, arg);
+		break;
 	case PIN_CONFIG_INPUT_ENABLE:
 		ret = uniphier_pinconf_input_enable(dev, pin, arg);
 		break;
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index 8884b08..3f47693 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -13,11 +13,44 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
-#define UNIPHIER_PIN_ATTR_PACKED(iectrl)	(iectrl)
+/* drive strength control register number */
+#define UNIPHIER_PIN_DRVCTRL_SHIFT	0
+#define UNIPHIER_PIN_DRVCTRL_BITS	9
+#define UNIPHIER_PIN_DRVCTRL_MASK	((1U << (UNIPHIER_PIN_DRVCTRL_BITS)) \
+					 - 1)
+
+/* drive control type */
+#define UNIPHIER_PIN_DRV_TYPE_SHIFT	((UNIPHIER_PIN_DRVCTRL_SHIFT) + \
+					 (UNIPHIER_PIN_DRVCTRL_BITS))
+#define UNIPHIER_PIN_DRV_TYPE_BITS	2
+#define UNIPHIER_PIN_DRV_TYPE_MASK	((1U << (UNIPHIER_PIN_DRV_TYPE_BITS)) \
+					 - 1)
+
+/* drive control type */
+enum uniphier_pin_drv_type {
+	UNIPHIER_PIN_DRV_1BIT,		/* 2 level control: 4/8 mA */
+	UNIPHIER_PIN_DRV_2BIT,		/* 4 level control: 8/12/16/20 mA */
+	UNIPHIER_PIN_DRV_3BIT,		/* 8 level control: 4/5/7/9/11/12/14/16 mA */
+};
+
+#define UNIPHIER_PIN_DRVCTRL(x) \
+	(((x) & (UNIPHIER_PIN_DRVCTRL_MASK)) << (UNIPHIER_PIN_DRVCTRL_SHIFT))
+#define UNIPHIER_PIN_DRV_TYPE(x) \
+	(((x) & (UNIPHIER_PIN_DRV_TYPE_MASK)) << (UNIPHIER_PIN_DRV_TYPE_SHIFT))
+
+#define UNIPHIER_PIN_ATTR_PACKED(drvctrl, drv_type)	\
+	UNIPHIER_PIN_DRVCTRL(drvctrl) |			\
+	UNIPHIER_PIN_DRV_TYPE(drv_type)
+
+static inline unsigned int uniphier_pin_get_drvctrl(unsigned int data)
+{
+	return (data >> UNIPHIER_PIN_DRVCTRL_SHIFT) & UNIPHIER_PIN_DRVCTRL_MASK;
+}
 
-static inline unsigned int uniphier_pin_get_iectrl(unsigned long data)
+static inline unsigned int uniphier_pin_get_drv_type(unsigned int data)
 {
-	return data;
+	return (data >> UNIPHIER_PIN_DRV_TYPE_SHIFT) &
+						UNIPHIER_PIN_DRV_TYPE_MASK;
 }
 
 /**
@@ -74,10 +107,11 @@ struct uniphier_pinctrl_socdata {
 #define UNIPHIER_PINCTRL_CAPS_MUX_4BIT		BIT(0)
 };
 
-#define UNIPHIER_PINCTRL_PIN(a, b)					\
+#define UNIPHIER_PINCTRL_PIN(a, b, c, d)				\
 {									\
 	.number = a,							\
-	.data = UNIPHIER_PIN_ATTR_PACKED(b),				\
+	.name = b,							\
+	.data = UNIPHIER_PIN_ATTR_PACKED(c, d),				\
 }
 
 #define __UNIPHIER_PINCTRL_GROUP(grp)					\
-- 
2.7.4

  parent reply	other threads:[~2018-05-05 10:53 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-05 10:53 [U-Boot] [PATCH 0/7] ARM: uniphier: support drive-strength pin configuration Masahiro Yamada
2018-05-05 10:53 ` [U-Boot] [PATCH 1/7] pinctrl: uniphier: remove unneeded pin data of LD6b Masahiro Yamada
2018-05-05 10:53 ` [U-Boot] [PATCH 2/7] pinctrl: uniphier: replace printf() with dev_err() Masahiro Yamada
2018-05-05 10:53 ` [U-Boot] [PATCH 3/7] pinctrl: uniphier: include <linux/build_bug.h> instead of <linux/bug.h> Masahiro Yamada
2018-05-05 10:53 ` [U-Boot] [PATCH 4/7] pinctrl: uniphier: support per-pin configuration via DT Masahiro Yamada
2018-05-05 10:53 ` Masahiro Yamada [this message]
2018-05-05 10:53 ` [U-Boot] [PATCH 6/7] pinctrl: uniphier: add ethernet TX pin data for LD20 Masahiro Yamada
2018-05-05 10:53 ` [U-Boot] [PATCH 7/7] ARM: uniphier: enable CONFIG_PINCONF Masahiro Yamada
2018-05-08  1:30 ` [U-Boot] [PATCH 0/7] ARM: uniphier: support drive-strength pin configuration Masahiro Yamada

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=1525517637-17603-6-git-send-email-yamada.masahiro@socionext.com \
    --to=yamada.masahiro@socionext.com \
    --cc=u-boot@lists.denx.de \
    /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.