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
next prev parent 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.