/*------------------------------------------------------------------------------------------*\ * * Copyright (C) 2006 AVM GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include "avm_sammel.h" #include "avm_led.h" #include "avm_led_driver.h" /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) #include #else #include #include #endif struct _asm_led_gpio_bit_context *first_context = NULL; struct _asm_led_gpio_bit_context { struct _asm_led_gpio_bit_context *next; unsigned int link_count; unsigned int gpio_bit; unsigned int pos; unsigned int reverse; char name[32]; #if defined(CONFIG_ARCH_DAVINCI) struct resource *led_resource; #endif /*--- #if defined(CONFIG_ARCH_DAVINCI) ---*/ }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_led_gpio_bit_driver_init(unsigned int gpio_bit, unsigned int pos, char *name) { struct _asm_led_gpio_bit_context *context; struct _asm_led_gpio_bit_context *C = first_context; /*--- printk("[avm_led_gpio_bit_driver_init] start: gpio_bit %u pos %u name %s\n", gpio_bit, pos, name); ---*/ while(C) { /*--- printk("[avm_led_gpio_bit_driver_init] check %u == %u\n", C->gpio_bit, gpio_bit); ---*/ if(C->gpio_bit == gpio_bit) { C->link_count++; avm_led_gpio_bit_driver_action((unsigned int)C, 0); /*--- printk("[avm_led_gpio_bit_driver_init] old found: gpio_bit %u pos %u name %s\n", gpio_bit, pos, name); ---*/ return (int)C; } C = C->next; } context = (struct _asm_led_gpio_bit_context *)kmalloc(sizeof(struct _asm_led_gpio_bit_context), GFP_ATOMIC); memset(context, 0, sizeof(struct _asm_led_gpio_bit_context)); avm_gpio_ctrl(gpio_bit, GPIO_PIN, GPIO_OUTPUT_PIN); #if defined(CONFIG_MIPS) if(gpio_bit == 7) { context->reverse = 0; } else { context->reverse = 1; } #endif /*--- #if defined(CONFIG_MIPS) ---*/ context->link_count = 1; #if defined(CONFIG_ARCH_DAVINCI) context->led_resource = kmalloc(sizeof(struct resource) + strlen(name) + 1, GFP_ATOMIC); if(context->led_resource == NULL) { kfree(context); return 0; } /*--- printk("[avm_led_gpio_bit_driver_init] gpio %u pos %u name %s\n", gpio_bit, pos, name); ---*/ memset(context->led_resource, 0, sizeof(struct resource)); context->led_resource->name = (char *)((unsigned int)context->led_resource + sizeof(struct resource) + sizeof("LED: ")); strcpy(context->led_resource->name, "LED: "); strcat(context->led_resource->name, name); context->led_resource->start = gpio_bit; context->led_resource->end = gpio_bit; if(request_resource(&gpio_resource, context->led_resource)) { printk(KERN_ERR "GPIO %u: already in use, led driver init failed\n", gpio_bit); kfree(context->led_resource); kfree(context); } #endif /*--- #if defined(CONFIG_ARCH_DAVINCI) ---*/ context->gpio_bit = gpio_bit; context->pos = pos; memcpy(context->name, name, sizeof(context->name)); context->name[sizeof(context->name) - 1] = '\0'; avm_led_gpio_bit_driver_action((unsigned int)context, 0); if(first_context == NULL) first_context = context; else { context->next = first_context; first_context = context; } return (int)context; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ char *avm_led_gpio_bit_driver_show(unsigned int handle, unsigned int *pPos) { struct _asm_led_gpio_bit_context *context = (struct _asm_led_gpio_bit_context *)handle; if(pPos) *pPos = context->pos; DEB_NOTE("[avm_led]: single gpio driver: GPIO %u %s (pin %u \"%s\")\n", context->gpio_bit, context->reverse ? "inverted" : "normal", context->pos, context->name); return context->name; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_led_gpio_bit_driver_exit(unsigned int handle) { if(handle) kfree((void *)handle); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_led_gpio_bit_driver_action(unsigned int handle, unsigned int on) { struct _asm_led_gpio_bit_context *context = (struct _asm_led_gpio_bit_context *)handle; on = on ? 1 : 0; on = context->reverse ? !on : on; return avm_gpio_out_bit(context->gpio_bit, on); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_led_gpio_bit_driver_sync(unsigned int handle, unsigned int state_id) { return 0; }