/****************************************************************************** * FILE PURPOSE: - LED HAL module source ****************************************************************************** * FILE NAME: led_hal.c * * DESCRIPTION: LED HAL API's source. * * REVISION HISTORY: * 27 Aug 2003 Initial Creation Sharath Kumar * * 16 Dec 2003 Updates for 5.7 Sharath Kumar * * 07 Jan 2004 Wrapper for DSL Sharath Kumar * * (C) Copyright 2002, Texas Instruments, Inc *******************************************************************************/ #include #include "led_platform.h" #include #include "led_hal.h" #if defined(CONFIG_MIPS_OHIO) #include #include #include #include #include #endif /*--- #if defined(CONFIG_MIPS_OHIO) ---*/ #if defined(CONFIG_MIPS_AR7) #include #include #include #include #include #endif /*--- #if defined(CONFIG_MIPS_AR7) ---*/ #if defined(CONFIG_MIPS_UR8) #include #include #include #include #include #endif /*--- #if defined(CONFIG_MIPS_UR8) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if 0 #define DEB_EVENT(args...) printk(KERN_ERR args) #else #define DEB_EVENT(args...) #endif #define REQUIRES_TIMER(x) ((x == LED_ONESHOT_ON) || (x == LED_ONESHOT_OFF) || (x == LED_FLASH) || (x == LED_BLINK_CODE0) || (x == LED_BLINK_CODE1) || (x == LED_BLINK_CODE2)) /*******************TYPEDEFs**************************************************/ typedef struct { unsigned int state[MAX_MODULE_INSTANCES]; unsigned int module_map; unsigned int pos_map[2]; } LED_OBJ_T; typedef struct state_entry STATE_ENTRY_T; struct state_entry { void (*handler) (STATE_ENTRY_T * state); unsigned int timer_running; LED_OBJ_T *led; unsigned int map1[2]; unsigned int map2[2]; void *os_timer; unsigned int param1; unsigned int param2; unsigned int module_id; unsigned int instance; unsigned int mode; }; typedef struct module_instance { int module_id; int instance; struct _module_instance_event { int id; unsigned int buffer_len; void *buffer; } event; STATE_ENTRY_T *states[MAX_STATE_ENTRIES]; } MODULE_INSTANCE_T; typedef struct module_entry { unsigned char *name; MODULE_INSTANCE_T *module_instance[MAX_MODULE_INSTANCES]; } MODULE_ENTRY_T; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ enum _led_blink_state { led_blink_0_state_next_on_0, led_blink_1_state_next_on_0, led_blink_1_state_next_off_0, led_blink_1_state_next_on_1, led_blink_2_state_next_on_0, led_blink_2_state_next_off_0, led_blink_2_state_next_on_1, led_blink_2_state_next_short_pause, led_blink_2_state_next_on_2, led_blink_0_state_next_pause, led_blink_1_state_next_pause, led_blink_2_state_next_pause }; char *_led_blink_state_name[] = { "led_blink_0_state_next_on_0", "led_blink_1_state_next_on_0", "led_blink_1_state_next_off_0", "led_blink_1_state_next_on_1", "led_blink_2_state_next_on_0", "led_blink_2_state_next_off_0", "led_blink_2_state_next_on_1", "led_blink_2_state_next_short_pause", "led_blink_2_state_next_on_2", "led_blink_0_state_next_pause" "led_blink_1_state_next_pause" "led_blink_2_state_next_pause" }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define MAX_LATE_ACTIONS 20 static unsigned int avalanche_led_configurated = 0; static struct _avalanche_led_late_action { void *handle; int state; } avalanche_led_late_action[MAX_LATE_ACTIONS]; /******************variable defn/declns***************************************/ static LED_OBJ_T *leds[MAX_LED_ENTRIES]; static MODULE_ENTRY_T *modules[MAX_MODULE_ENTRIES]; /* Declare Mutex lock */ spinlock_t avm_led_lock = SPIN_LOCK_UNLOCKED; /* GPIO OFF STATE */ static unsigned int gpio_offstate_map[2]; /* Number of GPIO pins in the system */ static unsigned int num_gpios; /* LED handlers */ static void (*led_mode_handler[NUM_LED_MODES]) (STATE_ENTRY_T * state); /******************static functions*****************************************/ static void *led_malloc (int n) { void *p; p = os_malloc (n); if (p) os_memset (p, 0, n); return p; } unsigned led_state[2][MAX_MODULE_INSTANCES][32]; /*--- fuer 64 LEDs ---*/ /*------------------------------------------------------------------------------------------*\ * STATE_ENTRY_T * state \*------------------------------------------------------------------------------------------*/ static void avalanche_gpio_set(int *set_map, int *pos_map, STATE_ENTRY_T *state) { unsigned int output_set_map; int i, index; #if 0 int i; for(i = 0; i < num_gpios ; i += 32) { int index = i/32; /*--- DEB_INFO("[avalanche_led/avalanche_gpio_set]: set mask 0x%x clear mask 0x%x index %u\n", set_map[index], pos_map[index], index); ---*/ avalanche_gpio_out_value(set_map[index], pos_map[index],index); } #endif DEB_INFO("avalanche_gpio_set(set: 0x%x pos: 0x%x id=%u)\n", set_map[0], pos_map[0], state->module_id); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ #if 0 if(state->instance == 0) { for( i = 0 ; i < MAX_MODULE_ENTRIES ; i++) { int ii; if(modules[i] == 0) continue; for(ii = 0 ; ii < MAX_MODULE_INSTANCES ; ii++) { int iii; if(modules[i]->module_instance[ii] == 0) continue; for( iii = 0 ; iii < MAX_STATE_ENTRIES ; iii++) { if(modules[i]->module_instance[ii]->states[iii] == state) { DEB_INFO("[%s] module_id %u instance %u\n", (char *)(modules[i]->name ? (char *)modules[i]->name : "no name"), modules[i]->module_instance[ii]->module_id, modules[i]->module_instance[ii]->instance); state->instance = modules[i]->module_instance[ii]->instance + 1; goto found; } } } } } found: #endif /*--------------------------------------------------------------------------------------*\ * fuer alle möglichen LEDs \*--------------------------------------------------------------------------------------*/ for(index = 0 ; index < (num_gpios / 32) ; index++) { unsigned int bit_pos = state->module_id; output_set_map = 0; if(bit_pos >= 32) { DEB_INFO("[avalanche_gpio_set] ERROR: led_state Bit mask to large %u\n", bit_pos); return; } for(i = 0 ; i < 32 ; i++) { int ii; /*----------------------------------------------------------------------------------*\ * fuer jede LED die in pos_map gesetzt ist das zur Instanz gehörende Bit in * led_state löschen \*----------------------------------------------------------------------------------*/ if(pos_map[index] & (1 << i)) { led_state[index][state->instance][i] &= ~(1 << bit_pos); } else { continue; } /*----------------------------------------------------------------------------------*\ * fuer jede LED die in set_map gesetzt ist das zur Instanz gehörende Bit in * led_state setzen \*----------------------------------------------------------------------------------*/ if((set_map[index] & (1 << i)) == 0) { led_state[index][state->instance][i] |= (1 << bit_pos); } /*----------------------------------------------------------------------------------*\ * das Bit in der output set mask setzen wenn irgend ein Bit in dem entsprechenden * led_state gesetzt ist. \*----------------------------------------------------------------------------------*/ for(ii = 0 ; ii < MAX_MODULE_INSTANCES ; ii++) { if(led_state[index][ii][i]) { output_set_map |= 1 << i; break; } } } output_set_map = ~output_set_map & pos_map[index]; DEB_INFO("gpio_set(output: 0x%x pos: 0x%x id=%u, index=%u)\n", output_set_map, pos_map[index], state->module_id, index); #if defined(CONFIG_AVM_UBIK2) ubik2_ioarea_systemservices->GPIO.GPOUT[index] &= ~pos_map[index]; ubik2_ioarea_systemservices->GPIO.GPOUT[index] |= output_set_map & pos_map[index]; #endif /*--- #if defined(CONFIG_AVM_UBIK2) ---*/ #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) /*--- *GPIO_OUT &= ~pos_map[index]; ---*/ /*--- *GPIO_OUT |= output_set_map & pos_map[index]; ---*/ avm_gpio_set_bitmask(pos_map[index], output_set_map); #endif /*--- #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) ---*/ } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static MODULE_INSTANCE_T *get_module (char *name, int instance) { int module_id; MODULE_INSTANCE_T *mod_inst; DEB_INFO("[avalanche_led/get_module]: find: name=%s instance=%u\n", name, instance); if (instance >= MAX_MODULE_INSTANCES) { DEB_ERR("[avalanche_led/get_module]: instance > MAX_MODULE_INSTANCES (%u)\n", MAX_MODULE_INSTANCES); return NULL; } for (module_id = 0; module_id < MAX_MODULE_ENTRIES; module_id++) { if (modules[module_id] && !os_strcmp (name, modules[module_id]->name)) { DEB_INFO("[avalanche_led/get_module]: module found module_id=%u name=%s\n", module_id, name); break; } } if (module_id == MAX_MODULE_ENTRIES) { for (module_id = 0; (module_id < MAX_MODULE_ENTRIES) && modules[module_id]; module_id++) ; if (module_id < MAX_MODULE_ENTRIES) { modules[module_id] = led_malloc (sizeof (MODULE_ENTRY_T)); if (!modules[module_id]) { DEB_ERR("[avalanche_led/get_module]: module (%u) not valid\n", module_id); return NULL; } modules[module_id]->name = led_malloc (os_strlen (name) + 1); if (!modules[module_id]->name) { DEB_ERR("[avalanche_led/get_module]: module (%u) has no name\n", module_id); return NULL; } os_strcpy (modules[module_id]->name, name); } else { log_msg ("ERROR:Module Count exceeded\n"); return NULL; } } if (!modules[module_id]->module_instance[instance]) { modules[module_id]->module_instance[instance] = led_malloc (sizeof (MODULE_INSTANCE_T)); } if (!modules[module_id]->module_instance[instance]) { DEB_ERR("[avalanche_led/get_module]: instance (%u) not valid\n", instance); return NULL; } mod_inst = modules[module_id]->module_instance[instance]; mod_inst->module_id = module_id; mod_inst->instance = instance; DEB_INFO("[avalanche_led/get_module]: handle=0x%p\n", (void *)mod_inst); return mod_inst; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void assign_map(int *to, int *from) { int i; for(i = 0 ; i < num_gpios ; i += 32) { int index = i/32; to[index] = from[index]; } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static LED_OBJ_T *get_led (int * pos_map) { int led_id; for (led_id = 0; led_id < MAX_LED_ENTRIES ; led_id++) { if (leds[led_id]) { int i; int flag=0; for(i = 0 ; i < num_gpios ; i += 32) { int index = i/32; if(leds[led_id]->pos_map[index] != pos_map[index]) flag =1; } if(flag == 0) break; } } if (led_id == MAX_LED_ENTRIES) { for (led_id = 0 ; (led_id < MAX_LED_ENTRIES) && leds[led_id] ; led_id++) ; if (led_id < MAX_LED_ENTRIES) { leds[led_id] = led_malloc (sizeof (LED_OBJ_T)); if (!leds[led_id]) return NULL; assign_map(leds[led_id]->pos_map, pos_map); } else { log_msg ("ERROR:Module Count exceeded\n"); return NULL; } } return leds[led_id]; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_oneshot_on_timer_func (int arg) { STATE_ENTRY_T *state = (STATE_ENTRY_T *) arg; LED_OBJ_T *led = state->led; unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); state->timer_running = 0; led->state[state->instance] = LED_OFF; avalanche_gpio_set(state->map2, led->pos_map, state); spin_unlock_irqrestore(&avm_led_lock, flags); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_oneshot_off_timer_func (int arg) { STATE_ENTRY_T *state = (STATE_ENTRY_T *) arg; LED_OBJ_T *led = state->led; unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); state->timer_running = 0; led->state[state->instance] = LED_ON; avalanche_gpio_set(state->map2, led->pos_map, state); spin_unlock_irqrestore(&avm_led_lock, flags); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_flash_timer_func (int arg) { STATE_ENTRY_T *state = (STATE_ENTRY_T *) arg; LED_OBJ_T *led = state->led; unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); if (led->state[state->instance] != LED_FLASH) { state->timer_running = 0; spin_unlock_irqrestore(&avm_led_lock, flags); DEB_INFO("[led_flash_timer_func] instance = %u state (%u) != LED_FLASH: stop timer\n", state->instance, led->state[state->instance]); return; } if (state->timer_running == 1) { state->timer_running = 2; avalanche_gpio_set(state->map2, led->pos_map, state); os_timer_add (state->os_timer, state->param2, (int)state); } else { state->timer_running = 1; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, state->param1, (int)state); } spin_unlock_irqrestore(&avm_led_lock, flags); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define set_blink_state(text, var, value) { DEB_INFO("[set_blink_state]: %s %s->%s\n", text, _led_blink_state_name[var], _led_blink_state_name[value]); (var) = (value); } static void led_blink_code_timer_func (int arg) { STATE_ENTRY_T *state = (STATE_ENTRY_T *) arg; LED_OBJ_T *led = state->led; enum _led_blink_state blink_state = (state->timer_running >> 1) & 0xFF; unsigned int blink_count = state->timer_running >> 9; unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); switch(blink_state) { case led_blink_0_state_next_on_0: case led_blink_0_state_next_pause: if(led->state[state->instance] != LED_BLINK_CODE0) state->timer_running = 0; break; case led_blink_1_state_next_on_0: case led_blink_1_state_next_off_0: case led_blink_1_state_next_on_1: case led_blink_1_state_next_pause: if(led->state[state->instance] != LED_BLINK_CODE1) state->timer_running = 0; break; case led_blink_2_state_next_on_0: case led_blink_2_state_next_off_0: case led_blink_2_state_next_on_1: case led_blink_2_state_next_short_pause: case led_blink_2_state_next_on_2: case led_blink_2_state_next_pause: if(led->state[state->instance] != LED_BLINK_CODE2) state->timer_running = 0; break; } if(state->timer_running == 0) { spin_unlock_irqrestore(&avm_led_lock, flags); DEB_INFO("[led_blink_code_timer_funcX] instance = %u state (%u) != LED_LED_BLINK_CODE[012]: stop timer\n", state->instance, led->state[state->instance]); return; } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ switch(blink_state) { /*----------------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------------*/ case led_blink_0_state_next_on_0: avalanche_gpio_set(state->map1, led->pos_map, state); /*--- einschalten ---*/ os_timer_add (state->os_timer, state->param1, (int)state); set_blink_state("(handle led_blink_0_state_next_on_0)", blink_state, led_blink_0_state_next_pause); break; /*----------------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------------*/ case led_blink_1_state_next_on_0: avalanche_gpio_set(state->map1, led->pos_map, state); /*--- einschalten ---*/ os_timer_add (state->os_timer, state->param1 / 4, (int)state); set_blink_state("(handle led_blink_1_state_next_on_0)", blink_state, led_blink_1_state_next_off_0); break; case led_blink_1_state_next_off_0: avalanche_gpio_set(state->map2, led->pos_map, state); /*--- ausschalten ---*/ os_timer_add (state->os_timer, state->param1 / 4, (int)state); set_blink_state("(handle led_blink_1_state_next_off_0)", blink_state, led_blink_1_state_next_on_1); break; case led_blink_1_state_next_on_1: avalanche_gpio_set(state->map1, led->pos_map, state); /*--- einschalten ---*/ os_timer_add (state->os_timer, state->param1 / 4, (int)state); set_blink_state("(handle led_blink_1_state_next_on_1)", blink_state, led_blink_1_state_next_pause); break; /*----------------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------------*/ case led_blink_2_state_next_on_0: avalanche_gpio_set(state->map1, led->pos_map, state); /*--- einschalten ---*/ os_timer_add (state->os_timer, state->param1 / 4, (int)state); set_blink_state("(handle led_blink_2_state_next_on_0)", blink_state, led_blink_2_state_next_off_0); break; case led_blink_2_state_next_off_0: avalanche_gpio_set(state->map2, led->pos_map, state); /*--- ausschalten ---*/ os_timer_add (state->os_timer, state->param1 / 4, (int)state); set_blink_state("(handle led_blink_2_state_next_off_0)", blink_state, led_blink_2_state_next_on_1); break; case led_blink_2_state_next_on_1: avalanche_gpio_set(state->map1, led->pos_map, state); /*--- einschalten ---*/ os_timer_add (state->os_timer, state->param1 / 4, (int)state); set_blink_state("(handle led_blink_2_state_next_on_1)", blink_state, led_blink_2_state_next_short_pause); break; case led_blink_2_state_next_short_pause: avalanche_gpio_set(state->map2, led->pos_map, state); /*--- ausschalten ---*/ os_timer_add (state->os_timer, state->param1 * 2, (int)state); set_blink_state("(handle led_blink_2_state_next_short_pause)", blink_state, led_blink_2_state_next_on_2); break; case led_blink_2_state_next_on_2: avalanche_gpio_set(state->map1, led->pos_map, state); /*--- einschalten ---*/ os_timer_add (state->os_timer, state->param1, (int)state); set_blink_state("(handle led_blink_2_state_next_on_2)", blink_state, led_blink_2_state_next_pause); break; /*----------------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------------*/ case led_blink_0_state_next_pause: case led_blink_1_state_next_pause: case led_blink_2_state_next_pause: avalanche_gpio_set(state->map2, led->pos_map, state); /*--- ausschalten ---*/ blink_count--; if(blink_count == 0) { os_timer_add (state->os_timer, state->param1 * 5, (int)state); blink_count = state->param2; } else { if(blink_state == led_blink_2_state_next_pause) os_timer_add (state->os_timer, state->param1 * 2, (int)state); else os_timer_add (state->os_timer, state->param1, (int)state); } switch(blink_state) { case led_blink_0_state_next_pause: set_blink_state("(LED_BLINK_CODE0: handle led_blink_all_state_next_pause )", blink_state, led_blink_0_state_next_on_0); break; case led_blink_1_state_next_pause: set_blink_state("(LED_BLINK_CODE1: handle led_blink_all_state_next_pause )", blink_state, led_blink_1_state_next_on_0); break; case led_blink_2_state_next_pause: set_blink_state("(LED_BLINK_CODE2: handle led_blink_all_state_next_pause )", blink_state, led_blink_2_state_next_on_0); break; default: break; } break; default: DEB_ERR("[led_blink_code_timer_func] unknown blink-state %u\n", blink_state); break; } if(state->timer_running) state->timer_running = (blink_state << 1) | (blink_count << 9) | 1; spin_unlock_irqrestore(&avm_led_lock, flags); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_on(STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; DEB_INFO("[led_on]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_ON); led->state[state->instance] = LED_ON; avalanche_gpio_set(state->map1, led->pos_map, state); led->module_map |= (1 << (state->module_id)); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_off (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; DEB_INFO("[led_off]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_OFF); led->module_map &= ~(1 << (state->module_id)); if (!led->module_map) { led->state[state->instance] = LED_OFF; avalanche_gpio_set(state->map1, led->pos_map, state); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_oneshot_on (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; if (state->timer_running) { DEB_WARN("[led_oneshot_on]: instance = %u pos 0x%X, cancel: timer still running\n", state->instance, led->pos_map[0]); return; } DEB_INFO("[led_oneshot_on]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_ON); state->timer_running = 1; led->state[state->instance] = LED_ON; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, state->param1,(int) state); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_oneshot_off (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; if (state->timer_running) { DEB_WARN("[led_oneshot_off]: instance = %u pos 0x%X, cancel: timer still running\n", state->instance, led->pos_map[0]); return; } DEB_INFO("[led_oneshot_off]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_OFF); state->timer_running = 1; led->state[state->instance] = LED_OFF; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, state->param1,(int) state); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_flash (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; if (state->timer_running) { DEB_WARN("[led_flash]: instance = %u pos 0x%X, cancel: timer still running\n", state->instance, led->pos_map[0]); return; } DEB_INFO("[led_flash ]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_FLASH); state->timer_running = 1; led->state[state->instance] = LED_FLASH; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, state->param1,(int) state); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_blink_code0 (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; enum _led_blink_state blink_state = 0; unsigned int blink_count; if (state->timer_running) { DEB_WARN("[led_blink_code0]: instance = %u pos 0x%X cancel: timer still running\n", state->instance, led->pos_map[0]); return; } DEB_INFO("[led_blink_code0]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_BLINK_CODE0); set_blink_state("(led_blink_code0)", blink_state, led_blink_0_state_next_pause); blink_count = state->param2; led->state[state->instance] = LED_BLINK_CODE0; state->timer_running = (blink_state << 1) | (blink_count << 9) | 1; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, state->param1,(int) state); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_blink_code1 (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; enum _led_blink_state blink_state = 0; unsigned int blink_count; if (state->timer_running) { DEB_WARN("[led_blink_code1]: instance = %u pos 0x%X cancel: timer still running\n", state->instance, led->pos_map[0]); return; } DEB_INFO("[led_blink_code1]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_BLINK_CODE0); set_blink_state("(led_blink_code1)", blink_state, led_blink_1_state_next_off_0); blink_count = state->param2; state->timer_running = (blink_state << 1) | (blink_count << 9) | 1; led->state[state->instance] = LED_BLINK_CODE1; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, (state->param1) / 4 ,(int) state); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_blink_code2 (STATE_ENTRY_T * state) { LED_OBJ_T *led = state->led; enum _led_blink_state blink_state = 0; unsigned int blink_count; if (state->timer_running) { DEB_WARN("[led_blink_code2]: instance = %u pos 0x%X cancel: timer still running\n", state->instance, led->pos_map[0]); return; } DEB_INFO("[led_blink_code2]: instance = %u pos 0x%X (State %u -> %u)\n", state->instance, led->pos_map[0], led->state[state->instance], LED_BLINK_CODE0); set_blink_state("(led_blink_code2)", blink_state, led_blink_2_state_next_off_0); blink_count = state->param2; state->timer_running = (blink_state << 1) | (blink_count << 9) | 1; led->state[state->instance] = LED_BLINK_CODE2; avalanche_gpio_set(state->map1, led->pos_map, state); os_timer_add (state->os_timer, (state->param1) / 4,(int) state); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int led_get_mode(LED_CONFIG_T *led_cfg) { int num_gpio = led_cfg->gpio_num; int i; int *led_mode = led_cfg->mode; int max = -1; /* Return Max of available modes */ for(i = 0; i < num_gpio ; i++) { max = (max > led_mode[i]) ? max : led_mode[i]; } return max; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void led_assign_timer(STATE_ENTRY_T *state_entry) { if (state_entry->os_timer) { os_timer_delete(state_entry->os_timer); } switch(state_entry->mode) { case LED_ONESHOT_ON: state_entry->os_timer = os_timer_init(led_oneshot_on_timer_func); break; case LED_ONESHOT_OFF: state_entry->os_timer = os_timer_init(led_oneshot_off_timer_func); break; case LED_FLASH: state_entry->os_timer = os_timer_init(led_flash_timer_func); break; case LED_BLINK_CODE0: case LED_BLINK_CODE1: case LED_BLINK_CODE2: state_entry->os_timer = os_timer_init(led_blink_code_timer_func); break; default: log_msg("invalid mode in function led_assign timer\n"); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int led_get_map(LED_CONFIG_T *led_cfg, int *p_pos_map, int *p_map1, int *p_map2) { int i; int map1[2] = {0,0}; int pos_map[2] = {0,0}; int map2[2] = {0,0}; int requires_timer = REQUIRES_TIMER(led_get_mode(led_cfg)); for (i = 0; i < led_cfg->gpio_num; i++) { int gpio_map; int index = led_cfg->gpio[i]/32; int pos = led_cfg->gpio[i] % 32; if (led_cfg->gpio[i] >= num_gpios) { log_msg ("Error: gpio number out of range\n"); return -1; } gpio_map = 1 << pos; pos_map[index] |= gpio_map; switch (led_cfg->mode[i]) { case LED_OFF: if(gpio_offstate_map[index] & gpio_map) map1[index] |= gpio_map; if (requires_timer && (gpio_offstate_map[index] & gpio_map)) map2[index] |= gpio_map; break; case LED_ON: if(!(gpio_offstate_map[index] & gpio_map)) map1[index] |= gpio_map; if (requires_timer && !(gpio_offstate_map[index] & gpio_map)) map2[index] |= gpio_map; break; case LED_ONESHOT_OFF: if ((gpio_offstate_map[index] & gpio_map)) map1[index] |= gpio_map; else map2[index] |= gpio_map; break; case LED_ONESHOT_ON: case LED_FLASH: case LED_BLINK_CODE0: case LED_BLINK_CODE1: case LED_BLINK_CODE2: if (!(gpio_offstate_map[index] & gpio_map)) map1[index] |= gpio_map; else map2[index] |= gpio_map; break; default: log_msg ("Error: Invalid mode\n"); return -1; } } assign_map(p_pos_map,pos_map); assign_map(p_map1,map1); assign_map(p_map2,map2); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int configure_state(STATE_ENTRY_T *state_entry, LED_CONFIG_T *led_cfg) { // int state = led_cfg->state; int i; int map1[2] ; int pos_map[2]; int map2[2]; if((state_entry->mode = led_get_mode(led_cfg)) >= NUM_LED_MODES) { log_msg ("Error: Invalid mode in func configure_state\n"); return -1; } state_entry->handler = led_mode_handler[state_entry->mode]; if(led_get_map(led_cfg, pos_map, map1,map2)) { log_msg ("Error: gpio number out of range\n"); return -1; } assign_map(state_entry->map1,map1); assign_map(state_entry->map2,map2); state_entry->led = get_led(pos_map); /* Check if the state requires timer */ if(REQUIRES_TIMER(state_entry->mode)) { state_entry->timer_running = 0; state_entry->param1 = led_cfg->param1; state_entry->param2 = led_cfg->param2; led_assign_timer(state_entry); } /* enable gpio pins */ for(i = 0 ; i < led_cfg->gpio_num ; i++) { avm_gpio_ctrl(led_cfg->gpio[i], GPIO_PIN, GPIO_OUTPUT_PIN); } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void free_all_states(void) { int module_id; for(module_id = 0; module_id < MAX_MODULE_ENTRIES; module_id++) { if(modules[module_id]) { int i; for(i = 0; i< MAX_MODULE_INSTANCES; i++) { MODULE_INSTANCE_T *module_instance = modules[module_id]->module_instance[i]; if(module_instance) { int state_id; for(state_id =0; state_id < MAX_STATE_ENTRIES; state_id++) { STATE_ENTRY_T *state= module_instance->states[state_id]; if(state) { if(state->os_timer) os_timer_delete(state->os_timer); os_free(state); module_instance->states[state_id] = NULL; } } } } os_free(modules[module_id]->name); os_free(modules[module_id]); modules[module_id] = NULL; } } } /***********************************HAL APIS************************************/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void *avalanche_led_events; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avalanche_led_event_notify(void *Context, enum _avm_event_id id) { unsigned int i, ii; DEB_EVENT("[avalanche_led_event_notify] Context=0x%x id=%u\n", Context, id); if(id != avm_event_id_led_status) return; if(avalanche_led_events == NULL) return; for(i = 0 ; i < MAX_MODULE_ENTRIES ; i++) { void *ptr; if(modules[i] == NULL) continue; DEB_EVENT("[avalanche_led_event_notify] module %u found\n", i); for(ii = 0 ; ii < MAX_MODULE_INSTANCES ; ii++) { if(modules[i]->module_instance[ii] == NULL) continue; if(modules[i]->module_instance[ii]->event.buffer == NULL) continue; DEB_EVENT("[avalanche_led_event_notify] module %u instance %u found\n", i, ii); ptr = kmalloc(modules[i]->module_instance[ii]->event.buffer_len, GFP_ATOMIC); if(ptr == NULL) continue; memcpy(ptr, modules[i]->module_instance[ii]->event.buffer, modules[i]->module_instance[ii]->event.buffer_len); avm_event_source_trigger(avalanche_led_events, avm_event_id_led_status, modules[i]->module_instance[ii]->event.buffer_len, ptr); DEB_EVENT("[avalanche_led_event_notify] event sent\n"); } } } /************************************************************************** * FUNCTION NAME : avalanche_led_hal_init ************************************************************************** * DESCRIPTION : * The function initializes led hal module * * RETURNS : * 0 on Success * Negative value on Error ***************************************************************************/ int avalanche_led_hal_init (int *gpio_off_value, int num_gpio_pins) { //int i; num_gpios = num_gpio_pins + 4; assign_map(gpio_offstate_map, gpio_off_value); spin_lock_init(&avm_led_lock); /* initialize led state function handlers */ led_mode_handler[LED_ON] = led_on; led_mode_handler[LED_OFF] = led_off; led_mode_handler[LED_ONESHOT_ON] = led_oneshot_on; led_mode_handler[LED_ONESHOT_OFF] = led_oneshot_off; led_mode_handler[LED_FLASH] = led_flash; led_mode_handler[LED_BLINK_CODE0] = led_blink_code0; led_mode_handler[LED_BLINK_CODE1] = led_blink_code1; led_mode_handler[LED_BLINK_CODE2] = led_blink_code2; memset(&led_state, 0, sizeof(led_state)); avalanche_led_events = avm_event_source_register("led-events", (1ULL << avm_event_id_led_status), avalanche_led_event_notify, NULL); DEB_EVENT("[avalanche_led_hal_init] avalanche_led_events = 0x%x\n", avalanche_led_events); return 0; } /************************************************************************** * FUNCTION NAME : avalanche_led_config_set ************************************************************************** * DESCRIPTION : * The function configures LED state object * * RETURNS : * 0 on Success * Negative value on Error ***************************************************************************/ int avalanche_led_config_set(LED_CONFIG_T * led_cfg) { MODULE_INSTANCE_T *module; unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); module = get_module (led_cfg->name, led_cfg->instance); if (!module) goto config_failed; module->event.id = led_cfg->event_id; DEB_EVENT("[avalanche_led_config_set] id = %u state = %u event_name = %s\n", led_cfg->event_id, led_cfg->state, led_cfg->event_name); if (led_cfg->state < MAX_STATE_ENTRIES) { int state = led_cfg->state; if (!(module->states[state])) { module->states[state] = led_malloc (sizeof (STATE_ENTRY_T)); } if (!(module->states[state])) goto config_failed; module->states[state]->module_id = module->module_id; module->states[state]->instance = led_cfg->instance; if(configure_state(module->states[state], led_cfg)) { os_free(module->states[state]); module->states[state] = NULL; goto config_failed; } } else { log_msg ("ERROR:State Count exceeded\n"); goto config_failed; } spin_unlock_irqrestore(&avm_led_lock, flags); return 0; config_failed: spin_unlock_irqrestore(&avm_led_lock, flags); return -1; } /************************************************************************** * FUNCTION NAME : avalanche_led_register ************************************************************************** * DESCRIPTION : * The function creates handle to the given module and returns it. * * RETURNS : * Handle to the module instance on success. * NULL on failure. ***************************************************************************/ void *avalanche_led_register (const char *mod_name, int instance) { void *p; unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); p = (void *)get_module ((char *)mod_name, instance); spin_unlock_irqrestore(&avm_led_lock, flags); return p; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avalanche_led_late_actions(void) { int i; avalanche_led_configurated = 1; for(i = 0 ; i < MAX_LATE_ACTIONS ; i++) { if(avalanche_led_late_action[i].handle) { DEB_INFO("[avalanche_led_late_actions]: set state %u for handle 0x%x\n", avalanche_led_late_action[i].state, (unsigned int)avalanche_led_late_action[i].handle); avalanche_led_action(avalanche_led_late_action[i].handle, avalanche_led_late_action[i].state | 0x8000); avalanche_led_late_action[i].handle = NULL; } } avalanche_led_configurated = 2; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avalanche_led_event_action (void *module, int state_id, unsigned int param_len, void *user_ptr) { DEB_EVENT("[avalanche_led_event_action] module = 0x%x new state %u param_len %u user_ptr 0x%x\n", module, state_id, param_len, user_ptr); if(avalanche_led_events) { struct _avm_event_led_status *event; event = kmalloc(sizeof(struct _avm_event_led_status) + param_len, GFP_ATOMIC); if(event) { struct _avm_event_len_status *E; MODULE_INSTANCE_T *M = (MODULE_INSTANCE_T *)(module); event->header.id = avm_event_id_led_status; event->led = M->event.id; event->state = state_id; event->param_len = param_len; if(param_len) copy_from_user(event->params, user_ptr, param_len); E = kmalloc(sizeof(struct _avm_event_led_status) + param_len, GFP_ATOMIC); if(E) { memcpy(E, event, sizeof(struct _avm_event_led_status) + param_len); if(M->event.buffer) kfree(M->event.buffer); M->event.buffer_len = sizeof(struct _avm_event_led_status) + param_len; M->event.buffer = E; } DEB_EVENT("[avalanche_led_event_action] send id = %u event id = %u state = %u param_len = %u\n", event->header.id, event->led, event->state, event->param_len); avm_event_source_trigger(avalanche_led_events, avm_event_id_led_status, sizeof(struct _avm_event_led_status) + param_len, event); } } else { DEB_EVENT("[avalanche_led_event_action] event quelle not registered\n"); } avalanche_led_action (module, state_id); } /************************************************************************** * FUNCTION NAME : avalanche_led_action ************************************************************************** * DESCRIPTION : * The function triggers action on LED * ***************************************************************************/ void avalanche_led_action (void *module, int state_id) { unsigned long flags; spin_lock_irqsave(&avm_led_lock, flags); if(avalanche_led_configurated == 0) { int i; if(module == NULL) { DEB_ERR("[avalanche_led_action] no handle\n"); spin_unlock_irqrestore(&avm_led_lock, flags); return; } for(i = 0 ; i < MAX_LATE_ACTIONS ; i++) { if(avalanche_led_late_action[i].handle == module) { avalanche_led_late_action[i].state = state_id; DEB_INFO("[avalanche_led_action]: save state %u for known handle 0x%p\n", avalanche_led_late_action[i].state, avalanche_led_late_action[i].handle); break; } if(avalanche_led_late_action[i].handle == NULL) { avalanche_led_late_action[i].handle = module; avalanche_led_late_action[i].state = state_id; DEB_INFO("[avalanche_led_action]: save state %u for new handle 0x%p\n", avalanche_led_late_action[i].state, avalanche_led_late_action[i].handle); break; } } spin_unlock_irqrestore(&avm_led_lock, flags); return; } if(avalanche_led_configurated == 1) { if(state_id & 0x8000) { state_id &= ~0x8000; } else { spin_unlock_irqrestore(&avm_led_lock, flags); return; } } if (module && (state_id < MAX_STATE_ENTRIES)) { STATE_ENTRY_T *state = ((MODULE_INSTANCE_T *) (module))->states[state_id]; if (state) { state->handler (state); } else { #if 0 int id = ((MODULE_INSTANCE_T *) (module))->module_id; char *name = modules[id]->name; name = name ? name : "unknown"; DEB_WARN("[avalanche_led_action]: '%s' state_id %u not valid\n", name, state_id); #endif } } else { DEB_ERR("[avalanche_led_action]: ERROR: module = 0x%p (null) or state_id(%u) >= MAX(%u)\n", module, state_id, MAX_STATE_ENTRIES); } spin_unlock_irqrestore(&avm_led_lock, flags); return; } /************************************************************************** * FUNCTION NAME : avalanche_led_unregister ************************************************************************** * DESCRIPTION : * The function unregisters the module * * RETURNS : * 0 on Success * Negative value on Error ***************************************************************************/ int avalanche_led_unregister (void *mod_inst) { return 0; } /************************************************************************** * FUNCTION NAME : led_free_all ************************************************************************** * DESCRIPTION : * The function frees the memory allocated for holding state * configuration data * ***************************************************************************/ void avalanche_led_free_all(void) { free_all_states(); } /************************************************************************** * FUNCTION NAME : avalanche_led_hal_exit ************************************************************************** * DESCRIPTION : * The function releases all the allocated memory * ***************************************************************************/ void avalanche_led_hal_exit(void) { free_all_states(); } /***************************************************************************** * FUNCTION NAME : avalanche_led_config_get ***************************************************************************** * DESCRIPTION : * The function returns configuration information corresponding to module * state. * * RETURNS : * 0 on Success * Negative value on Error ***************************************************************************/ int avalanche_led_config_get(LED_CONFIG_T *led_cfg,int module_id,int instance, int state_id) { if(module_id == -1) { /* The module info is passed through field of led_cfg */ MODULE_INSTANCE_T *mod = get_module (led_cfg->name, instance); if(mod) module_id = mod->module_id; } if(module_id >= MAX_MODULE_ENTRIES || module_id < 0) return -1; if(state_id >= MAX_STATE_ENTRIES || module_id < 0) return -1; if(instance >= MAX_MODULE_INSTANCES || module_id < 0) return -1; if(modules[module_id]) { MODULE_INSTANCE_T *module = modules[module_id]->module_instance[instance]; if(module) { STATE_ENTRY_T *state = module->states[state_id]; if(state) { int i; LED_OBJ_T *led; strcpy(led_cfg->name, modules[module_id]->name); led_cfg->state = state_id; led_cfg->instance = instance; led_cfg->param1 = state->param1; led_cfg->param2 = state->param2; led_cfg->mode[0] = state->mode; led = state->led; /* needs to be modified for multi-pin leds */ for(i = 0;i < num_gpios && !(led->pos_map[i/32] & (1 << i)); i++); led_cfg->gpio[0] = i; led_cfg->gpio_num = 1; return 0; } } } return -1; } /*******************Export Symbols********************************************/ EXPORT_SYMBOL(avalanche_led_action); EXPORT_SYMBOL(avalanche_led_register); EXPORT_SYMBOL(avalanche_led_unregister); /*****************************************************************************/