/* gpio.c * * This file is the gpio driver for the Milkymist One board * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. * * $Id$ * * COPYRIGHT (c) Yann Sionneau (GSoC 2010) * Telecom SudParis */ #include #include #include #include #include #include #include #include "../include/system_conf.h" #include #define GPIO_DRIVER_TABLE_ENTRY { gpio_initialize, \ gpio_open, gpio_close, gpio_read, gpio_write, gpio_control} #define LED1_DEVICE_NAME "/dev/led1" #define LED2_DEVICE_NAME "/dev/led2" #define BTN1_DEVICE_NAME "/dev/btn1" #define BTN2_DEVICE_NAME "/dev/btn2" #define BTN3_DEVICE_NAME "/dev/btn3" static struct milkymist_gpio { rtems_device_minor_number minor; unsigned int *address; unsigned int offset; uint8_t readonly; pthread_mutex_t mutex; } gpio[5]; rtems_device_driver gpio_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { rtems_status_code status; printk( "gpio driver initializing..\n" ); status = rtems_io_register_name(LED1_DEVICE_NAME, major, 0); if (status != RTEMS_SUCCESSFUL) { printk("Error registering gpio device led1\n"); rtems_fatal_error_occurred( status ); } gpio[0].minor = 0; gpio[0].readonly = 0; gpio[0].offset = 0x00000001; gpio[0].address = (unsigned int *)0xe0001004; gpio[0].mutex = PTHREAD_MUTEX_INITIALIZER; status = rtems_io_register_name(LED2_DEVICE_NAME, major, 1); if (status != RTEMS_SUCCESSFUL) { printk("Error registering gpio device led2\n"); rtems_fatal_error_occurred( status ); } gpio[1].minor = 1; gpio[1].readonly = 0; gpio[1].offset = 0x00000002; gpio[1].address = (unsigned int *)0xe0001004; gpio[1].mutex = PTHREAD_MUTEX_INITIALIZER; status = rtems_io_register_name(BTN1_DEVICE_NAME, major, 2); if (status != RTEMS_SUCCESSFUL) { printk("Error registering gpio device btn1\n"); rtems_fatal_error_occurred( status ); } gpio[2].minor = 2; gpio[2].readonly = 1; gpio[2].offset = 0x00000001; gpio[2].address = (unsigned int *)0xe0001000; gpio[2].mutex = PTHREAD_MUTEX_INITIALIZER; status = rtems_io_register_name(BTN2_DEVICE_NAME, major, 3); if (status != RTEMS_SUCCESSFUL) { printk("Error registering gpio device btn2\n"); rtems_fatal_error_occurred( status ); } gpio[3].minor = 3; gpio[3].readonly = 1; gpio[3].address = (unsigned int *)0xe0001000; gpio[3].offset = 0x00000002; gpio[3].mutex = PTHREAD_MUTEX_INITIALIZER; status = rtems_io_register_name(BTN3_DEVICE_NAME, major, 4); if (status != RTEMS_SUCCESSFUL) { printk("Error registering gpio device btn3\n"); rtems_fatal_error_occurred( status ); } gpio[4].minor = 4; gpio[4].readonly = 1; gpio[4].offset = 0x00000004; gpio[4].address = (unsigned int *)0xe0001000; gpio[4].mutex = PTHREAD_MUTEX_INITIALIZER; return RTEMS_SUCCESSFUL; } rtems_device_driver gpio_close( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { if (pthread_mutex_unlock(&gpio[minor].mutex) == 0){ return RTEMS_SUCCESSFUL; } return RTEMS_UNSATISFIED; } rtems_device_driver gpio_open( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { if (pthread_mutex_trylock(&gpio[minor].mutex) == 0){ return RTEMS_SUCCESSFUL; } return RTEMS_UNSATISFIED; } rtems_device_driver gpio_read( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; rw_args->bytes_moved = 1; if ( *gpio[minor].address & gpio[minor].offset ) *(uint8_t *)rw_args->buffer = 1; else *(uint8_t *)rw_args->buffer = 0; return RTEMS_SUCCESSFUL; } rtems_device_driver gpio_write( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; rw_args->bytes_moved = 1; if (gpio[minor].readonly) return RTEMS_UNSATISFIED; if ( *(uint8_t *)rw_args->buffer ) *gpio[minor].address |= gpio[minor].offset; else *gpio[minor].address &= ~gpio[minor].offset; return RTEMS_SUCCESSFUL; } rtems_device_driver gpio_control( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_libio_ioctl_args_t *args = arg; switch( args->command ) { default: args->ioctl_return = 0; break; } return RTEMS_SUCCESSFUL; }