All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Vasut <marex@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 09/10] gpio: s3c: Fix the GPIO driver
Date: Sat, 11 Oct 2014 18:42:57 +0200	[thread overview]
Message-ID: <1413045778-5690-9-git-send-email-marex@denx.de> (raw)
In-Reply-To: <1413045778-5690-1-git-send-email-marex@denx.de>

The GPIO driver didn't correctly compute the bank offset
from the GPIO number and caused random writes into the
GPIO block address space. Fix the driver so it actually
does the writes correctly. While at it, make use of the
clrsetbits_le32() mechanisms.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Minkyu Kang <mk7.kang@samsung.com>
Cc: Vladimir Zapolskiy <vz@mleia.com>
---
 drivers/gpio/s3c2440_gpio.c | 75 +++++++++++++++++++++++++--------------------
 1 file changed, 42 insertions(+), 33 deletions(-)

diff --git a/drivers/gpio/s3c2440_gpio.c b/drivers/gpio/s3c2440_gpio.c
index e1e2d3f..d6c7eeb 100644
--- a/drivers/gpio/s3c2440_gpio.c
+++ b/drivers/gpio/s3c2440_gpio.c
@@ -8,53 +8,50 @@
 #include <asm/arch/s3c2440.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
+#include <errno.h>
 
 #define GPIO_INPUT  0x0
 #define GPIO_OUTPUT 0x1
 
-/* 0x4 means that we want DAT and not CON register */
-#define GPIO_PORT(x)	((((x) >> 5) & 0x3) + 0x4)
-#define GPIO_BIT(x)		((x) & 0x3f)
+#define S3C_GPIO_CON	0x0
+#define S3C_GPIO_DAT	0x4
 
-/*
- * It's how we calculate the full port address
- * We have to get the number of the port + 1 (Port A is at 0x56000001 ...)
- * We move it at the second digit, and finally we add 0x4 because we want
- * to modify GPIO DAT and not CON
- */
-#define GPIO_FULLPORT(x) (S3C24X0_GPIO_BASE | ((GPIO_PORT(gpio) + 1) << 1))
+static uint32_t s3c_gpio_get_bank_addr(unsigned gpio)
+{
+	/* There is up to 16 pins per bank, one bank is 0x10 big. */
+	uint32_t addr = gpio & ~0xf;
+
+	if (addr >= 0x80 && addr != 0xd0) {	/* Wrong GPIO bank. */
+		printf("Invalid GPIO bank (bank %02x)\n", addr);
+		return 0xffffffff;
+	}
+
+	return addr | S3C24X0_GPIO_BASE;
+}
 
 int gpio_set_value(unsigned gpio, int value)
 {
-	unsigned l = readl(GPIO_FULLPORT(gpio));
-	unsigned bit;
-	unsigned port = GPIO_FULLPORT(gpio);
-
-	/*
-	 * All GPIO Port have a configuration on
-	 * 2 bits excepted the first GPIO (A) which
-	 * have only 1 bit of configuration.
-	 */
-	if (!GPIO_PORT(gpio))
-		bit = (0x1 << GPIO_BIT(gpio));
-	else
-		bit = (0x3 << GPIO_BIT(gpio));
+	uint32_t addr = s3c_gpio_get_bank_addr(gpio);
+
+	if (addr == 0xffffffff)
+		return -EINVAL;
 
 	if (value)
-		l |= bit;
+		setbits_le32(addr | S3C_GPIO_DAT, 1 << (gpio & 0xf));
 	else
-		l &= ~bit;
+		clrbits_le32(addr | S3C_GPIO_DAT, 1 << (gpio & 0xf));
 
-	return writel(l, port);
+	return 0;
 }
 
 int gpio_get_value(unsigned gpio)
 {
-	unsigned l = readl(GPIO_FULLPORT(gpio));
+	uint32_t addr = s3c_gpio_get_bank_addr(gpio);
+
+	if (addr == 0xffffffff)
+		return -EINVAL;
 
-	if (GPIO_PORT(gpio) == 0) /* PORT A */
-		return (l >> GPIO_BIT(gpio)) & 0x1;
-	return (l >> GPIO_BIT(gpio)) & 0x3;
+	return !!(readl(addr | S3C_GPIO_DAT) & (1 << (gpio & 0xf)));
 }
 
 int gpio_request(unsigned gpio, const char *label)
@@ -67,13 +64,25 @@ int gpio_free(unsigned gpio)
 	return 0;
 }
 
+static int s3c_gpio_direction(unsigned gpio, uint8_t dir)
+{
+	uint32_t addr = s3c_gpio_get_bank_addr(gpio);
+	const uint32_t mask = 0x3 << ((gpio & 0xf) << 1);
+	const uint32_t dirm = dir << ((gpio & 0xf) << 1);
+
+	if (addr == 0xffffffff)
+		return -EINVAL;
+
+	clrsetbits_le32(addr | S3C_GPIO_CON, mask, dirm);
+	return 0;
+}
+
 int gpio_direction_input(unsigned gpio)
 {
-	return writel(GPIO_INPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio));
+	return s3c_gpio_direction(gpio, GPIO_INPUT);
 }
 
 int gpio_direction_output(unsigned gpio, int value)
 {
-	writel(GPIO_OUTPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio));
-	return gpio_set_value(gpio, value);
+	return s3c_gpio_direction(gpio, GPIO_OUTPUT);
 }
-- 
2.1.1

  parent reply	other threads:[~2014-10-11 16:42 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-11 16:42 [U-Boot] [PATCH 01/10] video: Add S3C24xx framebuffer support Marek Vasut
2014-10-11 16:42 ` [U-Boot] [PATCH 02/10] arm: s3c24xx: Fix incorrect CONFIG_SYS_S3C2410_NAND_HWECC name Marek Vasut
2014-11-27  2:03   ` [U-Boot] [U-Boot, " Scott Wood
2015-05-02  0:46     ` Marek Vasut
2015-05-02  1:11       ` Scott Wood
2015-05-02  1:18         ` Marek Vasut
2015-05-02  3:41           ` Scott Wood
2014-10-11 16:42 ` [U-Boot] [PATCH 03/10] mtd: nand: s3c: Fix data type width in debug() Marek Vasut
2014-11-27  2:06   ` [U-Boot] [U-Boot, " Scott Wood
2014-10-11 16:42 ` [U-Boot] [PATCH 04/10] mtd: nand: s3c: Unify the register definition and naming Marek Vasut
2014-10-11 16:42 ` [U-Boot] [PATCH 05/10] mtd: nand: s3c: Add S3C2440 specifics Marek Vasut
2014-11-27  2:20   ` [U-Boot] [U-Boot,05/10] " Scott Wood
2015-05-02  0:48     ` Marek Vasut
2015-05-02  1:05       ` Scott Wood
2014-10-11 16:42 ` [U-Boot] [PATCH 06/10] mtd: nand: s3c: Add S3C2440 buffer reading Marek Vasut
2014-10-11 16:42 ` [U-Boot] [PATCH 07/10] mtd: nand: s3c: Add missing correction and select_chip functions Marek Vasut
2014-10-28 22:45   ` Scott Wood
2016-01-14  1:41     ` Marek Vasut
2016-02-12 23:18       ` Scott Wood
2016-02-19 17:53         ` Marek Vasut
2016-02-19 17:54           ` Scott Wood
2014-10-11 16:42 ` [U-Boot] [PATCH 08/10] i2c: s3c: Implant support for S3C2440 Marek Vasut
2015-05-02  1:12   ` Marek Vasut
2015-05-06  8:02     ` Minkyu Kang
2014-10-11 16:42 ` Marek Vasut [this message]
2015-05-02  1:12   ` [U-Boot] [PATCH 09/10] gpio: s3c: Fix the GPIO driver Marek Vasut
2015-05-06  8:02     ` Minkyu Kang
2014-10-11 16:42 ` [U-Boot] [PATCH 10/10] net: smc911x: Keep MAC programmed Marek Vasut
2014-11-10 21:29   ` [U-Boot] [U-Boot,10/10] " Tom Rini
2014-10-16  9:28 ` [U-Boot] [PATCH 01/10] video: Add S3C24xx framebuffer support Anatolij Gustschin
2015-05-02  1:12   ` Marek Vasut
2016-02-19 18:02     ` Anatolij Gustschin
2016-02-19 18:37       ` Marek Vasut
2016-02-22 17:10 ` Anatolij Gustschin

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=1413045778-5690-9-git-send-email-marex@denx.de \
    --to=marex@denx.de \
    --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.