/* * Interrupt service routine * * Attends to BCI interruptions events, * specifically BATSTS (battery connection and removal) * VBATOV (main battery voltage threshold) events * */ static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id) { int ret; u8 isr1a_val, isr2a_val, clear_2a, clear_1a; if ((ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val, REG_BCIISR1A))) return IRQ_NONE; if ((ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val, REG_BCIISR2A))) return IRQ_NONE; clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0; clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0; /* cleaning BCI interrupt status flags */ if ((ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, clear_1a , REG_BCIISR1A))) return IRQ_NONE; if ((ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, clear_2a , REG_BCIISR2A))) return IRQ_NONE; /* battery connetion or removal event */ if (isr1a_val & BATSTS_ISR1) { ret = twl4030battery_presence_evt(); if (ret == -ENXIO) { twl4030battery_hw_presence_en(EVT_DISABLE); return IRQ_HANDLED; } if (ret) return IRQ_NONE; } /* battery voltage threshold event*/ else if (isr2a_val & VBATLVL_ISR1) { ret = twl4030battery_level_evt(); if (ret == -ENXIO) { twl4030battery_hw_level_en(EVT_DISABLE); return IRQ_HANDLED; } if (ret) return IRQ_NONE; } /* Only for debuging purpouses this branch never be taken */ else return IRQ_NONE; return IRQ_HANDLED; }
/* * API function * * Registers the event handler structure * * Return 0 on success * <0 on failure */ int twl4030battery_event_register(struct twl4030battery_events events) { twl4030battery_event.battery_level = events.battery_level; twl4030battery_event.battery_presence = events.battery_presence; twl4030battery_event.charger_presence = events.charger_presence; twl4030battery_event.bci_status = events.bci_status; twl4030battery_event.battery_sw_level_event_cfg = ( events.battery_sw_level_event_cfg & (EVT_LVL_4_EN | EVT_LVL_3_EN | EVT_LVL_2_EN | EVT_LVL_1_EN)) ; if(events.battery_level == NULL) { twl4030battery_hw_level_en(EVT_DISABLE); } else { twl4030battery_hw_level_en(EVT_ENABLE); twl4030battery_level_evt(); } if(events.battery_presence == NULL) { twl4030battery_hw_presence_en(EVT_DISABLE); } else { twl4030battery_hw_presence_en(EVT_ENABLE); twl4030battery_presence_evt(); } if(events.charger_presence == NULL) { twl4030charger_hw_presence_en(EVT_DISABLE); } else { twl4030charger_hw_presence_en(EVT_ENABLE); twl4030charger_presence_evt(); } if(events.bci_status == NULL) { twl4030bci_sw_status_en(EVT_DISABLE); flush_scheduled_work(); } else { twl4030bci_status_tmr.expires = jiffies + CHG_STS_DLY; add_timer(&twl4030bci_status_tmr); twl4030battery_event.temp_std = -1; twl4030bci_status_evt(); } return 0; }
/* * Interrupt service routine * * Attends to BCI interruptions events, * specifically BATSTS (battery connection and removal) * VBATOV (main battery voltage threshold) events * */ static irqreturn_t twl4030battery_interrupt(int irq, void *_di) { u8 uninitialized_var(isr1a_val), uninitialized_var(isr2a_val); u8 clear_2a, clear_1a; int ret; #ifdef CONFIG_LOCKDEP /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which * we don't want and can't tolerate. Although it might be * friendlier not to borrow this thread context... */ local_irq_enable(); #endif ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val, REG_BCIISR1A); if (ret) return IRQ_NONE; ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val, REG_BCIISR2A); if (ret) return IRQ_NONE; clear_2a = (isr2a_val & VBATLVL_ISR1) ? (VBATLVL_ISR1) : 0; clear_1a = (isr1a_val & BATSTS_ISR1) ? (BATSTS_ISR1) : 0; /* cleaning BCI interrupt status flags */ ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, clear_1a , REG_BCIISR1A); if (ret) return IRQ_NONE; ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, clear_2a , REG_BCIISR2A); if (ret) return IRQ_NONE; /* battery connetion or removal event */ if (isr1a_val & BATSTS_ISR1) twl4030battery_presence_evt(); /* battery voltage threshold event*/ else if (isr2a_val & VBATLVL_ISR1) twl4030battery_level_evt(); else return IRQ_NONE; return IRQ_HANDLED; }