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