add opendir alias
[minix.git] / lib / libgpio / gpio_omap.c
blobdcfc10a29eb747da6230fb3c01d524ae57c37ab3
1 /* kernel headers */
2 #include <minix/syslib.h>
3 #include <minix/drvlib.h>
4 #include <minix/log.h>
5 #include <minix/mmio.h>
6 #include <minix/gpio.h>
8 /* system headers */
9 #include <sys/mman.h>
10 #include <sys/types.h>
12 /* usr headers */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <assert.h>
20 #include "clkconf.h"
22 /* local headers */
24 /* used for logging */
25 static struct log log = {
26 .name = "gpio_omap",
27 .log_level = LEVEL_INFO,
28 .log_func = default_log
31 struct gpio_driver
33 /* request access to a gpio */
34 int (*claim) (char *owner, int nr, struct gpio ** gpio);
36 /* Configure the GPIO for a certain purpose */
37 int (*pin_mode) (struct gpio * gpio, int mode);
39 /* Set the value for a GPIO */
40 int (*set) (struct gpio * gpio, int value);
42 /* Read the current value of the GPIO */
43 int (*read) (struct gpio * gpio, int *value);
45 /* Read and clear the value interrupt value of the GPIO */
46 int (*intr_read) (struct gpio * gpio, int *value);
48 /* Interrupt hook */
49 int (*message_hook) (message * m);
52 static struct gpio_driver drv;
54 struct omap_gpio_bank
56 const char *name;
57 uint32_t register_address;
58 uint32_t irq_nr; /* irq number */
59 uint32_t base_address;
60 int32_t disabled;
61 int irq_id; /* orignhal hook id??? */
62 int irq_hook_id; /* hook id */
63 uint32_t inter_values; /* values when the interrupt was called */
66 #define GPIO1_BASE (0x48310000)
67 #define GPIO2_BASE (0x49050000)
68 #define GPIO3_BASE (0x49052000)
69 #define GPIO4_BASE (0x49054000)
70 #define GPIO5_BASE (0x49056000)
71 #define GPIO6_BASE (0x49058000)
72 #define GPIO1_IRQ 29 /* GPIO module 1 */
73 #define GPIO2_IRQ 30 /* GPIO module 2 */
74 #define GPIO3_IRQ 31 /* GPIO module 3 */
75 #define GPIO4_IRQ 32 /* GPIO module 4 */
76 #define GPIO5_IRQ 33 /* GPIO module 5 */
77 #define GPIO6_IRQ 34 /* GPIO module 6 */
78 #define GPIO1_IRQ_HOOK_ID 0
79 #define GPIO2_IRQ_HOOK_ID 1
80 #define GPIO3_IRQ_HOOK_ID 2
81 #define GPIO4_IRQ_HOOK_ID 3
82 #define GPIO5_IRQ_HOOK_ID 4
83 #define GPIO6_IRQ_HOOK_ID 5
85 #define GPIO_IRQSTATUS1 (0x18)
86 #define GPIO_IRQENABLE1 (0x01C)
87 #define GPIO_DATAOUT (0x3c)
88 #define GPIO_DATAIN (0x38)
89 #define GPIO_OE (0x34) /* Output Data Enable */
90 #define GPIO_RISINGDETECT1 (0x048)
91 #define GPIO_FALLINGDETECT1 (0x04c)
92 #define GPIO_CLEARDATAOUT (0x90)
93 #define GPIO_SETDATAOUT (0x94)
95 static struct omap_gpio_bank omap_gpio_banks[] = {
97 .name = "GPIO1",
98 .register_address = GPIO1_BASE,
99 .irq_nr = GPIO1_IRQ,
100 .base_address = 0,
101 .disabled = 0,
102 .irq_id = GPIO1_IRQ_HOOK_ID,
103 .irq_hook_id = GPIO1_IRQ_HOOK_ID,
106 .name = "GPIO2",
107 .register_address = GPIO2_BASE,
108 .irq_nr = GPIO2_IRQ,
109 .base_address = 0,
110 .disabled = 0,
111 .irq_id = GPIO2_IRQ_HOOK_ID,
112 .irq_hook_id = GPIO2_IRQ_HOOK_ID,
115 .name = "GPIO3",
116 .register_address = GPIO3_BASE,
117 .irq_nr = GPIO3_IRQ,
118 .base_address = 0,
119 .disabled = 0,
120 .irq_id = GPIO3_IRQ_HOOK_ID,
121 .irq_hook_id = GPIO3_IRQ_HOOK_ID,
124 .name = "GPIO4",
125 .register_address = GPIO4_BASE,
126 .irq_nr = GPIO4_IRQ,
127 .base_address = 0,
128 .disabled = 0,
129 .irq_id = GPIO4_IRQ_HOOK_ID,
130 .irq_hook_id = GPIO4_IRQ_HOOK_ID,
133 .name = "GPIO5",
134 .register_address = GPIO5_BASE,
135 .irq_nr = GPIO5_IRQ,
136 .base_address = 0,
137 .disabled = 0,
138 .irq_id = GPIO5_IRQ_HOOK_ID,
139 .irq_hook_id = GPIO5_IRQ_HOOK_ID,
142 .name = "GPIO6",
143 .register_address = GPIO6_BASE,
144 .irq_nr = GPIO6_IRQ,
145 .base_address = 0,
146 .disabled = 0,
147 .irq_id = GPIO6_IRQ_HOOK_ID,
148 .irq_hook_id = GPIO6_IRQ_HOOK_ID,
150 {NULL, 0, 0}
153 #define GPIO_REVISION 0x00
154 #define GPIO_REVISION_MAJOR(X) ((X & 0xF0) >> 4)
155 #define GPIO_REVISION_MINOR(X) (X & 0XF)
157 struct omap_gpio_bank *
158 omap_gpio_bank_get(int gpio_nr)
160 struct omap_gpio_bank *bank;
161 assert(gpio_nr >= 0 && gpio_nr <= 32 * 6);
162 bank = &omap_gpio_banks[gpio_nr / 32];
163 return bank;
167 omap_gpio_claim(char *owner, int nr, struct gpio **gpio)
169 log_trace(&log, "%s s claiming %d\n", owner, nr);
171 if (nr < 0 && nr >= 32 * 6) {
172 log_warn(&log, "%s is claiming unknown GPIO number %d\n",
173 owner, nr);
174 return EINVAL;
177 if (omap_gpio_bank_get(nr)->disabled == 1) {
178 log_warn(&log, "%s is claiming GPIO %d from disabled bank\n",
179 owner, nr);
180 return EINVAL;
183 struct gpio *tmp = malloc(sizeof(struct gpio));
184 memset(tmp, 0, sizeof(*tmp));
186 tmp->nr = nr;
187 *gpio = tmp;
188 return OK;
192 omap_gpio_pin_mode(struct gpio *gpio, int mode)
194 struct omap_gpio_bank *bank;
195 assert(gpio != NULL);
196 gpio->mode = mode;
198 bank = omap_gpio_bank_get(gpio->nr);
199 log_debug(&log,
200 "pin mode bank %s, base address 0x%x -> register address (0x%x,0x%x,0x%x)\n",
201 bank->name, bank->base_address, bank->register_address, GPIO_OE,
202 bank->register_address + GPIO_OE);
204 if (mode == GPIO_MODE_OUTPUT) {
205 set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32), 0);
206 } else {
207 set32(bank->base_address + GPIO_FALLINGDETECT1,
208 BIT(gpio->nr % 32), 0xffffffff);
209 set32(bank->base_address + GPIO_IRQENABLE1, BIT(gpio->nr % 32),
210 0xffffffff);
211 set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32),
212 0xffffffff);
214 return 0;
218 omap_gpio_set(struct gpio *gpio, int value)
220 struct omap_gpio_bank *bank;
221 assert(gpio != NULL);
222 assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
224 bank = omap_gpio_bank_get(gpio->nr);
225 if (value == 1) {
226 write32(bank->base_address + GPIO_SETDATAOUT,
227 BIT(gpio->nr % 32));
228 } else {
229 write32(bank->base_address + GPIO_CLEARDATAOUT,
230 BIT(gpio->nr % 32));
232 return OK;
236 omap_gpio_read(struct gpio *gpio, int *value)
238 struct omap_gpio_bank *bank;
239 assert(gpio != NULL);
240 assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
242 bank = omap_gpio_bank_get(gpio->nr);
243 log_trace(&log, "mode=%d OU/IN 0x%08x 0x%08x\n", gpio->mode,
244 read32(bank->base_address + GPIO_DATAIN),
245 read32(bank->base_address + GPIO_DATAOUT));
247 if (gpio->mode == GPIO_MODE_INPUT) {
248 *value =
249 (read32(bank->base_address +
250 GPIO_DATAIN) >> (gpio->nr % 32)) & 0x1;
251 } else {
252 *value =
253 (read32(bank->base_address +
254 GPIO_DATAOUT) >> (gpio->nr % 32)) & 0x1;
257 return OK;
261 omap_gpio_intr_read(struct gpio *gpio, int *value)
263 struct omap_gpio_bank *bank;
264 assert(gpio != NULL);
265 assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
267 bank = omap_gpio_bank_get(gpio->nr);
268 /* TODO: check if interrupt where enabled?? */
270 *value = (bank->inter_values >> (gpio->nr % 32)) & 0x1;
271 /* clear the data */
272 bank->inter_values &= ~(1 << (gpio->nr % 32));
274 return OK;
278 omap_message_hook(message * m)
280 unsigned long irq_set, i;
281 struct omap_gpio_bank *bank;
283 switch (_ENDPOINT_P(m->m_source)) {
284 case HARDWARE:
285 /* Hardware interrupt return a "set" if pending interrupts */
286 irq_set = m->NOTIFY_ARG;
287 log_debug(&log, "HW message 0X%08x\n", m->NOTIFY_ARG);
288 bank = &omap_gpio_banks[0];
289 for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
290 bank = &omap_gpio_banks[i];
292 if (irq_set & (1 << (bank->irq_id))) {
293 log_trace(&log, "Interrupt for bank %s\n",
294 bank->name);
295 bank->inter_values |=
296 read32(bank->base_address +
297 GPIO_IRQSTATUS1);
298 /* clear the interrupts */
299 write32(bank->base_address + GPIO_IRQSTATUS1,
300 0xffffffff);
301 if (sys_irqenable(&bank->irq_hook_id) != OK) {
302 log_warn(&log,
303 "Failed to enable irq for bank %s\n",
304 bank->name);
308 return OK;
309 default:
310 log_warn(&log, "Unknown message\n");
311 break;
313 return OK;
317 omap_gpio_init(struct gpio_driver *drv)
319 u32_t revision;
320 int i;
321 struct minix_mem_range mr;
322 struct omap_gpio_bank *bank;
324 bank = &omap_gpio_banks[0];
325 for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
326 bank = &omap_gpio_banks[i];
327 mr.mr_base = bank->register_address;
328 mr.mr_limit = bank->register_address + 0x400;
330 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
331 log_warn(&log,
332 "Unable to request permission to map memory\n");
333 return EPERM; /* fixme */
336 /* Set the base address to use */
337 bank->base_address =
338 (uint32_t) vm_map_phys(SELF,
339 (void *) bank->register_address, 0x400);
341 if (bank->base_address == (uint32_t) MAP_FAILED) {
342 log_warn(&log, "Unable to map GPIO memory\n");
343 return EPERM; /* fixme */
346 revision = 0;
347 revision = read32(bank->base_address + GPIO_REVISION);
348 /* test if we can access it */
349 if (GPIO_REVISION_MAJOR(revision) != 2
350 || GPIO_REVISION_MINOR(revision) != 5) {
351 log_warn(&log,
352 "Failed to read the revision of GPIO bank %s.. disabling\n",
353 bank->name);
354 bank->disabled = 1;
356 bank->disabled = 0;
358 if (sys_irqsetpolicy(bank->irq_nr, 0,
359 &bank->irq_hook_id) != OK) {
360 log_warn(&log,
361 "GPIO: couldn't set IRQ policy for bank %s\n",
362 bank->name);
363 continue;
365 if (bank->irq_id != bank->irq_hook_id) {
366 log_debug(&log, "requested id %d but got id %d\n",
367 bank->irq_id, bank->irq_hook_id);
369 if (sys_irqenable(&bank->irq_hook_id) != OK) {
370 log_warn(&log,
371 "GPIO: couldn't enable interrupt for %s\n",
372 bank->name);
374 log_trace(&log, "bank %s mapped on 0x%x with irq hook id %d\n",
375 bank->name, bank->base_address, bank->irq_hook_id);
379 clkconf_init();
380 /* enable the interface and functional clock on GPIO bank 1 */
381 clkconf_set(CM_FCLKEN_WKUP, BIT(3), 0xffffffff);
382 clkconf_set(CM_ICLKEN_WKUP, BIT(3), 0xffffffff);
383 clkconf_release();
386 drv->claim = omap_gpio_claim;
387 drv->pin_mode = omap_gpio_pin_mode;
388 drv->set = omap_gpio_set;
389 drv->read = omap_gpio_read;
390 drv->intr_read = omap_gpio_intr_read;
391 drv->message_hook = omap_message_hook;
392 return 0;
396 gpio_init()
398 return omap_gpio_init(&drv);
401 /* request access to a gpio */
403 gpio_claim(char *owner, int nr, struct gpio **gpio)
405 return drv.claim(owner, nr, gpio);
408 /* Configure the GPIO for a certain purpose */
410 gpio_pin_mode(struct gpio *gpio, int mode)
412 return drv.pin_mode(gpio, mode);
415 /* Set the value for a GPIO */
417 gpio_set(struct gpio *gpio, int value)
419 return drv.set(gpio, value);
422 /* Read the current value of the GPIO */
424 gpio_read(struct gpio *gpio, int *value)
426 return drv.read(gpio, value);
429 /* Read and clear the value interrupt value of the GPIO */
431 gpio_intr_read(struct gpio *gpio, int *value)
433 return drv.intr_read(gpio, value);
436 /* Interrupt hook */
438 gpio_intr_message(message * m)
440 return drv.message_hook(m);
444 gpio_release()
446 return OK;