All of lore.kernel.org
 help / color / mirror / Atom feed
From: Denis Turischev <denis@compulab.co.il>
To: LKML <linux-kernel@vger.kernel.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Subject: [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip.
Date: Wed, 30 Jun 2010 19:17:35 +0300	[thread overview]
Message-ID: <4C2B6E1F.80004@compulab.co.il> (raw)
In-Reply-To: <4C2B616F.90803@compulab.co.il>

Signed-off-by: Denis Turischev <denis@compulab.co.il>

---
 drivers/gpio/Kconfig        |    6 +
 drivers/gpio/Makefile       |    1 +
 drivers/gpio/f71808e_gpio.c |  284 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 291 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpio/f71808e_gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f666023..475e846 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -96,6 +96,12 @@ config GPIO_IT8761E
 	help
 	  Say yes here to support GPIO functionality of IT8761E super I/O chip.

+config GPIO_F71808E
+	tristate "F71808E GPIO support"
+	depends on GPIOLIB
+	help
+	  Say yes here to support GPIO functionality of F71808E super I/O chip.
+
 config GPIO_SCH
 	tristate "Intel SCH GPIO"
 	depends on GPIOLIB && PCI
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 51c3cdd..cb4dd30 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_GPIO_WM8994)	+= wm8994-gpio.o
 obj-$(CONFIG_GPIO_SCH)		+= sch_gpio.o
 obj-$(CONFIG_GPIO_RDC321X)	+= rdc321x-gpio.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= janz-ttl.o
+obj-$(CONFIG_GPIO_F71808E)	+= f71808e_gpio.o
diff --git a/drivers/gpio/f71808e_gpio.c b/drivers/gpio/f71808e_gpio.c
new file mode 100644
index 0000000..8ccdd9f
--- /dev/null
+++ b/drivers/gpio/f71808e_gpio.c
@@ -0,0 +1,284 @@
+/*
+ *  f71808e_gpio.c - GPIO interface for f71808E Super I/O chip
+ *
+ *  Author: Denis Turischev <denis@compulab.co.il>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+#include <linux/gpio.h>
+
+#define GPIO_NAME		"f71808-gpio"
+
+#define CHIP_ID			0x0901
+#define VENDOR_ID		0x3219
+
+#define LDN			0x07
+#define CR_GPIO			0x06
+
+#define CHIP_ID_HIGH_BYTE	0x20
+#define CHIP_ID_LOW_BYTE	0x21
+#define VENDOR_ID_HIGH_BYTE	0x22
+#define VENDOR_ID_LOW_BYTE	0x23
+
+static u8 ports[2] = { 0x2e, 0x4e };
+static u8 port;
+
+static DEFINE_SPINLOCK(sio_lock);
+
+
+static u8 read_reg(u8 addr, u8 port)
+{
+	outb(addr, port);
+	return inb(port + 1);
+}
+
+static void write_reg(u8 data, u8 addr, u8 port)
+{
+	outb(addr, port);
+	outb(data, port + 1);
+}
+
+static void enter_conf_mode(u8 port)
+{
+	outb(0x87, port);
+	outb(0x87, port);
+}
+
+static void exit_conf_mode(u8 port)
+{
+	outb(0xaa, port);
+}
+
+static void enter_gpio_mode(u8 port)
+{
+	write_reg(CR_GPIO, LDN, port);
+}
+
+static int f71808e_gpio_rename(unsigned gpio_num)
+{
+	/* [0-7] -> [0-7] */
+	if (gpio_num <= 7)
+		return gpio_num;
+
+	/*  [8-12] -> [10-14]*/
+	if (gpio_num <= 12)
+		return gpio_num + 2;
+
+	/* [13-20] -> [20-27] */
+	if (gpio_num <= 20)
+		return gpio_num + 7;
+
+	/* [21-25] -> [30-34] */
+	return gpio_num + 9;
+}
+
+static int f71808e_gpio_direction_in(struct gpio_chip *gc, unsigned _gpio_num)
+{
+	unsigned gpio_num;
+	u8 curr_vals, reg, bit;
+
+	gpio_num = f71808e_gpio_rename(_gpio_num);
+
+	bit = gpio_num % 10;
+	reg = 0xf0 - (gpio_num / 10) * 0x10;
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_vals = read_reg(reg, port);
+
+	if (curr_vals & (1 << bit))
+		write_reg(curr_vals & ~(1 << bit), reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+
+	return 0;
+}
+
+static int f71808e_gpio_direction_out(struct gpio_chip *gc,
+					unsigned _gpio_num, int val)
+{
+	unsigned gpio_num;
+	u8 curr_vals, reg, bit;
+
+	gpio_num = f71808e_gpio_rename(_gpio_num);
+
+	bit = gpio_num % 10;
+	reg = 0xf0 - (gpio_num / 10) * 0x10;
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_vals = read_reg(reg, port);
+
+	if (!(curr_vals & (1 << bit)))
+		write_reg(curr_vals | (1 << bit), reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+	return 0;
+}
+
+static int f71808e_gpio_get(struct gpio_chip *gc, unsigned _gpio_num)
+{
+	unsigned gpio_num, res;
+	u8 reg, bit;
+
+	gpio_num = f71808e_gpio_rename(_gpio_num);
+
+	bit = gpio_num % 10;
+	reg = 0xf2 - (gpio_num / 10) * 0x10;
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	res = !!(read_reg(reg, port) & (1 << bit));
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+
+	return res;
+}
+
+static void f71808e_gpio_set(struct gpio_chip *gc,
+				unsigned _gpio_num, int val)
+{
+	unsigned gpio_num;
+	u8 curr_vals, reg, bit;
+
+	gpio_num = f71808e_gpio_rename(_gpio_num);
+
+	bit = gpio_num % 10;
+	reg = 0xf1 - (gpio_num / 10) * 0x10;
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_vals = read_reg(reg, port);
+
+	if (val)
+		write_reg(curr_vals | (1 << bit), reg, port);
+	else
+		write_reg(curr_vals & ~(1 << bit), reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+}
+
+static struct gpio_chip f71808e_gpio_chip = {
+	.label			= GPIO_NAME,
+	.owner			= THIS_MODULE,
+	.get			= f71808e_gpio_get,
+	.direction_input	= f71808e_gpio_direction_in,
+	.set			= f71808e_gpio_set,
+	.direction_output	= f71808e_gpio_direction_out,
+};
+
+static int __init f71808e_gpio_init(void)
+{
+	int i, chip_id, vendor_id, err;
+	u8 io_reg, curr_vals;
+
+	/* chip and port detection */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		spin_lock(&sio_lock);
+		enter_conf_mode(ports[i]);
+
+		chip_id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
+				read_reg(CHIP_ID_LOW_BYTE, ports[i]);
+
+		vendor_id = (read_reg(VENDOR_ID_HIGH_BYTE, ports[i]) << 8) +
+				read_reg(VENDOR_ID_LOW_BYTE, ports[i]);
+
+		exit_conf_mode(ports[i]);
+		spin_unlock(&sio_lock);
+
+		if ((chip_id == CHIP_ID) && (vendor_id == VENDOR_ID)) {
+			port = ports[i];
+			break;
+		}
+	}
+
+	if (!port)
+		return -ENODEV;
+
+	/* Enable all pins with GPIO capability */
+	/* By default we enable all possible GPIOs on the chip */
+	spin_lock(&sio_lock);
+	enter_conf_mode(port);
+
+	/* Enable GPIO30 and GPIO31 */
+	io_reg = 0x27;
+	curr_vals = read_reg(io_reg, port);
+	write_reg(curr_vals & 0xfe, io_reg, port);
+
+	/* Enable GPIO[0-7], GPIO30, GPIO31, GPIO34 */
+	io_reg = 0x29;
+	write_reg(0xff, io_reg, port);
+
+	/* Enable GPIO[10-14], GPIO21, GPIO23 */
+	io_reg = 0x2a;
+	write_reg(0x13, io_reg, port);
+
+	/* Enable GPIO[20-27] */
+	io_reg = 0x2b;
+	write_reg(0xff, io_reg, port);
+
+	exit_conf_mode(port);
+	spin_unlock(&sio_lock);
+
+	f71808e_gpio_chip.base = -1;
+	f71808e_gpio_chip.ngpio = 26;
+
+	err = gpiochip_add(&f71808e_gpio_chip);
+	if (err < 0)
+		goto gpiochip_add_err;
+
+	return 0;
+
+gpiochip_add_err:
+	return err;
+}
+
+static void __exit f71808e_gpio_exit(void)
+{
+	gpiochip_remove(&f71808e_gpio_chip);
+}
+module_init(f71808e_gpio_init);
+module_exit(f71808e_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for F71808E Super I/O chip");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4

  reply	other threads:[~2010-06-30 16:16 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-28  8:54 [RESEND] gpio: introduce it8761e_gpio driver for IT8761E Super I/O chip Denis Turischev
2010-03-02 22:40 ` Andrew Morton
2010-03-17 10:09   ` it8761e_gpio: Fixed bug in gpio numbering Denis Turischev
2010-04-28  8:24     ` Denis Turischev
2010-06-30 15:23 ` [PATCH 1/2] gpio: SIO IT8761, Poulsbo SCH are I/O mapped Denis Turischev
2010-06-30 16:17   ` Denis Turischev [this message]
2010-06-30 16:37     ` [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip David Brownell
2010-07-01 10:06       ` Denis Turischev

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=4C2B6E1F.80004@compulab.co.il \
    --to=denis@compulab.co.il \
    --cc=dbrownell@users.sourceforge.net \
    --cc=linux-kernel@vger.kernel.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.