YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
gpio_bbb.c
1/************************************************
2 G P I O _ B B B
3
4 A performant GPIO library for the BeagleBone
5
6 (c) 2015-2019 A. Terstegge
8
9************************************************/
10
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/fs.h>
15
16#include <linux/sched.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/irq.h>
20#include <linux/gpio.h>
21#include <linux/pinctrl/consumer.h>
22
23#include <linux/kdev_t.h>
24#include <linux/device.h>
25#include <linux/cdev.h>
26
27#include "gpio_bbb.h"
28
29MODULE_LICENSE ("GPL");
30MODULE_AUTHOR ("Andreas Terstegge");
31MODULE_DESCRIPTION("A fast IOCTL-based GPIO driver for the BBB");
32
33#define MOD_STR "gpio_bbb: "
34
35static int open_count = 0;
36
37static dev_t devnum; // Global var for the device number
38static struct class *cl; // Global var for the device class
39static struct cdev c_dev; // Global var for the character device structure
40
41static wait_queue_head_t queue;
42static int gpio_irq;
43
44static int irq_enabled[GPIO_COUNT];
45static u16 gpio_mode[GPIO_COUNT];
46
47/**************************/
48/* global memory adresses */
49/**************************/
50#define CTRL_MODULE_ADDR 0x44e10000
51#define CTRL_MODULE_LEN 0xa00
52void __iomem *ctrl_module_base;
53
54unsigned int GPIO_BANK_ADDR[4] = {
55 0x44e07000, // GPIO0
56 0x4804c000, // GPIO1
57 0x481ac000, // GPIO2
58 0x481ae000 // GPIO3
59};
60#define GPIO_BANK_LEN 0x200
61void __iomem *gpio_base[4];
62
63/******************************/
64/* GPIO bank register offsets */
65/******************************/
66#define GPIO_IRQSTATUS_RAW_0 0x024
67#define GPIO_IRQSTATUS_0 0x02c
68#define GPIO_IRQSTATUS_SET_0 0x034
69#define GPIO_IRQSTATUS_CLR_0 0x03c
70#define GPIO_OE 0x134
71#define GPIO_DATAIN 0x138
72#define GPIO_DATAOUT 0x13c
73#define GPIO_LEVELDETECT0 0x140
74#define GPIO_LEVELDETECT1 0x144
75#define GPIO_RISINGDETECT 0x148
76#define GPIO_FALLINGDETECT 0x14c
77#define GPIO_SETDATAOUT 0x194
78#define GPIO_CLEARDATAOUT 0x190
79
80/*************/
81/* GPIO data */
82/*************/
83#define ENABLE 0x80
84#define DISABLE 0x00
85#define GPIO0 (00 << 5)
86#define GPIO1 (01 << 5)
87#define GPIO2 (02 << 5)
88#define GPIO3 (03 << 5)
89u8 gpio_data[GPIO_COUNT] = {
90// ========+=========+=======+======+=========+=======+=========
91// Offset | Status | Bank | Pin | GPIO-No |Header |Usage
92// ========+=========+=======+======+=========+=======+=========
93 /*0x800*/ ENABLE | GPIO1 | 0, // GPIO-32 P8-25 MMC1 DAT0
94 /*0x804*/ ENABLE | GPIO1 | 1, // GPIO-33 P8-24 MMC1 DAT1
95 /*0x808*/ ENABLE | GPIO1 | 2, // GPIO-34 P8-05 MMC1 DAT2
96 /*0x80c*/ ENABLE | GPIO1 | 3, // GPIO-35 P8-06 MMC1 DAT3
97 /*0x810*/ ENABLE | GPIO1 | 4, // GPIO-36 P8-23 MMC1 DAT4
98 /*0x814*/ ENABLE | GPIO1 | 5, // GPIO-37 P8-22 MMC1 DAT5
99 /*0x818*/ ENABLE | GPIO1 | 6, // GPIO-38 P8-03 MMC1 DAT6
100 /*0x81c*/ ENABLE | GPIO1 | 7, // GPIO-39 P8-04 MMC1 DAT7
101 /*0x820*/ ENABLE | GPIO0 | 22, // GPIO-22 P8-19 (EHRPWM2A)
102 /*0x824*/ ENABLE | GPIO0 | 23, // GPIO-23 P8-13 (EHRPWM2B)
103 /*0x828*/ ENABLE | GPIO0 | 26, // GPIO-26 P8-14
104 /*0x82c*/ ENABLE | GPIO0 | 27, // GPIO-27 P8-17
105 /*0x830*/ ENABLE | GPIO1 | 12, // GPIO-44 P8-12
106 /*0x834*/ ENABLE | GPIO1 | 13, // GPIO-45 P8-11
107 /*0x838*/ ENABLE | GPIO1 | 14, // GPIO-46 P8-16
108 /*0x83c*/ ENABLE | GPIO1 | 15, // GPIO-47 P8-15
109
110 /*0x840*/ ENABLE | GPIO1 | 16, // GPIO-48 P9-15 connected to GPIO-64
111 /*0x844*/ ENABLE | GPIO1 | 17, // GPIO-49 P9-23
112 /*0x848*/ ENABLE | GPIO1 | 18, // GPIO-50 P9-14 (EHRPWM1A)
113 /*0x84c*/ ENABLE | GPIO1 | 19, // GPIO-51 P9-16 (EHRPWM1B)
114 /*0x850*/ ENABLE | GPIO1 | 20, // GPIO-52 ----- EMMC_RSTN (MMC1)
115 /*0x854*/ ENABLE | GPIO1 | 21, // GPIO-53 ----- LED USR0
116 /*0x858*/ ENABLE | GPIO1 | 22, // GPIO-54 ----- LED USR1
117 /*0x85c*/ ENABLE | GPIO1 | 23, // GPIO-55 ----- LED USR2
118 /*0x860*/ ENABLE | GPIO1 | 24, // GPIO-56 ----- LED USR3
119 /*0x864*/ ENABLE | GPIO1 | 25, // GPIO-57 ----- LCD INT
120 /*0x868*/ ENABLE | GPIO1 | 26, // GPIO-58 ----- USB1 OCN
121 /*0x86c*/ ENABLE | GPIO1 | 27, // GPIO-59 ----- HDMICLK DISN
122 /*0x870*/ ENABLE | GPIO0 | 30, // GPIO-30 P9-11 (UART4RXD)
123 /*0x874*/ ENABLE | GPIO0 | 31, // GPIO-31 P9-13 (UART4TXD)
124 /*0x878*/ ENABLE | GPIO1 | 28, // GPIO-60 P9-12
125 /*0x87c*/ ENABLE | GPIO1 | 29, // GPIO-61 P8-26
126
127 /*0x880*/ ENABLE | GPIO1 | 30, // GPIO-62 P8-21 MMC1 CLK
128 /*0x884*/ ENABLE | GPIO1 | 31, // GPIO-63 P8-20 MMC1 CMD
129 /*0x888*/ ENABLE | GPIO2 | 0, // GPIO-64 ----- connected to GPIO-48
130 /*0x88c*/ ENABLE | GPIO2 | 1, // GPIO-65 P8-18
131 /*0x890*/ ENABLE | GPIO2 | 2, // GPIO-66 P8-07 (TIMER4)
132 /*0x894*/ ENABLE | GPIO2 | 3, // GPIO-67 P8-08 (TIMER7)
133 /*0x898*/ ENABLE | GPIO2 | 4, // GPIO-68 P8-10 (TIMER6)
134 /*0x89c*/ ENABLE | GPIO2 | 5, // GPIO-69 P8-09 (TIMER5)
135 /*0x8a0*/ ENABLE | GPIO2 | 6, // GPIO-70 P8-45 LCD DATA 0
136 /*0x8a4*/ ENABLE | GPIO2 | 7, // GPIO-71 P8-46 LCD DATA 1
137 /*0x8a8*/ ENABLE | GPIO2 | 8, // GPIO-72 P8-43 LCD DATA 2
138 /*0x8ac*/ ENABLE | GPIO2 | 9, // GPIO-73 P8-44 LCD DATA 3
139 /*0x8b0*/ ENABLE | GPIO2 | 10, // GPIO-74 P8-41 LCD DATA 4
140 /*0x8b4*/ ENABLE | GPIO2 | 11, // GPIO-75 P8-42 LCD DATA 5
141 /*0x8b8*/ ENABLE | GPIO2 | 12, // GPIO-76 P8-39 LCD DATA 6
142 /*0x8bc*/ ENABLE | GPIO2 | 13, // GPIO-77 P8-40 LCD DATA 7
143
144 /*0x8c0*/ ENABLE | GPIO2 | 14, // GPIO-78 P8-37 LCD DATA 8
145 /*0x8c4*/ ENABLE | GPIO2 | 15, // GPIO-79 P8-38 LCD DATA 9
146 /*0x8c8*/ ENABLE | GPIO2 | 16, // GPIO-80 P8-36 LCD DATA 10
147 /*0x8cc*/ ENABLE | GPIO2 | 17, // GPIO-81 P8-34 LCD DATA 11
148 /*0x8d0*/ ENABLE | GPIO0 | 8, // GPIO-8 P8-35 LCD DATA 12
149 /*0x8d4*/ ENABLE | GPIO0 | 9, // GPIO-9 P8-33 LCD DATA 13
150 /*0x8d8*/ ENABLE | GPIO0 | 10, // GPIO-10 P8-31 LCD DATA 14
151 /*0x8dc*/ ENABLE | GPIO0 | 11, // GPIO-11 P8-32 LCD DATA 15
152 /*0x8e0*/ ENABLE | GPIO2 | 22, // GPIO-86 P8-27 LCD VSYNC
153 /*0x8e4*/ ENABLE | GPIO2 | 23, // GPIO-87 P8-29 LCD HSYNC
154 /*0x8e8*/ ENABLE | GPIO2 | 24, // GPIO-88 P8-28 LCD PCLK
155 /*0x8ec*/ ENABLE | GPIO2 | 25, // GPIO-89 P8-30 LCD DE
156 /*0x8f0*/ ENABLE | GPIO2 | 26, // GPIO-90 ----- MMC0 DAT3
157 /*0x8f4*/ ENABLE | GPIO2 | 27, // GPIO-91 ----- MMC0 DAT2
158 /*0x8f8*/ ENABLE | GPIO2 | 28, // GPIO-92 ----- MMC0 DAT1
159 /*0x8fc*/ ENABLE | GPIO2 | 29, // GPIO-93 ----- MMC0 DAT0
160
161 /*0x900*/ ENABLE | GPIO2 | 30, // GPIO-94 ----- MMC0 CLKO
162 /*0x904*/ ENABLE | GPIO2 | 31, // GPIO-95 ----- MMC0 CMD
163 /*0x908*/ DISABLE | GPIO3 | 0, // GPIO-96 ----- MII1_COL
164 /*0x90c*/ DISABLE | GPIO3 | 1, // GPIO-97 ----- MII1_CRS_DV
165 /*0x910*/ DISABLE | GPIO3 | 2, // GPIO-98 ----- MII1_RXERR
166 /*0x914*/ DISABLE | GPIO3 | 3, // GPIO-99 ----- MII1_TXEN
167 /*0x918*/ DISABLE | GPIO3 | 4, // GPIO-100 ----- MII1_RXDV
168 /*0x91c*/ DISABLE | GPIO0 | 16, // GPIO-16 ----- MII1_TXD3
169 /*0x920*/ DISABLE | GPIO0 | 17, // GPIO-17 ----- MII1_TXD2
170 /*0x924*/ DISABLE | GPIO0 | 21, // GPIO-21 ----- MII1_TXD1
171 /*0x928*/ DISABLE | GPIO0 | 28, // GPIO-28 ----- MII1_TXD0
172 /*0x92c*/ DISABLE | GPIO3 | 9, // GPIO-105 ----- MII1_TXCLK
173 /*0x930*/ DISABLE | GPIO3 | 10, // GPIO-106 ----- MII1_RXCLK
174 /*0x934*/ DISABLE | GPIO2 | 18, // GPIO-82 ----- MII1_RXD3
175 /*0x938*/ DISABLE | GPIO2 | 19, // GPIO-83 ----- MII1_RXD2
176 /*0x93c*/ DISABLE | GPIO2 | 20, // GPIO-84 ----- MII1_RXD1
177
178 /*0x940*/ DISABLE | GPIO2 | 21, // GPIO-85 ----- MII1_RXD0
179 /*0x944*/ DISABLE | GPIO0 | 29, // GPIO-29 ----- MII1_REFCLK
180 /*0x948*/ DISABLE | GPIO0 | 0, // GPIO-0 ----- MDIO_DATA
181 /*0x94c*/ DISABLE | GPIO0 | 1, // GPIO-1 ----- MDIO_CLK
182 /*0x950*/ ENABLE | GPIO0 | 2, // GPIO-2 P9-22 (UART2_RXD)
183 /*0x954*/ ENABLE | GPIO0 | 3, // GPIO-3 P9-21 (UART2_TXD)
184 /*0x958*/ ENABLE | GPIO0 | 4, // GPIO-4 P9-17 (I2C1 SDA)
185 /*0x95c*/ ENABLE | GPIO0 | 5, // GPIO-5 P9-18 (I2C1 SCL)
186 /*0x960*/ ENABLE | GPIO0 | 6, // GPIO-6 ----- MMC0_CD
187 /*0x964*/ ENABLE | GPIO0 | 7, // GPIO-7 P9-42A connected to GPIO-114
188 /*0x968*/ ENABLE | GPIO1 | 8, // GPIO-40 ----- n.c.
189 /*0x96c*/ ENABLE | GPIO1 | 9, // GPIO-41 ----- (TESTPT1)
190 /*0x970*/ ENABLE | GPIO1 | 10, // GPIO-42 ----- UART0_RXD
191 /*0x974*/ ENABLE | GPIO1 | 11, // GPIO-43 ----- UART0_TXD
192 /*0x978*/ ENABLE | GPIO0 | 12, // GPIO-12 P9-20 I2C2_SDA (CAPE)
193 /*0x97c*/ ENABLE | GPIO0 | 13, // GPIO-13 P9-19 I2C2_SCL (CAPE)
194
195 /*0x980*/ ENABLE | GPIO0 | 14, // GPIO-14 P9-26 (UART1_RXD)
196 /*0x984*/ ENABLE | GPIO0 | 15, // GPIO-15 P9-24 (UART1_TXD)
197 /*0x988*/ ENABLE | GPIO3 | 5, // GPIO-101 ----- I2C0_SDA
198 /*0x98c*/ ENABLE | GPIO3 | 6, // GPIO-102 ----- I2C0_SCL
199 /*0x990*/ ENABLE | GPIO3 | 14, // GPIO-110 P9-31 (SPI1_SCLK)
200 /*0x994*/ ENABLE | GPIO3 | 15, // GPIO-111 P9-29 (SPI1_D0)
201 /*0x998*/ ENABLE | GPIO3 | 16, // GPIO-112 P9-30 (SPI1_D1)
202 /*0x99c*/ ENABLE | GPIO3 | 17, // GPIO-113 P9-28 (SPI1_CS0)
203 /*0x9a0*/ ENABLE | GPIO3 | 18, // GPIO-114 P9-42B connected to GPIO-7
204 /*0x9a4*/ ENABLE | GPIO3 | 19, // GPIO-115 P9-27
205 /*0x9a8*/ ENABLE | GPIO3 | 20, // GPIO-116 P9-41B connected TO GPIO-20
206 /*0x9ac*/ ENABLE | GPIO3 | 21, // GPIO-117 P9-25
207 /*0x9b0*/ ENABLE | GPIO0 | 19, // GPIO-19 CLKOUT HDMI
208 /*0x9b4*/ ENABLE | GPIO0 | 20, // GPIO-20 P9-41A CLKOUT
209 /*0x9b8*/ DISABLE, // WARMRSTN
210 /*0x9bc*/ DISABLE, // UNUSED
211
212 /*0x9c0*/ DISABLE, // nNMI -----
213 /*0x9c4*/ DISABLE, // UNUSED
214 /*0x9c8*/ DISABLE, // UNUSED
215 /*0x9cc*/ DISABLE, // UNUSED
216 /*0x9d0*/ DISABLE, // TMS ----- JTAG
217 /*0x9d4*/ DISABLE, // TDI ----- JTAG
218 /*0x9d8*/ DISABLE, // TDO ----- JTAG
219 /*0x9dc*/ DISABLE, // TCK ----- JTAG
220 /*0x9e0*/ DISABLE, // TRSTN ----- JTAG
221 /*0x9e4*/ ENABLE | GPIO3 | 7, // GPIO-103 ----- JTAG
222 /*0x9e8*/ ENABLE | GPIO3 | 8, // GPIO-104 ----- JTAG
223 /*0x9ec*/ DISABLE, // UNUSED
224 /*0x9f0*/ DISABLE, // UNUSED
225 /*0x9f4*/ DISABLE, // UNUSED
226 /*0x9f8*/ DISABLE, // PWRONRSTN
227 /*0x9fc*/ DISABLE // PMIC_POWER_EN
228};
229
230
231struct file_operations Fops = {
232 .open = device_open, /* open */
233 .release = device_release, /* close */
234 .read = device_read, /* read */
235 .write = device_write, /* write */
236 .unlocked_ioctl = device_ioctl, /* ioctl */
237};
238
239module_init (gpio_bbb_start);
240module_exit (gpio_bbb_end);
241
242
243/****************************************/
244/******* Module Lifecycle methods *******/
245/****************************************/
246static int __init gpio_bbb_start (void) {
247 struct device * dev;
248 int ret;
249
250 /* map memory areas */
251 ret = _map_memory();
252 if (ret < 0) return ret;
253 /* create device class */
254 cl = class_create( THIS_MODULE, "chardev" );
255 if (cl == NULL ) {
256 printk (KERN_ALERT MOD_STR"Class creation failed\n" );
257 return -EPERM;
258 }
259 /* set the file mode of /dev/gpio_bbb */
260 cl->dev_uevent = my_dev_uevent;
261
262 /* create device */
263 devnum = MKDEV(MAJOR_NUM, 0);
264 dev = device_create( cl, NULL, devnum, NULL, GPIO_DEV_NAME );
265 if (dev == NULL) {
266 printk(KERN_ALERT MOD_STR"Device creation failed\n" );
267 class_destroy(cl);
268 return -EPERM;
269 }
270 /* initialize and add device */
271 cdev_init( &c_dev, &Fops );
272 ret = cdev_add( &c_dev, devnum, 1 );
273 if(ret < 0) {
274 printk (KERN_ALERT MOD_STR"Device addition failed\n" );
275 device_destroy(cl, devnum);
276 class_destroy (cl);
277 return ret;
278 }
279 /* clear variables */
280 memset(&irq_enabled, 0, GPIO_COUNT);
281 /* initialize the wait queue */
282 init_waitqueue_head(&queue);
283 printk(KERN_INFO MOD_STR"Device %s registered\n", "/dev/"GPIO_DEV_NAME);
284 return 0;
285}
286
287static int my_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
288{
289 add_uevent_var(env, "DEVMODE=%#o", 0666);
290 return 0;
291}
292
293static void __exit gpio_bbb_end(void) {
294 /* unmap memory */
295 _unmap_memory();
296 /* release irqs and gpios */
297 _release_all_irqs();
298 /* unregister the device */
299 cdev_del ( &c_dev );
300 device_destroy (cl, devnum);
301 class_destroy (cl);
302 printk(KERN_INFO MOD_STR"Device %s unregistered\n", "/dev/"GPIO_DEV_NAME);
303}
304
305
306/****************************/
307/* Character device methods */
308/****************************/
309static int device_open (struct inode *inode, struct file *file) {
310 open_count++;
311 return 0;
312}
313
314static int device_release(struct inode *inode, struct file *file) {
315 open_count--;
316 if (open_count == 0) {
317 _release_all_irqs();
318 }
319 return 0;
320}
321
322static ssize_t device_read(struct file *filp, char *buff,
323 size_t len, loff_t *off) {
324 gpio_irq = -1;
325 // wait for interrupt to occur
326 wait_event_interruptible(queue, gpio_irq != -1);
327 // do the processing in user space...
328 return gpio_irq;
329}
330
331static ssize_t device_write(struct file *filp, const char *buff,
332 size_t len, loff_t *off) {
333 /* Generate a dummy interrupt. This
334 * can be used to e.g. terminate the
335 * irq handler in user space w/o
336 * using a signal... */
337 gpio_irq = -2;
338 wake_up_interruptible(&queue);
339 return 0;
340}
341
342long device_ioctl(struct file *file,
343 unsigned int ioctl_num, /* number and param for ioctl */
344 unsigned long ioctl_param) {
345
346 u8 gpio_num = ioctl_param & 0x7f;
347
348 switch(ioctl_num) {
349 case IOCTL_GPIO_MODE:
350 return _gpioMode(gpio_num, ioctl_param >> 8);
351 case IOCTL_GPIO_READ:
352 return _gpioRead(gpio_num);
353 case IOCTL_GPIO_WRITE:
354 return _gpioWrite(gpio_num, ioctl_param >> 8);
355 case IOCTL_GPIO_TOGGLE:
356 return _gpioToggle(gpio_num);
357 case IOCTL_GPIO_ATTACH_IRQ:
358 return _gpioAttachIrq(gpio_num, ioctl_param >> 8);
359 case IOCTL_GPIO_DETACH_IRQ:
360 return _gpioDetachIrq(gpio_num);
361 case IOCTL_GPIO_ENABLE_IRQ:
362 return _gpioEnableIrq(gpio_num);
363 case IOCTL_GPIO_DISABLE_IRQ:
364 return _gpioDisableIrq(gpio_num);
365 case IOCTL_SET_DEBOUNCE:
366 if (!(gpio_mode[gpio_num] & GPIO_REQUESTED)) return -EINVAL;
367 return gpio_set_debounce(gpio_num, ioctl_param >> 8);
368 }
369 return 0;
370}
371
372
373/****************/
374/* GPIO methods */
375/****************/
376static int _gpioMode(u8 gpio_num, u16 flags) {
377 u8 gpio_bank = gpio_num >> 5;
378 u32 gpio_mask = 1 << (gpio_num & 0x1f);
379
380 int ret;
381 u16 val;
382 /* calculate the offset */
383 u16 offset = _gpio_to_offset (gpio_num);
384 if (!(gpio_mode[gpio_num] & GPIO_REQUESTED)) {
385 if (offset < 0) return offset;
386 /* Try to request the gpio ... */
387 printk(KERN_INFO MOD_STR "Requesting GPIO #%i\n", gpio_num);
388 ret = gpio_request(gpio_num, GPIO_DEV_NAME);
389 if (ret < 0) {
390 /* okay, gpio is in use :( ... We might only switch */
391 /* on the receiver, if not already enabled */
392 if (flags == GPIO_INPUT) {
393 /* is the receiver already switched on ? */
394 ret = ioread32(ctrl_module_base + offset);
395 if (!(ret & 0x20)) {
396 printk(KERN_WARNING
397 MOD_STR "Enabling receiver on already used GPIO #%i\n", gpio_num);
398 _ioset32 (0x20, ctrl_module_base + offset);
399 gpio_mode[gpio_num] = flags;
400 return 0;
401 }
402 } else {
403 return ret;
404 }
405 }
406 /* store mode for later usage */
407 gpio_mode[gpio_num] = flags | GPIO_REQUESTED;
408 }
409 /* set modes in control module */
410 val = 0xf; // Mode 7 -> GPIO OUTPUT, no pullup/down, fast
411 if (flags & GPIO_INPUT) val |= 0x20;
412 if (flags & GPIO_PULLDOWN) val ^= 0x08; // toggle
413 if (flags & GPIO_PULLUP) val ^= 0x18;
414 if (flags & GPIO_SLOW) val |= 0x40;
415 if (flags & GPIO_FAST) val &= ~0x40;
416 iowrite32(val, ctrl_module_base + offset);
417 printk(KERN_INFO MOD_STR "GPIO #%i set to mode 0x%02X\n", gpio_num, val);
418
419 /* set IO mode in gpio bank */
420 if (flags & GPIO_INPUT) {
421 _ioset32 (gpio_mask, gpio_base[gpio_bank] + GPIO_OE);
422 }
423 if (flags & GPIO_OUTPUT) {
424 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_OE);
425 }
426 if (flags & GPIO_OUTPUT_OPEN_SOURCE) {
427 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_SETDATAOUT);
428 }
429 if (flags & GPIO_OUTPUT_OPEN_DRAIN) {
430 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_CLEARDATAOUT);
431 }
432 if (flags & GPIO_INIT_HIGH) {
433 _gpioWrite(gpio_num, 1);
434 }
435 if (flags & GPIO_INIT_LOW) {
436 _gpioWrite(gpio_num, 0);
437 }
438 return 0;
439}
440
441static int _gpioRead(u8 gpio_num) {
442 u8 gpio_bank = gpio_num >> 5;
443 u32 gpio_mask = 1 << (gpio_num & 0x1f);
444 u32 val;
445
446 if (gpio_mode[gpio_num] & GPIO_INPUT) {
447 val = ioread32(gpio_base[gpio_bank] + GPIO_DATAIN) & gpio_mask;
448 } else {
449 val = ioread32(gpio_base[gpio_bank] + GPIO_DATAOUT) & gpio_mask;
450 }
451 return (val) ? 1 : 0;
452}
453
454static int _gpioWrite (u8 gpio_num, int value) {
455 u8 gpio_bank = gpio_num >> 5;
456 u32 gpio_mask = 1 << (gpio_num & 0x1f);
457 u16 flags;
458
459 if (!(gpio_mode[gpio_num] & GPIO_REQUESTED)) return -EPERM;
460 flags = gpio_mode[gpio_num];
461 if (value) {
462 if (flags & GPIO_OUTPUT_OPEN_DRAIN) {
463 _ioset32(gpio_mask, gpio_base[gpio_bank] + GPIO_OE); // Input
464 return 0;
465 }
466 if (flags & GPIO_OUTPUT_OPEN_SOURCE) {
467 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_OE); // Output
468 return 0;
469 }
470 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_SETDATAOUT);
471 }
472 else {
473 if (flags & GPIO_OUTPUT_OPEN_DRAIN) {
474 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_OE); // Output
475 return 0;
476 }
477 if (flags & GPIO_OUTPUT_OPEN_SOURCE) {
478 _ioset32(gpio_mask, gpio_base[gpio_bank] + GPIO_OE); // Input
479 return 0;
480 }
481 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_CLEARDATAOUT);
482 }
483 return 0;
484}
485
486static int _gpioToggle (u8 gpio_num) {
487 u8 gpio_bank = gpio_num >> 5;
488 u32 gpio_mask = 1 << (gpio_num & 0x1f);
489
490 u32 val = ioread32(gpio_base[gpio_bank] + GPIO_DATAOUT) & gpio_mask;
491 return _gpioWrite(gpio_num, !val);
492}
493
494static int _gpioAttachIrq(u8 gpio_num, u16 flags) {
495 u8 gpio_bank = gpio_num >> 5;
496 u32 gpio_mask = 1 << (gpio_num & 0x1f);
497 int irq, ret;
498
499 /* request the irq and install handler */
500 if (!irq_enabled[gpio_num]) {
501 irq = gpio_to_irq(gpio_num);
502 /* request irq and install handler */
503 ret = request_any_context_irq (irq, _gpio_irq_handler, IRQF_SHARED, "gpio_bbb", &gpio_data);
504 if (ret < 0) {
505 printk(KERN_ERR MOD_STR"Failed to request IRQ %i (error %i)\n", irq, ret);
506 return ret;
507 }
508 // Set IRQ type
509 irq_set_irq_type(irq, IRQ_TYPE_NONE);
510 irq_enabled[gpio_num] = irq;
511 printk(KERN_INFO MOD_STR"Using IRQ #%i for GPIO #%i\n", irq, gpio_num);
512 }
513 /* configure the gpio irq triggers */
514 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_RISINGDETECT);
515 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_FALLINGDETECT);
516 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_LEVELDETECT1);
517 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_LEVELDETECT0);
518 if (flags & GPIO_RISING)
519 _ioset32 (gpio_mask, gpio_base[gpio_bank] + GPIO_RISINGDETECT);
520 if (flags & GPIO_FALLING)
521 _ioset32 (gpio_mask, gpio_base[gpio_bank] + GPIO_FALLINGDETECT);
522 if (flags & GPIO_LEVEL_HIGH)
523 _ioset32 (gpio_mask, gpio_base[gpio_bank] + GPIO_LEVELDETECT1);
524 if (flags & GPIO_LEVEL_LOW)
525 _ioset32 (gpio_mask, gpio_base[gpio_bank] + GPIO_LEVELDETECT0);
526 return 0;
527}
528
529static int _gpioDetachIrq(u8 gpio_num) {
530 u8 gpio_bank = gpio_num >> 5;
531 u32 gpio_mask = 1 << (gpio_num & 0x1f);
532
533 if (!irq_enabled[gpio_num]) return -EINVAL;
534 /* diable and clear the gpio irq */
535 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_IRQSTATUS_CLR_0);
536 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_IRQSTATUS_0);
537 /* release the irq */
538 _release_irq (gpio_num);
539 return 0;
540}
541
542static int _gpioEnableIrq(u8 gpio_num) {
543 u8 gpio_bank = gpio_num >> 5;
544 u32 gpio_mask = 1 << (gpio_num & 0x1f);
545
546 if (!irq_enabled[gpio_num]) return -EINVAL;
547 /* clear and re-enable irqs */
548 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_IRQSTATUS_0);
549 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_IRQSTATUS_SET_0);
550 return 0;
551}
552
553static int _gpioDisableIrq(u8 gpio_num) {
554 u8 gpio_bank = gpio_num >> 5;
555 u32 gpio_mask = 1 << (gpio_num & 0x1f);
556
557 if (!irq_enabled[gpio_num]) return -EINVAL;
558 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_IRQSTATUS_CLR_0);
559 iowrite32(gpio_mask, gpio_base[gpio_bank] + GPIO_IRQSTATUS_0);
560 return 0;
561}
562
563
564/*******************/
565/* Utility methods */
566/*******************/
567static void _ioset32(u32 v, void __iomem *addr) {
568 u32 tmp;
569 tmp = ioread32(addr);
570 tmp |= v;
571 iowrite32(tmp, addr);
572}
573
574static void _ioclear32(u32 v, void __iomem *addr) {
575 u32 tmp;
576 tmp = ioread32(addr);
577 tmp &= ~v;
578 iowrite32(tmp, addr);
579}
580
581static int _map_memory(void) {
582 int i;
583 ctrl_module_base = ioremap(CTRL_MODULE_ADDR, CTRL_MODULE_LEN);
584 if(!ctrl_module_base) {
585 printk (KERN_ALERT MOD_STR"Failed to map memory for CTRL_MODULE.%c\n", 0x20);
586 return -EPERM;
587 }
588 for (i=0; i < 4; ++i) {
589 gpio_base[i] = ioremap(GPIO_BANK_ADDR[i], GPIO_BANK_LEN);
590 if (!gpio_base[i]) {
591 printk (KERN_ALERT MOD_STR"Failed to map memory for GPIO bank %d.\n", i);
592 iounmap(ctrl_module_base);
593 for (--i; i >= 0; --i) iounmap(gpio_base[i]);
594 return -EPERM;
595 }
596 }
597 return 0;
598}
599
600static void _unmap_memory(void) {
601 int i;
602 iounmap (ctrl_module_base);
603 for(i=0; i < 4; ++i) iounmap (gpio_base[i]);
604}
605
606static u16 _gpio_to_offset(u8 gpio_num) {
607 u16 offset;
608 u8 entry = gpio_num | ENABLE;
609 for (offset = 0; offset < GPIO_COUNT; ++offset) {
610 if (gpio_data[offset] == entry)
611 break;
612 }
613 if (offset == GPIO_COUNT) return -EINVAL;
614 offset *= 4;
615 offset += 0x800;
616 return offset;
617}
618
619static u8 _irq_to_gpio(int irq) {
620 u8 i;
621 for (i=0; i < GPIO_COUNT; ++i) {
622 if (irq_enabled[i] == irq) break;
623 }
624 return (i==GPIO_COUNT) ? -1 : i;
625}
626
627static void _release_irq(u8 gpio_num) {
628 u8 gpio_bank = gpio_num >> 5;
629 u32 gpio_mask = 1 << (gpio_num & 0x1f);
630 u32 offset;
631 if (irq_enabled[gpio_num]) {
632 printk (KERN_INFO MOD_STR "Releasing IRQ #%i\n", irq_enabled[gpio_num]);
633 free_irq (irq_enabled[gpio_num], &gpio_data);
634 irq_enabled[gpio_num] = 0;
635 if (!(gpio_mode[gpio_num] & GPIO_REQUESTED)) {
636 /* the gpio was not requested, and the receiver */
637 /* was not enabled, when getting the irq. Since */
638 /* free_irq is enabling the receiver automatically, */
639 /* switch it off again... */
640 offset = _gpio_to_offset(gpio_num);
641 if (offset >= 0) {
642 /* disable receiver */
643 _ioclear32(0x20, ctrl_module_base + offset);
644 /* re-enable output */
645 _ioclear32(gpio_mask, gpio_base[gpio_bank] + GPIO_OE);
646 }
647 }
648 }
649}
650
651static void _release_all_irqs(void) {
652 int i;
653 for (i=0; i < GPIO_COUNT; ++i) {
654 _release_irq (i);
655 if (gpio_mode[i] & GPIO_REQUESTED) {
656 printk(KERN_INFO MOD_STR "Freeing GPIO #%i\n", i);
657 gpio_free(i);
658 pinctrl_free_gpio(i);
659 }
660 gpio_mode[i] = 0;
661 }
662}
663
664/*********************/
665/* interrupt handler */
666/*********************/
667irqreturn_t _gpio_irq_handler(int irq, void *dev_id) {
668 int gpio_num;
669 // Check dev_id
670 if (dev_id != (void *)&gpio_data) {
671 return IRQ_NONE;
672 }
673 // Get gpio number from irq
674 gpio_num = _irq_to_gpio(irq);
675 if (gpio_num >= 0) {
676 gpio_irq = gpio_num;
677 wake_up_interruptible(&queue);
678 }
679 return IRQ_HANDLED;
680}
681