static enum acipc_return_code acipc_event_unbind(u32 user_event) { u32 i; IPC_ENTER(); for (i = 0; i < ACIPC_NUMBER_OF_EVENTS; i++) { if (acipc->acipc_db.event_db[i].mask & user_event) { if (acipc->acipc_db.event_db[i].IIR_bit & user_event) { acipc_int_disable(acipc->acipc_db.event_db[i]. IIR_bit); acipc->acipc_db.event_db[i].cb = acipc_default_callback; acipc->acipc_db.event_db[i].mode = ACIPC_CB_NORMAL; acipc->acipc_db.event_db[i].mask = 0; } /* clean this event from other event's mask */ acipc->acipc_db.event_db[i].mask &= ~user_event; } } IPC_LEAVE(); return ACIPC_RC_OK; }
acipc_return_code acipc_event_bind(u32 user_event, acipc_rec_event_callback cb, acipc_callback_mode cb_mode, u32 *historical_event_status) { u32 i; IPC_ENTER(); for (i=0;i<ACIPC_NUMBER_OF_EVENTS;i++) { if (acipc->acipc_db.event_db[i].IIR_bit & user_event) { if (acipc->acipc_db.event_db[i].cb != acipc_default_callback) return(ACIPC_EVENT_ALREADY_BIND); else { acipc->acipc_db.event_db[i].cb = cb; acipc->acipc_db.event_db[i].mode = cb_mode; acipc->acipc_db.event_db[i].mask = user_event & acipc->acipc_db.event_db[i].IIR_bit; acipc_int_enable(acipc->acipc_db.event_db[i].IIR_bit); } } } /* if there were historical events*/ if (acipc->acipc_db.historical_event_status & user_event) { *historical_event_status = acipc->acipc_db.historical_event_status & user_event; /* clear the historical events from the database*/ acipc->acipc_db.historical_event_status &= ~user_event; return (ACIPC_HISTORICAL_EVENT_OCCUR); } IPC_LEAVE(); return ACIPC_RC_OK; }
static enum acipc_return_code acipc_event_set(enum acipc_events user_event) { IPC_ENTER(); acipc_writel_withdummy(IPC_ISRW, user_event); IPCTRACE("acipc_event_set userEvent 0x%x\n", user_event); IPC_LEAVE(); return ACIPC_RC_OK; }
static irqreturn_t acipc_interrupt_handler(int irq, void *dev_id) { u32 i, on_events; IPC_ENTER(); ACIPC_IIR_READ(acipc->IIR_val); /* read the IIR*/ /*using ACIPCEventStatusGet might cause getting here with IIR=0*/ if (acipc->IIR_val) { for (i = 0; i < ACIPC_NUMBER_OF_EVENTS; i++) { /* NOTE: if the driver state is 'NO_DDR' the following * condition will ignore events that configure to be * called only when DDR availble. currently this will * leave the event bit on meaning the LISR will be called * upon release interrupts.thus the driver state must be restore * ( to NORMAL) before release the interrupts */ #if 0 if ((acipc->acipc_db.event_db[i].IIR_bit & acipc->IIR_val)&& (!((acipc->acipc_db.driver_mode == ACIPC_CB_ALWAYS_NO_DDR)&& (acipc->acipc_db.event_db[i].mode == ACIPC_CB_NORMAL)))){ #else if ((acipc->acipc_db.event_db[i].IIR_bit & acipc->IIR_val) && (acipc->acipc_db.event_db[i].mode == ACIPC_CB_NORMAL)) { #endif on_events = (acipc->IIR_val)&(acipc->acipc_db.event_db[i].mask); /* call the user callback with the status of other * events as define when the user called ACIPCEventBind */ acipc->acipc_db.event_db[i].cb(on_events); /* clean the event(s)*/ acipc_writel(IPC_ICR, on_events); /* if more then one event exist we clear * the rest of the bits from the global * IIR_val so user callback will be called only once. */ acipc->IIR_val &= (~on_events); } } } IPC_LEAVE(); return IRQ_HANDLED; } u32 user_callback(u32 events_status) { acipc->bind_event_arg = events_status; acipc->poll_status = 1; wake_up_interruptible(&acipc->acipc_wait_q); return 0; }
acipc_return_code acipc_event_set(acipc_events user_event) { IPC_ENTER(); acipc_writel(IPC_ISRW, user_event); IPCTRACE("acipc_event_set userEvent 0x%x\n", user_event); IPC_LEAVE(); return(ACIPC_RC_OK); }
static enum acipc_return_code acipc_data_read(acipc_data *data) { IPC_ENTER(); /* reading the data from RDR */ *data = acipc_readl(IPC_RDR); IPC_LEAVE(); return ACIPC_RC_OK; }
static u32 acipc_default_callback(u32 status) { IPC_ENTER(); /* getting here means that the client didn't yet bind his callback. * we will save the event until the bind occur */ acipc->acipc_db.historical_event_status += status; IPC_LEAVE(); return 0 ; }
static void acipc_change_driver_state(int is_DDR_ready) { IPC_ENTER(); IPCTRACE("acipc_change_driver_state isDDRReady %d\n", is_DDR_ready); if (is_DDR_ready) acipc->acipc_db.driver_mode = ACIPC_CB_NORMAL; else acipc->acipc_db.driver_mode = ACIPC_CB_ALWAYS_NO_DDR; IPC_LEAVE(); }
acipc_return_code acipc_data_send(acipc_events user_event, acipc_data data) { IPC_ENTER(); IPCTRACE("acipc_data_send userEvent 0x%x, data 0x%x\n", user_event, data); /* writing the data to WDR*/ acipc_writel(IPC_WDR, data); /* fire the event to the other subsystem * to indicate the data is ready for read */ acipc_writel(IPC_ISRW, user_event); IPC_LEAVE(); return ACIPC_RC_OK; }
static irqreturn_t acipc_interrupt_handler(int irq, void *dev_id) { u32 i, on_events; IPC_ENTER(); ACIPC_IIR_READ(acipc->IIR_val); /* read the IIR */ /* using ACIPCEventStatusGet might cause getting here with IIR=0 */ if (acipc->IIR_val) { for (i = 0; i < ACIPC_NUMBER_OF_EVENTS; i++) { if ((acipc->acipc_db.event_db[i].IIR_bit & acipc->IIR_val) && (acipc->acipc_db.event_db[i].mode == ACIPC_CB_NORMAL)) { on_events = (acipc->IIR_val) & (acipc->acipc_db. event_db[i].mask); /* clean the event(s) */ acipc_writel_withdummy(IPC_ICR, on_events); /* * call the user callback with the status * of other events as define when the user * called ACIPCEventBind */ acipc->acipc_db.event_db[i].cb(on_events); /* * if more then one event exist we clear * the rest of the bits from the global * IIR_val so user callback will be called * only once. */ acipc->IIR_val &= (~on_events); } } } IPC_LEAVE(); return IRQ_HANDLED; }
acipc_return_code acipc_event_status_get(u32 user_event, u32 *status) { u32 IIR_local_val; IPC_ENTER(); /* reading the status from IIR*/ ACIPC_IIR_READ(IIR_local_val); /* clear the events hw status*/ acipc_writel(IPC_ICR, user_event); /* verify that this event will be cleared from the global IIR variable. * for cases this API is called from user callback */ acipc->IIR_val &= ~(user_event); *status = IIR_local_val & user_event; IPC_LEAVE(); return ACIPC_RC_OK; }