* [RESEND] gpio: introduce it8761e_gpio driver for IT8761E Super I/O chip @ 2010-02-28 8:54 Denis Turischev 2010-03-02 22:40 ` Andrew Morton 2010-06-30 15:23 ` [PATCH 1/2] gpio: SIO IT8761, Poulsbo SCH are I/O mapped Denis Turischev 0 siblings, 2 replies; 8+ messages in thread From: Denis Turischev @ 2010-02-28 8:54 UTC (permalink / raw) To: LKML, David Brownell; +Cc: Andrew Morton Signed-off-by: Denis Turischev <denis@compulab.co.il> --- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/it8761e_gpio.c | 231 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/it8761e_gpio.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1730068..3c9e5ed 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -101,6 +101,12 @@ config GPIO_SCH This driver can also be built as a module. If so, the module will be called sch-gpio. +config GPIO_IT8761E + tristate "IT8761E GPIO support" + depends on GPIOLIB + help + Say yes here to support GPIO functionality of IT8761E super I/O chip. + comment "I2C GPIO expanders:" config GPIO_MAX732X diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index aa1d06e..4adf128 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o obj-$(CONFIG_GPIO_SCH) += sch_gpio.o +obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c new file mode 100644 index 0000000..753219c --- /dev/null +++ b/drivers/gpio/it8761e_gpio.c @@ -0,0 +1,231 @@ +/* + * it8761_gpio.c - GPIO interface for IT8761E 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 SIO_CHIP_ID 0x8761 +#define CHIP_ID_HIGH_BYTE 0x20 +#define CHIP_ID_LOW_BYTE 0x21 + +static u8 ports[2] = { 0x2e, 0x4e }; +static u8 port; + +static DEFINE_SPINLOCK(sio_lock); + +#define GPIO_NAME "it8761-gpio" +#define GPIO_BA_HIGH_BYTE 0x60 +#define GPIO_BA_LOW_BYTE 0x61 +#define GPIO_IOSIZE 4 +#define GPIO1X_IO 0xf0 +#define GPIO2X_IO 0xf1 + +static u16 gpio_ba; + +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(0x61, port); + outb(0x55, port); + outb((port == 0x2e) ? 0x55 : 0xaa, port); +} + +static void exit_conf_mode(u8 port) +{ + outb(0x2, port); + outb(0x2, port + 1); +} + +static void enter_gpio_mode(u8 port) +{ + write_reg(0x2, 0x7, port); +} + +static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) +{ + u16 reg; + u8 bit; + + bit = gpio_num % 7; + reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + + return !!(inb(reg) & (1 << bit)); +} + +static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) +{ + u8 curr_dirs; + u8 io_reg, bit; + + bit = gpio_num % 7; + io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + + spin_lock(&sio_lock); + + enter_conf_mode(port); + enter_gpio_mode(port); + + curr_dirs = read_reg(io_reg, port); + + if (curr_dirs & (1 << bit)) + write_reg(curr_dirs & ~(1 << bit), io_reg, port); + + exit_conf_mode(port); + + spin_unlock(&sio_lock); + return 0; +} + +static void it8761e_gpio_set(struct gpio_chip *gc, + unsigned gpio_num, int val) +{ + u8 curr_vals, bit; + u16 reg; + + bit = gpio_num % 7; + reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + + spin_lock(&sio_lock); + + curr_vals = inb(reg); + if (val) + outb(curr_vals | (1 << bit) , reg); + else + outb(curr_vals & ~(1 << bit), reg); + + spin_unlock(&sio_lock); +} + +static int it8761e_gpio_direction_out(struct gpio_chip *gc, + unsigned gpio_num, int val) +{ + u8 curr_dirs, io_reg, bit; + + bit = gpio_num % 7; + io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + + it8761e_gpio_set(gc, gpio_num, val); + + spin_lock(&sio_lock); + + enter_conf_mode(port); + enter_gpio_mode(port); + + curr_dirs = read_reg(io_reg, port); + + if (!(curr_dirs & (1 << bit))) + write_reg(curr_dirs | (1 << bit), io_reg, port); + + exit_conf_mode(port); + + spin_unlock(&sio_lock); + return 0; +} + +static struct gpio_chip it8761e_gpio_chip = { + .label = GPIO_NAME, + .owner = THIS_MODULE, + .get = it8761e_gpio_get, + .direction_input = it8761e_gpio_direction_in, + .set = it8761e_gpio_set, + .direction_output = it8761e_gpio_direction_out, +}; + +static int __init it8761e_gpio_init(void) +{ + int i, id, err; + + /* chip and port detection */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + spin_lock(&sio_lock); + enter_conf_mode(ports[i]); + + id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) + + read_reg(CHIP_ID_LOW_BYTE, ports[i]); + + exit_conf_mode(ports[i]); + spin_unlock(&sio_lock); + + if (id == SIO_CHIP_ID) { + port = ports[i]; + break; + } + } + + if (!port) + return -ENODEV; + + /* fetch GPIO base address */ + enter_conf_mode(port); + enter_gpio_mode(port); + gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) + + read_reg(GPIO_BA_LOW_BYTE, port); + exit_conf_mode(port); + + if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME)) + return -EBUSY; + + it8761e_gpio_chip.base = -1; + it8761e_gpio_chip.ngpio = 14; + + err = gpiochip_add(&it8761e_gpio_chip); + if (err < 0) + goto gpiochip_add_err; + + return 0; + +gpiochip_add_err: + release_region(gpio_ba, GPIO_IOSIZE); + gpio_ba = 0; + return err; +} + +static void __exit it8761e_gpio_exit(void) +{ + if (gpio_ba) { + gpiochip_remove(&it8761e_gpio_chip); + + release_region(gpio_ba, GPIO_IOSIZE); + gpio_ba = 0; + } +} +module_init(it8761e_gpio_init); +module_exit(it8761e_gpio_exit); + +MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); +MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip"); +MODULE_LICENSE("GPL"); -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [RESEND] gpio: introduce it8761e_gpio driver for IT8761E Super I/O chip 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-06-30 15:23 ` [PATCH 1/2] gpio: SIO IT8761, Poulsbo SCH are I/O mapped Denis Turischev 1 sibling, 1 reply; 8+ messages in thread From: Andrew Morton @ 2010-03-02 22:40 UTC (permalink / raw) To: Denis Turischev; +Cc: LKML, David Brownell On Sun, 28 Feb 2010 10:54:12 +0200 Denis Turischev <denis@compulab.co.il> wrote: > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -101,6 +101,12 @@ config GPIO_SCH > This driver can also be built as a module. If so, the module > will be called sch-gpio. > > +config GPIO_IT8761E > + tristate "IT8761E GPIO support" > + depends on GPIOLIB > + help > + Say yes here to support GPIO functionality of IT8761E super I/O chip. > + The comment said "put expanders in the right section, in alphabetical order". It wasn't in alphabetical order ;) Is this a "Memory mapped GPIO expander"? Looks like it's IO-mapped, but there isn't a section in Kconfig for that. PCI mapped? ^ permalink raw reply [flat|nested] 8+ messages in thread
* it8761e_gpio: Fixed bug in gpio numbering 2010-03-02 22:40 ` Andrew Morton @ 2010-03-17 10:09 ` Denis Turischev 2010-04-28 8:24 ` Denis Turischev 0 siblings, 1 reply; 8+ messages in thread From: Denis Turischev @ 2010-03-17 10:09 UTC (permalink / raw) To: LKML; +Cc: David Brownell Signed-off-by: Denis Turischev <denis@compulab.co.il> --- drivers/gpio/it8761e_gpio.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c index 753219c..41a9388 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/it8761e_gpio.c @@ -80,8 +80,8 @@ static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) u16 reg; u8 bit; - bit = gpio_num % 7; - reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + bit = gpio_num % 8; + reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; return !!(inb(reg) & (1 << bit)); } @@ -91,8 +91,8 @@ static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) u8 curr_dirs; u8 io_reg, bit; - bit = gpio_num % 7; - io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + bit = gpio_num % 8; + io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; spin_lock(&sio_lock); @@ -116,8 +116,8 @@ static void it8761e_gpio_set(struct gpio_chip *gc, u8 curr_vals, bit; u16 reg; - bit = gpio_num % 7; - reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + bit = gpio_num % 8; + reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; spin_lock(&sio_lock); @@ -135,8 +135,8 @@ static int it8761e_gpio_direction_out(struct gpio_chip *gc, { u8 curr_dirs, io_reg, bit; - bit = gpio_num % 7; - io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + bit = gpio_num % 8; + io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; it8761e_gpio_set(gc, gpio_num, val); @@ -200,7 +200,7 @@ static int __init it8761e_gpio_init(void) return -EBUSY; it8761e_gpio_chip.base = -1; - it8761e_gpio_chip.ngpio = 14; + it8761e_gpio_chip.ngpio = 16; err = gpiochip_add(&it8761e_gpio_chip); if (err < 0) -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* it8761e_gpio: Fixed bug in gpio numbering 2010-03-17 10:09 ` it8761e_gpio: Fixed bug in gpio numbering Denis Turischev @ 2010-04-28 8:24 ` Denis Turischev 0 siblings, 0 replies; 8+ messages in thread From: Denis Turischev @ 2010-04-28 8:24 UTC (permalink / raw) To: LKML; +Cc: David Brownell, Andrew Morton SIO chip contains 16 possible gpio lines, not 14. Schematic just was not read carefully. Signed-off-by: Denis Turischev <denis@compulab.co.il> --- drivers/gpio/it8761e_gpio.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c index 753219c..41a9388 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/it8761e_gpio.c @@ -80,8 +80,8 @@ static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) u16 reg; u8 bit; - bit = gpio_num % 7; - reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + bit = gpio_num % 8; + reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; return !!(inb(reg) & (1 << bit)); } @@ -91,8 +91,8 @@ static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) u8 curr_dirs; u8 io_reg, bit; - bit = gpio_num % 7; - io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + bit = gpio_num % 8; + io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; spin_lock(&sio_lock); @@ -116,8 +116,8 @@ static void it8761e_gpio_set(struct gpio_chip *gc, u8 curr_vals, bit; u16 reg; - bit = gpio_num % 7; - reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + bit = gpio_num % 8; + reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; spin_lock(&sio_lock); @@ -135,8 +135,8 @@ static int it8761e_gpio_direction_out(struct gpio_chip *gc, { u8 curr_dirs, io_reg, bit; - bit = gpio_num % 7; - io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + bit = gpio_num % 8; + io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; it8761e_gpio_set(gc, gpio_num, val); @@ -200,7 +200,7 @@ static int __init it8761e_gpio_init(void) return -EBUSY; it8761e_gpio_chip.base = -1; - it8761e_gpio_chip.ngpio = 14; + it8761e_gpio_chip.ngpio = 16; err = gpiochip_add(&it8761e_gpio_chip); if (err < 0) -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/2] gpio: SIO IT8761, Poulsbo SCH are I/O mapped 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-06-30 15:23 ` Denis Turischev 2010-06-30 16:17 ` [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip Denis Turischev 1 sibling, 1 reply; 8+ messages in thread From: Denis Turischev @ 2010-06-30 15:23 UTC (permalink / raw) To: LKML; +Cc: David Brownell Super I/O IT8761 and Poulsbo SCH expanders look like I/O mapped and not memory mapped. Signed-off-by: Denis Turischev <denis@compulab.co.il> --- drivers/gpio/Kconfig | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 724038d..f666023 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -70,12 +70,6 @@ config GPIO_MAX730X comment "Memory mapped GPIO expanders:" -config GPIO_IT8761E - tristate "IT8761E GPIO support" - depends on GPIOLIB - help - Say yes here to support GPIO functionality of IT8761E super I/O chip. - config GPIO_PL061 bool "PrimeCell PL061 GPIO support" depends on ARM_AMBA @@ -94,6 +88,14 @@ config GPIO_VR41XX help Say yes here to support the NEC VR4100 series General-purpose I/O Uint +comment "I/O mapped GPIO expanders:" + +config GPIO_IT8761E + tristate "IT8761E GPIO support" + depends on GPIOLIB + help + Say yes here to support GPIO functionality of IT8761E super I/O chip. + config GPIO_SCH tristate "Intel SCH GPIO" depends on GPIOLIB && PCI -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip. 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 2010-06-30 16:37 ` David Brownell 0 siblings, 1 reply; 8+ messages in thread From: Denis Turischev @ 2010-06-30 16:17 UTC (permalink / raw) To: LKML; +Cc: David Brownell 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 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip. 2010-06-30 16:17 ` [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip Denis Turischev @ 2010-06-30 16:37 ` David Brownell 2010-07-01 10:06 ` Denis Turischev 0 siblings, 1 reply; 8+ messages in thread From: David Brownell @ 2010-06-30 16:37 UTC (permalink / raw) To: LKML, Denis Turischev My first reaction is that this whole chip, including its GPIO support, would best live in drivers/mfd like various other multi-function devices. I'm trying to avoid cluttering drivers/gpio with fragments of chip support that don't stand on their own... ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip. 2010-06-30 16:37 ` David Brownell @ 2010-07-01 10:06 ` Denis Turischev 0 siblings, 0 replies; 8+ messages in thread From: Denis Turischev @ 2010-07-01 10:06 UTC (permalink / raw) To: David Brownell; +Cc: LKML If so as it8761e_gpio must be moved to drivers/mfd too. On 06/30/2010 07:37 PM, David Brownell wrote: > My first reaction is that this whole chip, including > its GPIO support, would best live in drivers/mfd like > various other multi-function devices. > > I'm trying to avoid cluttering drivers/gpio with fragments of chip support that don't stand on their own... > > -- Denis ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-07-01 10:05 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 ` [PATCH 2/2] gpio: introduce f71808e_gpio driver for F71808E Super I/O chip Denis Turischev 2010-06-30 16:37 ` David Brownell 2010-07-01 10:06 ` Denis Turischev
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox