xref: /openbmc/linux/drivers/gpio/gpio-gpio-mm.c (revision a44d924c)
1 /*
2  * GPIO driver for the Diamond Systems GPIO-MM
3  * Copyright (C) 2016 William Breathitt Gray
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License, version 2, as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * This driver supports the following Diamond Systems devices: GPIO-MM and
15  * GPIO-MM-12.
16  */
17 #include <linux/bitmap.h>
18 #include <linux/bitops.h>
19 #include <linux/device.h>
20 #include <linux/errno.h>
21 #include <linux/gpio/driver.h>
22 #include <linux/io.h>
23 #include <linux/ioport.h>
24 #include <linux/isa.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/spinlock.h>
29 
30 #define GPIOMM_EXTENT 8
31 #define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT)
32 
33 static unsigned int base[MAX_NUM_GPIOMM];
34 static unsigned int num_gpiomm;
35 module_param_hw_array(base, uint, ioport, &num_gpiomm, 0);
36 MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses");
37 
38 /**
39  * struct gpiomm_gpio - GPIO device private data structure
40  * @chip:	instance of the gpio_chip
41  * @io_state:	bit I/O state (whether bit is set to input or output)
42  * @out_state:	output bits state
43  * @control:	Control registers state
44  * @lock:	synchronization lock to prevent I/O race conditions
45  * @base:	base port address of the GPIO device
46  */
47 struct gpiomm_gpio {
48 	struct gpio_chip chip;
49 	unsigned char io_state[6];
50 	unsigned char out_state[6];
51 	unsigned char control[2];
52 	spinlock_t lock;
53 	unsigned int base;
54 };
55 
56 static int gpiomm_gpio_get_direction(struct gpio_chip *chip,
57 	unsigned int offset)
58 {
59 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
60 	const unsigned int port = offset / 8;
61 	const unsigned int mask = BIT(offset % 8);
62 
63 	return !!(gpiommgpio->io_state[port] & mask);
64 }
65 
66 static int gpiomm_gpio_direction_input(struct gpio_chip *chip,
67 	unsigned int offset)
68 {
69 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
70 	const unsigned int io_port = offset / 8;
71 	const unsigned int control_port = io_port / 3;
72 	const unsigned int control_addr = gpiommgpio->base + 3 + control_port*4;
73 	unsigned long flags;
74 	unsigned int control;
75 
76 	spin_lock_irqsave(&gpiommgpio->lock, flags);
77 
78 	/* Check if configuring Port C */
79 	if (io_port == 2 || io_port == 5) {
80 		/* Port C can be configured by nibble */
81 		if (offset % 8 > 3) {
82 			gpiommgpio->io_state[io_port] |= 0xF0;
83 			gpiommgpio->control[control_port] |= BIT(3);
84 		} else {
85 			gpiommgpio->io_state[io_port] |= 0x0F;
86 			gpiommgpio->control[control_port] |= BIT(0);
87 		}
88 	} else {
89 		gpiommgpio->io_state[io_port] |= 0xFF;
90 		if (io_port == 0 || io_port == 3)
91 			gpiommgpio->control[control_port] |= BIT(4);
92 		else
93 			gpiommgpio->control[control_port] |= BIT(1);
94 	}
95 
96 	control = BIT(7) | gpiommgpio->control[control_port];
97 	outb(control, control_addr);
98 
99 	spin_unlock_irqrestore(&gpiommgpio->lock, flags);
100 
101 	return 0;
102 }
103 
104 static int gpiomm_gpio_direction_output(struct gpio_chip *chip,
105 	unsigned int offset, int value)
106 {
107 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
108 	const unsigned int io_port = offset / 8;
109 	const unsigned int control_port = io_port / 3;
110 	const unsigned int mask = BIT(offset % 8);
111 	const unsigned int control_addr = gpiommgpio->base + 3 + control_port*4;
112 	const unsigned int out_port = (io_port > 2) ? io_port + 1 : io_port;
113 	unsigned long flags;
114 	unsigned int control;
115 
116 	spin_lock_irqsave(&gpiommgpio->lock, flags);
117 
118 	/* Check if configuring Port C */
119 	if (io_port == 2 || io_port == 5) {
120 		/* Port C can be configured by nibble */
121 		if (offset % 8 > 3) {
122 			gpiommgpio->io_state[io_port] &= 0x0F;
123 			gpiommgpio->control[control_port] &= ~BIT(3);
124 		} else {
125 			gpiommgpio->io_state[io_port] &= 0xF0;
126 			gpiommgpio->control[control_port] &= ~BIT(0);
127 		}
128 	} else {
129 		gpiommgpio->io_state[io_port] &= 0x00;
130 		if (io_port == 0 || io_port == 3)
131 			gpiommgpio->control[control_port] &= ~BIT(4);
132 		else
133 			gpiommgpio->control[control_port] &= ~BIT(1);
134 	}
135 
136 	if (value)
137 		gpiommgpio->out_state[io_port] |= mask;
138 	else
139 		gpiommgpio->out_state[io_port] &= ~mask;
140 
141 	control = BIT(7) | gpiommgpio->control[control_port];
142 	outb(control, control_addr);
143 
144 	outb(gpiommgpio->out_state[io_port], gpiommgpio->base + out_port);
145 
146 	spin_unlock_irqrestore(&gpiommgpio->lock, flags);
147 
148 	return 0;
149 }
150 
151 static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset)
152 {
153 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
154 	const unsigned int port = offset / 8;
155 	const unsigned int mask = BIT(offset % 8);
156 	const unsigned int in_port = (port > 2) ? port + 1 : port;
157 	unsigned long flags;
158 	unsigned int port_state;
159 
160 	spin_lock_irqsave(&gpiommgpio->lock, flags);
161 
162 	/* ensure that GPIO is set for input */
163 	if (!(gpiommgpio->io_state[port] & mask)) {
164 		spin_unlock_irqrestore(&gpiommgpio->lock, flags);
165 		return -EINVAL;
166 	}
167 
168 	port_state = inb(gpiommgpio->base + in_port);
169 
170 	spin_unlock_irqrestore(&gpiommgpio->lock, flags);
171 
172 	return !!(port_state & mask);
173 }
174 
175 static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
176 	unsigned long *bits)
177 {
178 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
179 	size_t i;
180 	static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
181 	const unsigned int gpio_reg_size = 8;
182 	unsigned int bits_offset;
183 	size_t word_index;
184 	unsigned int word_offset;
185 	unsigned long word_mask;
186 	const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
187 	unsigned long port_state;
188 
189 	/* clear bits array to a clean slate */
190 	bitmap_zero(bits, chip->ngpio);
191 
192 	/* get bits are evaluated a gpio port register at a time */
193 	for (i = 0; i < ARRAY_SIZE(ports); i++) {
194 		/* gpio offset in bits array */
195 		bits_offset = i * gpio_reg_size;
196 
197 		/* word index for bits array */
198 		word_index = BIT_WORD(bits_offset);
199 
200 		/* gpio offset within current word of bits array */
201 		word_offset = bits_offset % BITS_PER_LONG;
202 
203 		/* mask of get bits for current gpio within current word */
204 		word_mask = mask[word_index] & (port_mask << word_offset);
205 		if (!word_mask) {
206 			/* no get bits in this port so skip to next one */
207 			continue;
208 		}
209 
210 		/* read bits from current gpio port */
211 		port_state = inb(gpiommgpio->base + ports[i]);
212 
213 		/* store acquired bits at respective bits array offset */
214 		bits[word_index] |= (port_state << word_offset) & word_mask;
215 	}
216 
217 	return 0;
218 }
219 
220 static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset,
221 	int value)
222 {
223 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
224 	const unsigned int port = offset / 8;
225 	const unsigned int mask = BIT(offset % 8);
226 	const unsigned int out_port = (port > 2) ? port + 1 : port;
227 	unsigned long flags;
228 
229 	spin_lock_irqsave(&gpiommgpio->lock, flags);
230 
231 	if (value)
232 		gpiommgpio->out_state[port] |= mask;
233 	else
234 		gpiommgpio->out_state[port] &= ~mask;
235 
236 	outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port);
237 
238 	spin_unlock_irqrestore(&gpiommgpio->lock, flags);
239 }
240 
241 static void gpiomm_gpio_set_multiple(struct gpio_chip *chip,
242 	unsigned long *mask, unsigned long *bits)
243 {
244 	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
245 	unsigned int i;
246 	const unsigned int gpio_reg_size = 8;
247 	unsigned int port;
248 	unsigned int out_port;
249 	unsigned int bitmask;
250 	unsigned long flags;
251 
252 	/* set bits are evaluated a gpio register size at a time */
253 	for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
254 		/* no more set bits in this mask word; skip to the next word */
255 		if (!mask[BIT_WORD(i)]) {
256 			i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
257 			continue;
258 		}
259 
260 		port = i / gpio_reg_size;
261 		out_port = (port > 2) ? port + 1 : port;
262 		bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
263 
264 		spin_lock_irqsave(&gpiommgpio->lock, flags);
265 
266 		/* update output state data and set device gpio register */
267 		gpiommgpio->out_state[port] &= ~mask[BIT_WORD(i)];
268 		gpiommgpio->out_state[port] |= bitmask;
269 		outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port);
270 
271 		spin_unlock_irqrestore(&gpiommgpio->lock, flags);
272 
273 		/* prepare for next gpio register set */
274 		mask[BIT_WORD(i)] >>= gpio_reg_size;
275 		bits[BIT_WORD(i)] >>= gpio_reg_size;
276 	}
277 }
278 
279 #define GPIOMM_NGPIO 48
280 static const char *gpiomm_names[GPIOMM_NGPIO] = {
281 	"Port 1A0", "Port 1A1", "Port 1A2", "Port 1A3", "Port 1A4", "Port 1A5",
282 	"Port 1A6", "Port 1A7", "Port 1B0", "Port 1B1", "Port 1B2", "Port 1B3",
283 	"Port 1B4", "Port 1B5", "Port 1B6", "Port 1B7", "Port 1C0", "Port 1C1",
284 	"Port 1C2", "Port 1C3", "Port 1C4", "Port 1C5", "Port 1C6", "Port 1C7",
285 	"Port 2A0", "Port 2A1", "Port 2A2", "Port 2A3", "Port 2A4", "Port 2A5",
286 	"Port 2A6", "Port 2A7", "Port 2B0", "Port 2B1", "Port 2B2", "Port 2B3",
287 	"Port 2B4", "Port 2B5", "Port 2B6", "Port 2B7", "Port 2C0", "Port 2C1",
288 	"Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7",
289 };
290 
291 static int gpiomm_probe(struct device *dev, unsigned int id)
292 {
293 	struct gpiomm_gpio *gpiommgpio;
294 	const char *const name = dev_name(dev);
295 	int err;
296 
297 	gpiommgpio = devm_kzalloc(dev, sizeof(*gpiommgpio), GFP_KERNEL);
298 	if (!gpiommgpio)
299 		return -ENOMEM;
300 
301 	if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) {
302 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
303 			base[id], base[id] + GPIOMM_EXTENT);
304 		return -EBUSY;
305 	}
306 
307 	gpiommgpio->chip.label = name;
308 	gpiommgpio->chip.parent = dev;
309 	gpiommgpio->chip.owner = THIS_MODULE;
310 	gpiommgpio->chip.base = -1;
311 	gpiommgpio->chip.ngpio = GPIOMM_NGPIO;
312 	gpiommgpio->chip.names = gpiomm_names;
313 	gpiommgpio->chip.get_direction = gpiomm_gpio_get_direction;
314 	gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input;
315 	gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output;
316 	gpiommgpio->chip.get = gpiomm_gpio_get;
317 	gpiommgpio->chip.get_multiple = gpiomm_gpio_get_multiple;
318 	gpiommgpio->chip.set = gpiomm_gpio_set;
319 	gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple;
320 	gpiommgpio->base = base[id];
321 
322 	spin_lock_init(&gpiommgpio->lock);
323 
324 	err = devm_gpiochip_add_data(dev, &gpiommgpio->chip, gpiommgpio);
325 	if (err) {
326 		dev_err(dev, "GPIO registering failed (%d)\n", err);
327 		return err;
328 	}
329 
330 	/* initialize all GPIO as output */
331 	outb(0x80, base[id] + 3);
332 	outb(0x00, base[id]);
333 	outb(0x00, base[id] + 1);
334 	outb(0x00, base[id] + 2);
335 	outb(0x80, base[id] + 7);
336 	outb(0x00, base[id] + 4);
337 	outb(0x00, base[id] + 5);
338 	outb(0x00, base[id] + 6);
339 
340 	return 0;
341 }
342 
343 static struct isa_driver gpiomm_driver = {
344 	.probe = gpiomm_probe,
345 	.driver = {
346 		.name = "gpio-mm"
347 	},
348 };
349 
350 module_isa_driver(gpiomm_driver, num_gpiomm);
351 
352 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
353 MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver");
354 MODULE_LICENSE("GPL v2");
355