xref: /openbmc/linux/drivers/gpio/gpio-it87.c (revision 8fccdb58)
1b8664924SDiego Elio Pettenò /*
2b8664924SDiego Elio Pettenò  *  GPIO interface for IT87xx Super I/O chips
3b8664924SDiego Elio Pettenò  *
4b8664924SDiego Elio Pettenò  *  Author: Diego Elio Pettenò <flameeyes@flameeyes.eu>
5b8664924SDiego Elio Pettenò  *
6b8664924SDiego Elio Pettenò  *  Based on it87_wdt.c     by Oliver Schuster
7b8664924SDiego Elio Pettenò  *           gpio-it8761e.c by Denis Turischev
8b8664924SDiego Elio Pettenò  *           gpio-stmpe.c   by Rabin Vincent
9b8664924SDiego Elio Pettenò  *
10b8664924SDiego Elio Pettenò  *  This program is free software; you can redistribute it and/or modify
11b8664924SDiego Elio Pettenò  *  it under the terms of the GNU General Public License 2 as published
12b8664924SDiego Elio Pettenò  *  by the Free Software Foundation.
13b8664924SDiego Elio Pettenò  *
14b8664924SDiego Elio Pettenò  *  This program is distributed in the hope that it will be useful,
15b8664924SDiego Elio Pettenò  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16b8664924SDiego Elio Pettenò  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17b8664924SDiego Elio Pettenò  *  GNU General Public License for more details.
18b8664924SDiego Elio Pettenò  *
19b8664924SDiego Elio Pettenò  *  You should have received a copy of the GNU General Public License
20b8664924SDiego Elio Pettenò  *  along with this program; see the file COPYING.  If not, write to
21b8664924SDiego Elio Pettenò  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22b8664924SDiego Elio Pettenò  */
23b8664924SDiego Elio Pettenò 
24b8664924SDiego Elio Pettenò #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25b8664924SDiego Elio Pettenò 
26b8664924SDiego Elio Pettenò #include <linux/init.h>
27b8664924SDiego Elio Pettenò #include <linux/kernel.h>
28b8664924SDiego Elio Pettenò #include <linux/module.h>
29b8664924SDiego Elio Pettenò #include <linux/io.h>
30b8664924SDiego Elio Pettenò #include <linux/errno.h>
31b8664924SDiego Elio Pettenò #include <linux/ioport.h>
32b8664924SDiego Elio Pettenò #include <linux/slab.h>
33b8664924SDiego Elio Pettenò #include <linux/gpio.h>
34b8664924SDiego Elio Pettenò 
35b8664924SDiego Elio Pettenò /* Chip Id numbers */
36b8664924SDiego Elio Pettenò #define NO_DEV_ID	0xffff
378fccdb58SMartin Blumenstingl #define IT8620_ID	0x8620
388fccdb58SMartin Blumenstingl #define IT8628_ID	0x8628
39b8664924SDiego Elio Pettenò #define IT8728_ID	0x8728
40b8664924SDiego Elio Pettenò #define IT8732_ID	0x8732
41b8664924SDiego Elio Pettenò #define IT8761_ID	0x8761
42b8664924SDiego Elio Pettenò 
43b8664924SDiego Elio Pettenò /* IO Ports */
44b8664924SDiego Elio Pettenò #define REG		0x2e
45b8664924SDiego Elio Pettenò #define VAL		0x2f
46b8664924SDiego Elio Pettenò 
47b8664924SDiego Elio Pettenò /* Logical device Numbers LDN */
48b8664924SDiego Elio Pettenò #define GPIO		0x07
49b8664924SDiego Elio Pettenò 
50b8664924SDiego Elio Pettenò /* Configuration Registers and Functions */
51b8664924SDiego Elio Pettenò #define LDNREG		0x07
52b8664924SDiego Elio Pettenò #define CHIPID		0x20
53b8664924SDiego Elio Pettenò #define CHIPREV		0x22
54b8664924SDiego Elio Pettenò 
55b8664924SDiego Elio Pettenò /**
56b8664924SDiego Elio Pettenò  * struct it87_gpio - it87-specific GPIO chip
57b8664924SDiego Elio Pettenò  * @chip the underlying gpio_chip structure
58b8664924SDiego Elio Pettenò  * @lock a lock to avoid races between operations
59b8664924SDiego Elio Pettenò  * @io_base base address for gpio ports
60b8664924SDiego Elio Pettenò  * @io_size size of the port rage starting from io_base.
61b8664924SDiego Elio Pettenò  * @output_base Super I/O register address for Output Enable register
62b8664924SDiego Elio Pettenò  * @simple_base Super I/O 'Simple I/O' Enable register
63b8664924SDiego Elio Pettenò  * @simple_size Super IO 'Simple I/O' Enable register size; this is
64b8664924SDiego Elio Pettenò  *	required because IT87xx chips might only provide Simple I/O
65b8664924SDiego Elio Pettenò  *	switches on a subset of lines, whereas the others keep the
66b8664924SDiego Elio Pettenò  *	same status all time.
67b8664924SDiego Elio Pettenò  */
68b8664924SDiego Elio Pettenò struct it87_gpio {
69b8664924SDiego Elio Pettenò 	struct gpio_chip chip;
70b8664924SDiego Elio Pettenò 	spinlock_t lock;
71b8664924SDiego Elio Pettenò 	u16 io_base;
72b8664924SDiego Elio Pettenò 	u16 io_size;
73b8664924SDiego Elio Pettenò 	u8 output_base;
74b8664924SDiego Elio Pettenò 	u8 simple_base;
75b8664924SDiego Elio Pettenò 	u8 simple_size;
76b8664924SDiego Elio Pettenò };
77b8664924SDiego Elio Pettenò 
78b8664924SDiego Elio Pettenò static struct it87_gpio it87_gpio_chip = {
79b8664924SDiego Elio Pettenò 	.lock = __SPIN_LOCK_UNLOCKED(it87_gpio_chip.lock),
80b8664924SDiego Elio Pettenò };
81b8664924SDiego Elio Pettenò 
82b8664924SDiego Elio Pettenò /* Superio chip access functions; copied from wdt_it87 */
83b8664924SDiego Elio Pettenò 
84b8664924SDiego Elio Pettenò static inline int superio_enter(void)
85b8664924SDiego Elio Pettenò {
86b8664924SDiego Elio Pettenò 	/*
87b8664924SDiego Elio Pettenò 	 * Try to reserve REG and REG + 1 for exclusive access.
88b8664924SDiego Elio Pettenò 	 */
89b8664924SDiego Elio Pettenò 	if (!request_muxed_region(REG, 2, KBUILD_MODNAME))
90b8664924SDiego Elio Pettenò 		return -EBUSY;
91b8664924SDiego Elio Pettenò 
92b8664924SDiego Elio Pettenò 	outb(0x87, REG);
93b8664924SDiego Elio Pettenò 	outb(0x01, REG);
94b8664924SDiego Elio Pettenò 	outb(0x55, REG);
95b8664924SDiego Elio Pettenò 	outb(0x55, REG);
96b8664924SDiego Elio Pettenò 	return 0;
97b8664924SDiego Elio Pettenò }
98b8664924SDiego Elio Pettenò 
99b8664924SDiego Elio Pettenò static inline void superio_exit(void)
100b8664924SDiego Elio Pettenò {
101b8664924SDiego Elio Pettenò 	outb(0x02, REG);
102b8664924SDiego Elio Pettenò 	outb(0x02, VAL);
103b8664924SDiego Elio Pettenò 	release_region(REG, 2);
104b8664924SDiego Elio Pettenò }
105b8664924SDiego Elio Pettenò 
106b8664924SDiego Elio Pettenò static inline void superio_select(int ldn)
107b8664924SDiego Elio Pettenò {
108b8664924SDiego Elio Pettenò 	outb(LDNREG, REG);
109b8664924SDiego Elio Pettenò 	outb(ldn, VAL);
110b8664924SDiego Elio Pettenò }
111b8664924SDiego Elio Pettenò 
112b8664924SDiego Elio Pettenò static inline int superio_inb(int reg)
113b8664924SDiego Elio Pettenò {
114b8664924SDiego Elio Pettenò 	outb(reg, REG);
115b8664924SDiego Elio Pettenò 	return inb(VAL);
116b8664924SDiego Elio Pettenò }
117b8664924SDiego Elio Pettenò 
118b8664924SDiego Elio Pettenò static inline void superio_outb(int val, int reg)
119b8664924SDiego Elio Pettenò {
120b8664924SDiego Elio Pettenò 	outb(reg, REG);
121b8664924SDiego Elio Pettenò 	outb(val, VAL);
122b8664924SDiego Elio Pettenò }
123b8664924SDiego Elio Pettenò 
124b8664924SDiego Elio Pettenò static inline int superio_inw(int reg)
125b8664924SDiego Elio Pettenò {
126b8664924SDiego Elio Pettenò 	int val;
127b8664924SDiego Elio Pettenò 
128b8664924SDiego Elio Pettenò 	outb(reg++, REG);
129b8664924SDiego Elio Pettenò 	val = inb(VAL) << 8;
130b8664924SDiego Elio Pettenò 	outb(reg, REG);
131b8664924SDiego Elio Pettenò 	val |= inb(VAL);
132b8664924SDiego Elio Pettenò 	return val;
133b8664924SDiego Elio Pettenò }
134b8664924SDiego Elio Pettenò 
135b8664924SDiego Elio Pettenò static inline void superio_outw(int val, int reg)
136b8664924SDiego Elio Pettenò {
137b8664924SDiego Elio Pettenò 	outb(reg++, REG);
138b8664924SDiego Elio Pettenò 	outb(val >> 8, VAL);
139b8664924SDiego Elio Pettenò 	outb(reg, REG);
140b8664924SDiego Elio Pettenò 	outb(val, VAL);
141b8664924SDiego Elio Pettenò }
142b8664924SDiego Elio Pettenò 
143b8664924SDiego Elio Pettenò static inline void superio_set_mask(int mask, int reg)
144b8664924SDiego Elio Pettenò {
145b8664924SDiego Elio Pettenò 	u8 curr_val = superio_inb(reg);
146b8664924SDiego Elio Pettenò 	u8 new_val = curr_val | mask;
147b8664924SDiego Elio Pettenò 
148b8664924SDiego Elio Pettenò 	if (curr_val != new_val)
149b8664924SDiego Elio Pettenò 		superio_outb(new_val, reg);
150b8664924SDiego Elio Pettenò }
151b8664924SDiego Elio Pettenò 
152b8664924SDiego Elio Pettenò static inline void superio_clear_mask(int mask, int reg)
153b8664924SDiego Elio Pettenò {
154b8664924SDiego Elio Pettenò 	u8 curr_val = superio_inb(reg);
155b8664924SDiego Elio Pettenò 	u8 new_val = curr_val & ~mask;
156b8664924SDiego Elio Pettenò 
157b8664924SDiego Elio Pettenò 	if (curr_val != new_val)
158b8664924SDiego Elio Pettenò 		superio_outb(new_val, reg);
159b8664924SDiego Elio Pettenò }
160b8664924SDiego Elio Pettenò 
161b8664924SDiego Elio Pettenò static int it87_gpio_request(struct gpio_chip *chip, unsigned gpio_num)
162b8664924SDiego Elio Pettenò {
163b8664924SDiego Elio Pettenò 	u8 mask, group;
164b8664924SDiego Elio Pettenò 	int rc = 0;
1650a38fd94SLinus Walleij 	struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
166b8664924SDiego Elio Pettenò 
167b8664924SDiego Elio Pettenò 	mask = 1 << (gpio_num % 8);
168b8664924SDiego Elio Pettenò 	group = (gpio_num / 8);
169b8664924SDiego Elio Pettenò 
170b8664924SDiego Elio Pettenò 	spin_lock(&it87_gpio->lock);
171b8664924SDiego Elio Pettenò 
172b8664924SDiego Elio Pettenò 	rc = superio_enter();
173b8664924SDiego Elio Pettenò 	if (rc)
174b8664924SDiego Elio Pettenò 		goto exit;
175b8664924SDiego Elio Pettenò 
176b8664924SDiego Elio Pettenò 	/* not all the IT87xx chips support Simple I/O and not all of
177b8664924SDiego Elio Pettenò 	 * them allow all the lines to be set/unset to Simple I/O.
178b8664924SDiego Elio Pettenò 	 */
179b8664924SDiego Elio Pettenò 	if (group < it87_gpio->simple_size)
180b8664924SDiego Elio Pettenò 		superio_set_mask(mask, group + it87_gpio->simple_base);
181b8664924SDiego Elio Pettenò 
182b8664924SDiego Elio Pettenò 	/* clear output enable, setting the pin to input, as all the
183b8664924SDiego Elio Pettenò 	 * newly-exported GPIO interfaces are set to input.
184b8664924SDiego Elio Pettenò 	 */
185b8664924SDiego Elio Pettenò 	superio_clear_mask(mask, group + it87_gpio->output_base);
186b8664924SDiego Elio Pettenò 
187b8664924SDiego Elio Pettenò 	superio_exit();
188b8664924SDiego Elio Pettenò 
189b8664924SDiego Elio Pettenò exit:
190b8664924SDiego Elio Pettenò 	spin_unlock(&it87_gpio->lock);
191b8664924SDiego Elio Pettenò 	return rc;
192b8664924SDiego Elio Pettenò }
193b8664924SDiego Elio Pettenò 
194b8664924SDiego Elio Pettenò static int it87_gpio_get(struct gpio_chip *chip, unsigned gpio_num)
195b8664924SDiego Elio Pettenò {
196b8664924SDiego Elio Pettenò 	u16 reg;
197b8664924SDiego Elio Pettenò 	u8 mask;
1980a38fd94SLinus Walleij 	struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
199b8664924SDiego Elio Pettenò 
200b8664924SDiego Elio Pettenò 	mask = 1 << (gpio_num % 8);
201b8664924SDiego Elio Pettenò 	reg = (gpio_num / 8) + it87_gpio->io_base;
202b8664924SDiego Elio Pettenò 
203b8664924SDiego Elio Pettenò 	return !!(inb(reg) & mask);
204b8664924SDiego Elio Pettenò }
205b8664924SDiego Elio Pettenò 
206b8664924SDiego Elio Pettenò static int it87_gpio_direction_in(struct gpio_chip *chip, unsigned gpio_num)
207b8664924SDiego Elio Pettenò {
208b8664924SDiego Elio Pettenò 	u8 mask, group;
209b8664924SDiego Elio Pettenò 	int rc = 0;
2100a38fd94SLinus Walleij 	struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
211b8664924SDiego Elio Pettenò 
212b8664924SDiego Elio Pettenò 	mask = 1 << (gpio_num % 8);
213b8664924SDiego Elio Pettenò 	group = (gpio_num / 8);
214b8664924SDiego Elio Pettenò 
215b8664924SDiego Elio Pettenò 	spin_lock(&it87_gpio->lock);
216b8664924SDiego Elio Pettenò 
217b8664924SDiego Elio Pettenò 	rc = superio_enter();
218b8664924SDiego Elio Pettenò 	if (rc)
219b8664924SDiego Elio Pettenò 		goto exit;
220b8664924SDiego Elio Pettenò 
221b8664924SDiego Elio Pettenò 	/* clear the output enable bit */
222b8664924SDiego Elio Pettenò 	superio_clear_mask(mask, group + it87_gpio->output_base);
223b8664924SDiego Elio Pettenò 
224b8664924SDiego Elio Pettenò 	superio_exit();
225b8664924SDiego Elio Pettenò 
226b8664924SDiego Elio Pettenò exit:
227b8664924SDiego Elio Pettenò 	spin_unlock(&it87_gpio->lock);
228b8664924SDiego Elio Pettenò 	return rc;
229b8664924SDiego Elio Pettenò }
230b8664924SDiego Elio Pettenò 
231b8664924SDiego Elio Pettenò static void it87_gpio_set(struct gpio_chip *chip,
232b8664924SDiego Elio Pettenò 			  unsigned gpio_num, int val)
233b8664924SDiego Elio Pettenò {
234b8664924SDiego Elio Pettenò 	u8 mask, curr_vals;
235b8664924SDiego Elio Pettenò 	u16 reg;
2360a38fd94SLinus Walleij 	struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
237b8664924SDiego Elio Pettenò 
238b8664924SDiego Elio Pettenò 	mask = 1 << (gpio_num % 8);
239b8664924SDiego Elio Pettenò 	reg = (gpio_num / 8) + it87_gpio->io_base;
240b8664924SDiego Elio Pettenò 
241b8664924SDiego Elio Pettenò 	curr_vals = inb(reg);
242b8664924SDiego Elio Pettenò 	if (val)
243b8664924SDiego Elio Pettenò 		outb(curr_vals | mask, reg);
244b8664924SDiego Elio Pettenò 	else
245b8664924SDiego Elio Pettenò 		outb(curr_vals & ~mask, reg);
246b8664924SDiego Elio Pettenò }
247b8664924SDiego Elio Pettenò 
248b8664924SDiego Elio Pettenò static int it87_gpio_direction_out(struct gpio_chip *chip,
249b8664924SDiego Elio Pettenò 				   unsigned gpio_num, int val)
250b8664924SDiego Elio Pettenò {
251b8664924SDiego Elio Pettenò 	u8 mask, group;
252b8664924SDiego Elio Pettenò 	int rc = 0;
2530a38fd94SLinus Walleij 	struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
254b8664924SDiego Elio Pettenò 
255b8664924SDiego Elio Pettenò 	mask = 1 << (gpio_num % 8);
256b8664924SDiego Elio Pettenò 	group = (gpio_num / 8);
257b8664924SDiego Elio Pettenò 
258b8664924SDiego Elio Pettenò 	spin_lock(&it87_gpio->lock);
259b8664924SDiego Elio Pettenò 
260b8664924SDiego Elio Pettenò 	rc = superio_enter();
261b8664924SDiego Elio Pettenò 	if (rc)
262b8664924SDiego Elio Pettenò 		goto exit;
263b8664924SDiego Elio Pettenò 
264b8664924SDiego Elio Pettenò 	/* set the output enable bit */
265b8664924SDiego Elio Pettenò 	superio_set_mask(mask, group + it87_gpio->output_base);
266b8664924SDiego Elio Pettenò 
267b8664924SDiego Elio Pettenò 	it87_gpio_set(chip, gpio_num, val);
268b8664924SDiego Elio Pettenò 
269b8664924SDiego Elio Pettenò 	superio_exit();
270b8664924SDiego Elio Pettenò 
271b8664924SDiego Elio Pettenò exit:
272b8664924SDiego Elio Pettenò 	spin_unlock(&it87_gpio->lock);
273b8664924SDiego Elio Pettenò 	return rc;
274b8664924SDiego Elio Pettenò }
275b8664924SDiego Elio Pettenò 
276b8664924SDiego Elio Pettenò static struct gpio_chip it87_template_chip = {
277b8664924SDiego Elio Pettenò 	.label			= KBUILD_MODNAME,
278b8664924SDiego Elio Pettenò 	.owner			= THIS_MODULE,
279b8664924SDiego Elio Pettenò 	.request		= it87_gpio_request,
280b8664924SDiego Elio Pettenò 	.get			= it87_gpio_get,
281b8664924SDiego Elio Pettenò 	.direction_input	= it87_gpio_direction_in,
282b8664924SDiego Elio Pettenò 	.set			= it87_gpio_set,
283b8664924SDiego Elio Pettenò 	.direction_output	= it87_gpio_direction_out,
284b8664924SDiego Elio Pettenò 	.base			= -1
285b8664924SDiego Elio Pettenò };
286b8664924SDiego Elio Pettenò 
287b8664924SDiego Elio Pettenò static int __init it87_gpio_init(void)
288b8664924SDiego Elio Pettenò {
289b8664924SDiego Elio Pettenò 	int rc = 0, i;
290b8664924SDiego Elio Pettenò 	u16 chip_type;
291b8664924SDiego Elio Pettenò 	u8 chip_rev, gpio_ba_reg;
292b8664924SDiego Elio Pettenò 	char *labels, **labels_table;
293b8664924SDiego Elio Pettenò 
294b8664924SDiego Elio Pettenò 	struct it87_gpio *it87_gpio = &it87_gpio_chip;
295b8664924SDiego Elio Pettenò 
296b8664924SDiego Elio Pettenò 	rc = superio_enter();
297b8664924SDiego Elio Pettenò 	if (rc)
298b8664924SDiego Elio Pettenò 		return rc;
299b8664924SDiego Elio Pettenò 
300b8664924SDiego Elio Pettenò 	chip_type = superio_inw(CHIPID);
301b8664924SDiego Elio Pettenò 	chip_rev  = superio_inb(CHIPREV) & 0x0f;
302b8664924SDiego Elio Pettenò 	superio_exit();
303b8664924SDiego Elio Pettenò 
304b8664924SDiego Elio Pettenò 	it87_gpio->chip = it87_template_chip;
305b8664924SDiego Elio Pettenò 
306b8664924SDiego Elio Pettenò 	switch (chip_type) {
3078fccdb58SMartin Blumenstingl 	case IT8620_ID:
3088fccdb58SMartin Blumenstingl 	case IT8628_ID:
3098fccdb58SMartin Blumenstingl 		gpio_ba_reg = 0x62;
3108fccdb58SMartin Blumenstingl 		it87_gpio->io_size = 11;
3118fccdb58SMartin Blumenstingl 		it87_gpio->output_base = 0xc8;
3128fccdb58SMartin Blumenstingl 		it87_gpio->simple_size = 0;
3138fccdb58SMartin Blumenstingl 		it87_gpio->chip.ngpio = 64;
3148fccdb58SMartin Blumenstingl 		break;
315b8664924SDiego Elio Pettenò 	case IT8728_ID:
316b8664924SDiego Elio Pettenò 	case IT8732_ID:
317b8664924SDiego Elio Pettenò 		gpio_ba_reg = 0x62;
318b8664924SDiego Elio Pettenò 		it87_gpio->io_size = 8;
319b8664924SDiego Elio Pettenò 		it87_gpio->output_base = 0xc8;
320b8664924SDiego Elio Pettenò 		it87_gpio->simple_base = 0xc0;
321b8664924SDiego Elio Pettenò 		it87_gpio->simple_size = 5;
322b8664924SDiego Elio Pettenò 		it87_gpio->chip.ngpio = 64;
323b8664924SDiego Elio Pettenò 		break;
324b8664924SDiego Elio Pettenò 	case IT8761_ID:
325b8664924SDiego Elio Pettenò 		gpio_ba_reg = 0x60;
326b8664924SDiego Elio Pettenò 		it87_gpio->io_size = 4;
327b8664924SDiego Elio Pettenò 		it87_gpio->output_base = 0xf0;
328b8664924SDiego Elio Pettenò 		it87_gpio->simple_size = 0;
329b8664924SDiego Elio Pettenò 		it87_gpio->chip.ngpio = 16;
330b8664924SDiego Elio Pettenò 		break;
331b8664924SDiego Elio Pettenò 	case NO_DEV_ID:
332b8664924SDiego Elio Pettenò 		pr_err("no device\n");
333b8664924SDiego Elio Pettenò 		return -ENODEV;
334b8664924SDiego Elio Pettenò 	default:
335b8664924SDiego Elio Pettenò 		pr_err("Unknown Chip found, Chip %04x Revision %x\n",
336b8664924SDiego Elio Pettenò 		       chip_type, chip_rev);
337b8664924SDiego Elio Pettenò 		return -ENODEV;
338b8664924SDiego Elio Pettenò 	}
339b8664924SDiego Elio Pettenò 
340b8664924SDiego Elio Pettenò 	rc = superio_enter();
341b8664924SDiego Elio Pettenò 	if (rc)
342b8664924SDiego Elio Pettenò 		return rc;
343b8664924SDiego Elio Pettenò 
344b8664924SDiego Elio Pettenò 	superio_select(GPIO);
345b8664924SDiego Elio Pettenò 
346b8664924SDiego Elio Pettenò 	/* fetch GPIO base address */
347b8664924SDiego Elio Pettenò 	it87_gpio->io_base = superio_inw(gpio_ba_reg);
348b8664924SDiego Elio Pettenò 
349b8664924SDiego Elio Pettenò 	superio_exit();
350b8664924SDiego Elio Pettenò 
351b8664924SDiego Elio Pettenò 	pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n",
352b8664924SDiego Elio Pettenò 		chip_type, chip_rev, it87_gpio->chip.ngpio,
353b8664924SDiego Elio Pettenò 		it87_gpio->io_base);
354b8664924SDiego Elio Pettenò 
355b8664924SDiego Elio Pettenò 	if (!request_region(it87_gpio->io_base, it87_gpio->io_size,
356b8664924SDiego Elio Pettenò 							KBUILD_MODNAME))
357b8664924SDiego Elio Pettenò 		return -EBUSY;
358b8664924SDiego Elio Pettenò 
359b8664924SDiego Elio Pettenò 	/* Set up aliases for the GPIO connection.
360b8664924SDiego Elio Pettenò 	 *
361b8664924SDiego Elio Pettenò 	 * ITE documentation for recent chips such as the IT8728F
362b8664924SDiego Elio Pettenò 	 * refers to the GPIO lines as GPxy, with a coordinates system
363b8664924SDiego Elio Pettenò 	 * where x is the GPIO group (starting from 1) and y is the
364b8664924SDiego Elio Pettenò 	 * bit within the group.
365b8664924SDiego Elio Pettenò 	 *
366b8664924SDiego Elio Pettenò 	 * By creating these aliases, we make it easier to understand
367b8664924SDiego Elio Pettenò 	 * to which GPIO pin we're referring to.
368b8664924SDiego Elio Pettenò 	 */
369b8664924SDiego Elio Pettenò 	labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"),
370b8664924SDiego Elio Pettenò 								GFP_KERNEL);
371b8664924SDiego Elio Pettenò 	labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *),
372b8664924SDiego Elio Pettenò 								GFP_KERNEL);
373b8664924SDiego Elio Pettenò 
374b8664924SDiego Elio Pettenò 	if (!labels || !labels_table) {
375b8664924SDiego Elio Pettenò 		rc = -ENOMEM;
376b8664924SDiego Elio Pettenò 		goto labels_free;
377b8664924SDiego Elio Pettenò 	}
378b8664924SDiego Elio Pettenò 
379b8664924SDiego Elio Pettenò 	for (i = 0; i < it87_gpio->chip.ngpio; i++) {
380b8664924SDiego Elio Pettenò 		char *label = &labels[i * sizeof("it87_gpXY")];
381b8664924SDiego Elio Pettenò 
382b8664924SDiego Elio Pettenò 		sprintf(label, "it87_gp%u%u", 1+(i/8), i%8);
383b8664924SDiego Elio Pettenò 		labels_table[i] = label;
384b8664924SDiego Elio Pettenò 	}
385b8664924SDiego Elio Pettenò 
386b8664924SDiego Elio Pettenò 	it87_gpio->chip.names = (const char *const*)labels_table;
387b8664924SDiego Elio Pettenò 
3880a38fd94SLinus Walleij 	rc = gpiochip_add_data(&it87_gpio->chip, it87_gpio);
389b8664924SDiego Elio Pettenò 	if (rc)
390b8664924SDiego Elio Pettenò 		goto labels_free;
391b8664924SDiego Elio Pettenò 
392b8664924SDiego Elio Pettenò 	return 0;
393b8664924SDiego Elio Pettenò 
394b8664924SDiego Elio Pettenò labels_free:
395b8664924SDiego Elio Pettenò 	kfree(labels_table);
396b8664924SDiego Elio Pettenò 	kfree(labels);
397b8664924SDiego Elio Pettenò 	release_region(it87_gpio->io_base, it87_gpio->io_size);
398b8664924SDiego Elio Pettenò 	return rc;
399b8664924SDiego Elio Pettenò }
400b8664924SDiego Elio Pettenò 
401b8664924SDiego Elio Pettenò static void __exit it87_gpio_exit(void)
402b8664924SDiego Elio Pettenò {
403b8664924SDiego Elio Pettenò 	struct it87_gpio *it87_gpio = &it87_gpio_chip;
404b8664924SDiego Elio Pettenò 
405b8664924SDiego Elio Pettenò 	gpiochip_remove(&it87_gpio->chip);
406b8664924SDiego Elio Pettenò 	release_region(it87_gpio->io_base, it87_gpio->io_size);
407b8664924SDiego Elio Pettenò 	kfree(it87_gpio->chip.names[0]);
408b8664924SDiego Elio Pettenò 	kfree(it87_gpio->chip.names);
409b8664924SDiego Elio Pettenò }
410b8664924SDiego Elio Pettenò 
411b8664924SDiego Elio Pettenò module_init(it87_gpio_init);
412b8664924SDiego Elio Pettenò module_exit(it87_gpio_exit);
413b8664924SDiego Elio Pettenò 
414b8664924SDiego Elio Pettenò MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>");
415b8664924SDiego Elio Pettenò MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips");
416b8664924SDiego Elio Pettenò MODULE_LICENSE("GPL");
417