19cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev/* 2c103de240439dfee24ac50eb99c8be3a30d13323Grant Likely * GPIO interface for IT8761E Super I/O chip 39cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * 49cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * Author: Denis Turischev <denis@compulab.co.il> 59cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * 69cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * This program is free software; you can redistribute it and/or modify 79cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * it under the terms of the GNU General Public License 2 as published 89cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * by the Free Software Foundation. 99cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * 109cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * This program is distributed in the hope that it will be useful, 119cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * but WITHOUT ANY WARRANTY; without even the implied warranty of 129cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 139cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * GNU General Public License for more details. 149cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * 159cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * You should have received a copy of the GNU General Public License 169cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * along with this program; see the file COPYING. If not, write to 179cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 189cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev */ 199cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 209cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/init.h> 219cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/kernel.h> 229cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/module.h> 239cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/io.h> 249cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/errno.h> 259cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/ioport.h> 269cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 279cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#include <linux/gpio.h> 289cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 299cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define SIO_CHIP_ID 0x8761 309cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define CHIP_ID_HIGH_BYTE 0x20 319cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define CHIP_ID_LOW_BYTE 0x21 329cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 339cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic u8 ports[2] = { 0x2e, 0x4e }; 349cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic u8 port; 359cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 369cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic DEFINE_SPINLOCK(sio_lock); 379cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 389cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define GPIO_NAME "it8761-gpio" 399cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define GPIO_BA_HIGH_BYTE 0x60 409cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define GPIO_BA_LOW_BYTE 0x61 419cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define GPIO_IOSIZE 4 429cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define GPIO1X_IO 0xf0 439cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev#define GPIO2X_IO 0xf1 449cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 459cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic u16 gpio_ba; 469cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 479cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic u8 read_reg(u8 addr, u8 port) 489cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 499cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(addr, port); 509cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return inb(port + 1); 519cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 529cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 539cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic void write_reg(u8 data, u8 addr, u8 port) 549cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 559cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(addr, port); 569cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(data, port + 1); 579cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 589cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 599cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic void enter_conf_mode(u8 port) 609cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 619cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(0x87, port); 629cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(0x61, port); 639cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(0x55, port); 649cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb((port == 0x2e) ? 0x55 : 0xaa, port); 659cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 669cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 679cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic void exit_conf_mode(u8 port) 689cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 699cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(0x2, port); 709cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(0x2, port + 1); 719cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 729cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 739cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic void enter_gpio_mode(u8 port) 749cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 759cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev write_reg(0x2, 0x7, port); 769cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 779cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 789cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) 799cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 809cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u16 reg; 819cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u8 bit; 829cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 833c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev bit = gpio_num % 8; 843c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; 859cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 869cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return !!(inb(reg) & (1 << bit)); 879cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 889cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 899cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) 909cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 919cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u8 curr_dirs; 929cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u8 io_reg, bit; 939cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 943c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev bit = gpio_num % 8; 953c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; 969cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 979cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_lock(&sio_lock); 989cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 999cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_conf_mode(port); 1009cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_gpio_mode(port); 1019cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1029cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev curr_dirs = read_reg(io_reg, port); 1039cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1049cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (curr_dirs & (1 << bit)) 1059cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev write_reg(curr_dirs & ~(1 << bit), io_reg, port); 1069cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1079cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev exit_conf_mode(port); 1089cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1099cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_unlock(&sio_lock); 1109cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return 0; 1119cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 1129cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1139cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic void it8761e_gpio_set(struct gpio_chip *gc, 1149cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev unsigned gpio_num, int val) 1159cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 1169cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u8 curr_vals, bit; 1179cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u16 reg; 1189cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1193c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev bit = gpio_num % 8; 1203c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; 1219cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1229cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_lock(&sio_lock); 1239cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1249cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev curr_vals = inb(reg); 1259cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (val) 1269cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(curr_vals | (1 << bit) , reg); 1279cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev else 1289cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev outb(curr_vals & ~(1 << bit), reg); 1299cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1309cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_unlock(&sio_lock); 1319cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 1329cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1339cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic int it8761e_gpio_direction_out(struct gpio_chip *gc, 1349cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev unsigned gpio_num, int val) 1359cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 1369cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev u8 curr_dirs, io_reg, bit; 1379cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1383c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev bit = gpio_num % 8; 1393c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; 1409cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1419cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev it8761e_gpio_set(gc, gpio_num, val); 1429cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1439cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_lock(&sio_lock); 1449cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1459cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_conf_mode(port); 1469cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_gpio_mode(port); 1479cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1489cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev curr_dirs = read_reg(io_reg, port); 1499cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1509cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (!(curr_dirs & (1 << bit))) 1519cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev write_reg(curr_dirs | (1 << bit), io_reg, port); 1529cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1539cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev exit_conf_mode(port); 1549cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1559cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_unlock(&sio_lock); 1569cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return 0; 1579cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 1589cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1599cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic struct gpio_chip it8761e_gpio_chip = { 1609cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev .label = GPIO_NAME, 1619cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev .owner = THIS_MODULE, 1629cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev .get = it8761e_gpio_get, 1639cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev .direction_input = it8761e_gpio_direction_in, 1649cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev .set = it8761e_gpio_set, 1659cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev .direction_output = it8761e_gpio_direction_out, 1669cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev}; 1679cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1689cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic int __init it8761e_gpio_init(void) 1699cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 1709cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev int i, id, err; 1719cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1729cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev /* chip and port detection */ 1739cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev for (i = 0; i < ARRAY_SIZE(ports); i++) { 1749cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_lock(&sio_lock); 1759cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_conf_mode(ports[i]); 1769cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1779cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) + 1789cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev read_reg(CHIP_ID_LOW_BYTE, ports[i]); 1799cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1809cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev exit_conf_mode(ports[i]); 1819cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev spin_unlock(&sio_lock); 1829cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1839cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (id == SIO_CHIP_ID) { 1849cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev port = ports[i]; 1859cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev break; 1869cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev } 1879cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev } 1889cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1899cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (!port) 1909cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return -ENODEV; 1919cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1929cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev /* fetch GPIO base address */ 1939cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_conf_mode(port); 1949cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev enter_gpio_mode(port); 1959cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) + 1969cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev read_reg(GPIO_BA_LOW_BYTE, port); 1979cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev exit_conf_mode(port); 1989cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 1999cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME)) 2009cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return -EBUSY; 2019cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2029cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev it8761e_gpio_chip.base = -1; 2033c904afd7358e9ef515eb5df36b6f25c2b7fc2daDenis Turischev it8761e_gpio_chip.ngpio = 16; 2049cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2059cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev err = gpiochip_add(&it8761e_gpio_chip); 2069cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (err < 0) 2079cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev goto gpiochip_add_err; 2089cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2099cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return 0; 2109cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2119cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevgpiochip_add_err: 2129cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev release_region(gpio_ba, GPIO_IOSIZE); 2139cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev gpio_ba = 0; 2149cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev return err; 2159cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 2169cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2179cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevstatic void __exit it8761e_gpio_exit(void) 2189cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev{ 2199cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev if (gpio_ba) { 22048baa18b250d5e36ed9f9bb04cdf812d74da08caDaniel Mack int ret = gpiochip_remove(&it8761e_gpio_chip); 22148baa18b250d5e36ed9f9bb04cdf812d74da08caDaniel Mack 22248baa18b250d5e36ed9f9bb04cdf812d74da08caDaniel Mack WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n", 22348baa18b250d5e36ed9f9bb04cdf812d74da08caDaniel Mack __func__, ret); 2249cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2259cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev release_region(gpio_ba, GPIO_IOSIZE); 2269cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev gpio_ba = 0; 2279cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev } 2289cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev} 2299cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevmodule_init(it8761e_gpio_init); 2309cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischevmodule_exit(it8761e_gpio_exit); 2319cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis Turischev 2329cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis TurischevMODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); 2339cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis TurischevMODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip"); 2349cc0cb3c7d54f320b9eede6f4a49072ecadd864dDenis TurischevMODULE_LICENSE("GPL"); 235