static void t1_twl6030_init(void) { int ret; u8 val; /* * If disable GPADC_IN1, BAT_TEMP_OVRANGE interrupt is signaled. * Disable all interrupt of charger block except VBUS_DET. * We need only VBUS_DET interrupt of charger block fot usb otg. */ val = ~(TWL_CONTROLLER_RSVD | TWL_CONTROLLER_MVBUS_DET); ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, val, TWL_REG_CONTROLLER_INT_MASK); ret |= twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_LINE_C); if (ret) pr_err("%s:disable charger interrupt fail!\n", __func__); /* T1 use only preq1 of twl6030 */ val = ~(DEV_GRP_P1) << TWL6030_PHEONIX_MSK_TRANS_SHIFT; ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, val, TWL6030_PHOENIX_MSK_TRANSITION); if (ret) pr_err("%s:PHOENIX_MSK_TRANSITION write fail!\n", __func__); /* * Enable charge backup battery and set charging voltage to 2.6V. * Set VRTC low power mode in off/sleep and standard power mode in on. */ val = TWL_BBSPOR_CFG_BB_CHG_EN | TWL_BBSPOR_CFG_BBSEL_2_6V | TWL_BBSPOR_CFG_VRTC_EN_SLP_STS | TWL_BBSPOR_CFG_VRTC_EN_OFF_STS | TWL_BBSPOR_CFG_VRTC_PWEN; ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, val, TWL6030_BBSPOR_CFG); if (ret) pr_err("%s: BBSPOR_CFG write fail!\n", __func__); return; }
int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end, unsigned long features) { int status = 0; int i; int ret; u8 mask[4]; static struct irq_chip twl6030_irq_chip; if (features & TWL6032_SUBCLASS) twl6030_interrupt_mapping = twl6032_interrupt_mapping_table; mask[1] = 0xFF; mask[2] = 0xFF; mask[3] = 0xFF; ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */ ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */ ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */ twl6030_irq_base = irq_base; twl6030_irq_end = irq_end; /* install an irq handler for each of the modules; * clone dummy irq_chip since PIH can't *do* anything */ twl6030_irq_chip = dummy_irq_chip; twl6030_irq_chip.name = "twl6030"; twl6030_irq_chip.irq_set_type = NULL; twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; for (i = irq_base; i < irq_end; i++) { irq_set_chip_and_handler(i, &twl6030_irq_chip, handle_simple_irq); irq_set_chip_data(i, (void *)irq_num); activate_irq(i); } twl6030_irq_next = i; pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", irq_num, irq_base, twl6030_irq_next - 1); /* install an irq handler to demultiplex the TWL6030 interrupt */ init_completion(&irq_event); task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); if (IS_ERR(task)) { pr_err("twl6030: could not create irq %d thread!\n", irq_num); status = PTR_ERR(task); goto fail_kthread; } status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED, "TWL6030-PIH", &irq_event); if (status < 0) { pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); goto fail_irq; } twl_irq = irq_num; register_pm_notifier(&twl6030_irq_pm_notifier_block); #if 0 // LGE_CHANGE_START [2012.05.30] bk.shin for low battery problem status = twl6030_vlow_init(twl6030_irq_base + TWL_VLOW_INTR_OFFSET); if (status < 0) goto fail_vlow; #endif //LGE_CHANGE_S 2010.11.17 if (cpu_is_omap44xx()) { if (twl_class_is_6030()) { twl6030_interrupt_unmask (TWL6030_PWR_INT_MASK, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask (TWL6030_PWR_INT_MASK, REG_INT_MSK_STS_A); } } //LGE_CHANGE_E 2010.11.17 return status; #if 0 // LGE_CHANGE_START [2012.05.30] bk.shin for low battery problem fail_vlow: free_irq(irq_num, &irq_event); #endif fail_irq: kthread_stop(task); fail_kthread: for (i = irq_base; i < irq_end; i++) irq_set_chip_and_handler(i, NULL, NULL); return status; }
int twl6030_mmc_card_detect_config(void) { int ret; u8 reg_val = 0; /* Unmasking the Card detect Interrupt line for MMC1 from Phoenix */ twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK, REG_INT_MSK_LINE_B); twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK, REG_INT_MSK_STS_B); /* * Initially Configuring MMC_CTRL for receiving interrupts & * Card status on TWL6030 for MMC1 */ ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val, TWL6030_MMCCTRL); if (ret < 0) { pr_err("twl6030: Failed to read MMCCTRL, error %d\n", ret); return ret; } /* LGE_SJIT 2011-11-28 [[email protected]] 2011-11-28 * LGE_CHANGE [[email protected]] 2011-07-19, from p940 * * Leak the current 40mA on off state */ #if defined(CONFIG_MMC_OMAP_HS_VMMC_AUTO_OFF) reg_val |= VMMC_AUTO_OFF; #else reg_val &= ~VMMC_AUTO_OFF; #endif reg_val |= SW_FC; ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_MMCCTRL); if (ret < 0) { pr_err("twl6030: Failed to write MMCCTRL, error %d\n", ret); return ret; } /* Configuring PullUp-PullDown register */ ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val, TWL6030_CFG_INPUT_PUPD3); if (ret < 0) { pr_err("twl6030: Failed to read CFG_INPUT_PUPD3, error %d\n", ret); return ret; } reg_val &= ~(MMC_PU | MMC_PD); ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_CFG_INPUT_PUPD3); if (ret < 0) { pr_err("twl6030: Failed to write CFG_INPUT_PUPD3, error %d\n", ret); return ret; } ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, (MMC_MINS_DEB_MASK | MMC_MEXT_DEB_MASK), TWL6030_MMCDEBOUNCING); if (ret < 0){ pr_err("twl6030: Failed to write MMC_MEXT_DEB_MASK %d\n", ret); return ret; } return 0; }
static int __devinit charger_probe(struct platform_device *pdev) { int ret = 0; int irq = 0; u8 state = 0; struct charger_device_info *di; printk( KERN_INFO "[TA] Charger probe...\n"); sec_bci = get_sec_bci(); di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) return -ENOMEM; platform_set_drvdata(pdev, di); di->dev = &pdev->dev; device_config = pdev->dev.platform_data; #if 0 printk( KERN_INFO "[TA] %d, %d, %d\n ", device_config->VF_CHECK_USING_ADC, device_config->VF_ADC_PORT, device_config->SUPPORT_CHG_ING_IRQ); #endif this_dev = &pdev->dev; di->stat1 = 0x80; /*Init Work */ INIT_DELAYED_WORK(&di->twl6030charger_ctrl_work, twl6030charger_ctrl_work_handler); INIT_DELAYED_WORK(&di->twl6030charger_fault_work, twl6030charger_fault_work_handler); INIT_DELAYED_WORK(&di->bat_removal_detection_work, bat_removal_detection_work_handler); // Refer board_init_battery for checking resources CTRL_INT_IRQ = platform_get_irq(pdev,0); ret = request_threaded_irq(CTRL_INT_IRQ, NULL, twl6030charger_ctrl_isr, 0, pdev->name, di); if (ret) { dev_err(di->dev, "[TA] 1. could not request irq %d, status %d\n", CTRL_INT_IRQ, ret); goto ctrl_int_irq_fail; } CHARGERFAULT_INTR_IRQ = platform_get_irq(pdev,1); ret = request_threaded_irq(CHARGERFAULT_INTR_IRQ, NULL, twl6030charger_fault_isr, 0, pdev->name, di); if (ret) { dev_err(di->dev, "[TA] 2. could not request irq %d, status %d\n", CHARGERFAULT_INTR_IRQ, ret); goto chargerfault_irq_fail; } BAT_REMOVAL_IRQ = platform_get_irq(pdev, 2); ret = request_irq(BAT_REMOVAL_IRQ, bat_removal_detection_isr, IRQF_DISABLED, pdev->name, di); if (ret) { dev_err(di->dev, "[TA] 3. could not request irq %d, status %d\n", BAT_REMOVAL_IRQ, ret); goto bat_removal_irq_fail; } set_irq_type(BAT_REMOVAL_IRQ, IRQ_TYPE_EDGE_BOTH); /* initialize for USB charging */ /* MAX Charger Voltage/Current limit was set in the Bootloader */ /* Please find the related code in the sbl_board_charger.c */ /* twl6030_config_limit1_reg(di, MAX_CHARGER_VOLTAGE); */ /* twl6030_config_limit2_reg(di, MAX_CHARGER_CURRENT); */ twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MBAT_TEMP, CONTROLLER_INT_MASK); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MASK_MCHARGERUSB_THMREG, CHARGERUSB_INT_MASK); twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &state, CHARGERUSB_CTRL1); state |= TERM; twl_i2c_write_u8(TWL6030_MODULE_CHARGER, state, CHARGERUSB_CTRL1); twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_STS_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_STS_C); queue_delayed_work(sec_bci->sec_battery_workq, &di->twl6030charger_ctrl_work,HZ); return 0; bat_removal_irq_fail: irq = platform_get_irq(pdev, 1); free_irq(irq, di); chargerfault_irq_fail: irq = platform_get_irq(pdev, 0); free_irq(irq, di); ctrl_int_irq_fail: kfree(di); return ret; }
/* * MMC Slot Initialization. */ static int twl_mmc_late_init(struct device *dev) { struct omap_mmc_platform_data *mmc = dev->platform_data; int ret = 0; int i; /* MMC/SD/SDIO doesn't require a card detect switch */ if (!cpu_is_omap44xx()) { if (gpio_is_valid(mmc->slots[0].switch_pin)) { ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); if (ret) goto done; ret = gpio_direction_input(mmc->slots[0].switch_pin); if (ret) goto err; } } /* require at least main regulator */ for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { if (hsmmc[i].name == mmc->slots[0].name) { struct regulator *reg; hsmmc[i].mmc = mmc; reg = regulator_get(dev, "vmmc"); if (IS_ERR(reg)) { dev_dbg(dev, "vmmc regulator missing\n"); /* HACK: until fixed.c regulator is usable, * we don't require a main regulator * for MMC2 or MMC3 */ if (i != 0) break; ret = PTR_ERR(reg); hsmmc[i].vcc = NULL; goto err; } hsmmc[i].vcc = reg; mmc->slots[0].ocr_mask = mmc_regulator_get_ocrmask(reg); /* allow an aux regulator */ reg = regulator_get(dev, "vmmc_aux"); hsmmc[i].vcc_aux = IS_ERR(reg) ? NULL : reg; /* UGLY HACK: workaround regulator framework bugs. * When the bootloader leaves a supply active, it's * initialized with zero usecount ... and we can't * disable it without first enabling it. Until the * framework is fixed, we need a workaround like this * (which is safe for MMC, but not in general). */ if (regulator_is_enabled(hsmmc[i].vcc) > 0) { regulator_enable(hsmmc[i].vcc); regulator_disable(hsmmc[i].vcc); } if (hsmmc[i].vcc_aux) { if (regulator_is_enabled(reg) > 0) { regulator_enable(reg); regulator_disable(reg); } } if (cpu_is_omap44xx()) { if (twl_class_is_6030()) { twl6030_interrupt_unmask (TWL6030_MMCDETECT_INT_MASK, REG_INT_MSK_LINE_B); twl6030_interrupt_unmask (TWL6030_MMCDETECT_INT_MASK, REG_INT_MSK_STS_B); } /* Configure Phoenix for MMC1 Card detect */ if (i == 0) { twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x04, PHOENIX_MMC_CTRL); twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x11, PHOENIX_CFG_INPUT_PUPD3); } } break; } } return 0; err: gpio_free(mmc->slots[0].switch_pin); done: mmc->slots[0].card_detect_irq = 0; mmc->slots[0].card_detect = NULL; dev_err(dev, "err %d configuring card detect\n", ret); return ret; }
static int __devinit twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = 0; int irq = platform_get_irq(pdev, 0); u8 rd_reg; if (irq <= 0) return -EINVAL; rtc = rtc_device_register(pdev->name, &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); goto out0; } platform_set_drvdata(pdev, rtc); /* Starting backup batery charge - configuration 3v, 25uA */ ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, 0x12 /*BB_CFG*/); ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) dev_warn(&pdev->dev, "Power up reset detected.\n"); if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); /* Clear RTC Power up reset and pending alarm interrupts */ ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; ret = request_irq(irq, twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out1; } if (twl_class_is_6030()) { twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_STS_A); } /* Check RTC module status, Enable if it is off */ ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; } /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out2; #ifdef WORKQUEUE_RTC omap_rtc_wq = create_workqueue(MY_WORK_QUEUE_NAME); #endif return ret; out2: free_irq(irq, rtc); out1: rtc_device_unregister(rtc); out0: return ret; }
static int twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = -EINVAL; int irq = platform_get_irq(pdev, 0); u8 rd_reg; if (irq <= 0) goto out1; ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) dev_warn(&pdev->dev, "Power up reset detected.\n"); if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); /* Clear RTC Power up reset and pending alarm interrupts */ ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (twl_class_is_6030()) { twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_STS_A); } dev_info(&pdev->dev, "Enabling TWL-RTC\n"); ret = twl_rtc_write_u8(BIT_RTC_CTRL_REG_STOP_RTC_M, REG_RTC_CTRL_REG); if (ret < 0) goto out1; /* ensure interrupts are disabled, bootloaders can be strange */ ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); if (ret < 0) dev_warn(&pdev->dev, "unable to disable interrupt\n"); /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out1; rtc = rtc_device_register(pdev->name, &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); goto out1; } ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, dev_name(&rtc->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out2; } platform_set_drvdata(pdev, rtc); device_init_wakeup(&pdev->dev, 1); return 0; out2: rtc_device_unregister(rtc); out1: return ret; }
static int __devinit twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = 0; int irq = platform_get_irq(pdev, 0); u8 rd_reg; //COMMON_L1 [email protected] RTC_2011_2_1_SET //AO¨öA AU¥ìaAO UI ¢¯¢®¨ù¡© A¢´¨öA ¨ùoA¢´¥ìC¢¬e ¡íeA| ¢¯a¢¬A unsigned char rtc_init_year; unsigned char rtc_init_month; unsigned char rtc_init_day; unsigned char roll_back_date=0; if (irq <= 0) return -EINVAL; rtc = rtc_device_register(pdev->name, &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); goto out0; } platform_set_drvdata(pdev, rtc); ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) dev_warn(&pdev->dev, "Power up reset detected.\n"); if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); /* Clear RTC Power up reset and pending alarm interrupts */ ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; //Jags_13_04_11 RTC Randome Wakeup Fail Fix ++ ret = request_threaded_irq(irq, NULL,twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); //Jags_13_04_11 RTC Randome Wakeup Fail Fix -- /* ret = request_irq(irq, twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); */ if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out1; } if (twl_class_is_6030()) { twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_STS_A); } /* Check RTC module status, Enable if it is off */ ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; } //COMMON_L1 [email protected] RTC_2011_2_1_SET //AO¨öA AU¥ìaAO UI ¢¯¢®¨ù¡© A¢´¨öA ¨ùoA¢´¥ìC¢¬e ¡íeA| ¢¯a¢¬A ret = twl_rtc_read_u8(&rtc_init_year, REG_YEARS_REG); ret = twl_rtc_read_u8(&rtc_init_month, REG_MONTHS_REG); ret = twl_rtc_read_u8(&rtc_init_day, REG_DAYS_REG); if(rtc_init_year<0x11) { roll_back_date=1; } else if((rtc_init_year==0x11)&&(rtc_init_month==0x01)) { roll_back_date=1; } /* 2011-02-18 : Block for QM2 temporary, It should be considered in ATT SW if(roll_back_date) { twl_rtc_write_u8(0x11,REG_YEARS_REG); twl_rtc_write_u8(0x02,REG_MONTHS_REG); twl_rtc_write_u8(0x01,REG_DAYS_REG); } */ /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out2; return ret; out2: free_irq(irq, rtc); out1: rtc_device_unregister(rtc); out0: return ret; }
static int __devinit twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = 0; int irq = platform_get_irq(pdev, 0); u8 rd_reg; unsigned char rtc_init_year; unsigned char rtc_init_month; unsigned char rtc_init_day; unsigned char roll_back_date=0; if (irq <= 0) return -EINVAL; rtc = rtc_device_register(pdev->name, &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); goto out0; } platform_set_drvdata(pdev, rtc); ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) dev_warn(&pdev->dev, "Power up reset detected.\n"); if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); /* Clear RTC Power up reset and pending alarm interrupts */ ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; ret = request_threaded_irq(irq, NULL,twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out1; } if (twl_class_is_6030()) { twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_STS_A); } /* Check RTC module status, Enable if it is off */ ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; } ret = twl_rtc_read_u8(&rtc_init_year, REG_YEARS_REG); ret = twl_rtc_read_u8(&rtc_init_month, REG_MONTHS_REG); ret = twl_rtc_read_u8(&rtc_init_day, REG_DAYS_REG); if(rtc_init_year<0x11) { roll_back_date=1; } else if((rtc_init_year==0x11)&&(rtc_init_month==0x01)) { roll_back_date=1; } /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out2; return ret; out2: free_irq(irq, rtc); out1: rtc_device_unregister(rtc); out0: return ret; }
static int __devinit twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = -EINVAL; int irq = platform_get_irq(pdev, 0); u8 rd_reg; if (irq <= 0) goto out1; ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) dev_warn(&pdev->dev, "Power up reset detected.\n"); if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); /* Clear RTC Power up reset and pending alarm interrupts */ ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; if (twl_class_is_6030()) { twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, REG_INT_MSK_STS_A); } /* Check RTC module status, Enable if it is off */ ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out1; if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out1; } /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out1; rtc = rtc_device_register(pdev->name, &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); goto out1; } ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out2; } if (enable_irq_wake(irq) < 0) dev_warn(&pdev->dev, "Cannot enable wakeup for IRQ %d\n", irq); platform_set_drvdata(pdev, rtc); return 0; out2: rtc_device_unregister(rtc); out1: return ret; }
static int __init twl6030_bci_battery_probe(struct platform_device *pdev) { struct twl6030_bci_platform_data *pdata = pdev->dev.platform_data; struct twl6030_bci_device_info *di; int irq; int ret; u8 rd_reg = 0, controller_stat = 0; di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) return -ENOMEM; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); ret = -EINVAL; goto err_pdata; } di->dev = &pdev->dev; di->bat.name = "twl6030_bci_battery"; di->bat.supplied_to = twl6030_bci_supplied_to; di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to); di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = twl6030_bci_battery_props; di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props); di->bat.get_property = twl6030_bci_battery_get_property; di->bat.external_power_changed = twl6030_bci_battery_external_power_changed; di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN; di->bk_bat.name = "twl6030_bci_bk_battery"; di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bk_bat.properties = twl6030_bk_bci_battery_props; di->bk_bat.num_properties = ARRAY_SIZE(twl6030_bk_bci_battery_props); di->bk_bat.get_property = twl6030_bk_bci_battery_get_property; di->bk_bat.external_power_changed = NULL; /* * Android expects a battery type POWER_SUPPLY_TYPE_USB * as a usb charger battery. This battery * and its "online" property are used to determine if the * usb cable is plugged in or not. */ di->usb_bat.name = "twl6030_bci_usb_battery"; di->usb_bat.supplied_to = twl6030_bci_supplied_to; di->usb_bat.type = POWER_SUPPLY_TYPE_USB; di->usb_bat.properties = twl6030_usb_battery_props; di->usb_bat.num_properties = ARRAY_SIZE(twl6030_usb_battery_props); di->usb_bat.get_property = twl6030_usb_battery_get_property; di->usb_bat.external_power_changed = NULL; di->vac_priority = 1; platform_set_drvdata(pdev, di); /* settings for temperature sensing */ ret = twl6030battery_temp_setup(); if (ret) goto temp_setup_fail; /* request charger fault interruption */ irq = platform_get_irq(pdev, 1); ret = request_irq(irq, twl6030charger_fault_interrupt, 0, "twl_bci_fault", di); if (ret) { dev_dbg(&pdev->dev, "could not request irq %d, status %d\n", irq, ret); goto batt_irq_fail; } /* request charger ctrl interruption */ irq = platform_get_irq(pdev, 0); ret = request_irq(irq, twl6030charger_ctrl_interrupt, 0, "twl_bci_ctrl", di); if (ret) { dev_dbg(&pdev->dev, "could not request irq %d, status %d\n", irq, ret); goto chg_irq_fail; } twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_STS_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_STS_C); ret = power_supply_register(&pdev->dev, &di->bat); if (ret) { dev_dbg(&pdev->dev, "failed to register main battery\n"); goto batt_failed; } INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bci_monitor_work, twl6030_bci_battery_work); schedule_delayed_work(&di->twl6030_bci_monitor_work, 0); ret = power_supply_register(&pdev->dev, &di->bk_bat); if (ret) { dev_dbg(&pdev->dev, "failed to register backup battery\n"); goto bk_batt_failed; } ret = power_supply_register(&pdev->dev, &di->usb_bat); if (ret) { dev_dbg(&pdev->dev, "failed to register usb source\n"); goto usb_batt_failed; } INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bk_bci_monitor_work, twl6030_bk_bci_battery_work); schedule_delayed_work(&di->twl6030_bk_bci_monitor_work, 500); twl_i2c_read_u8(TWL6030_MODULE_ID0, &rd_reg, REG_MISC1); rd_reg = rd_reg | VAC_MEAS | VBAT_MEAS | BB_MEAS; twl_i2c_write_u8(TWL6030_MODULE_ID0, rd_reg, REG_MISC1); twl_i2c_read_u8(TWL6030_MODULE_ID1, &rd_reg, REG_TOGGLE1); rd_reg = rd_reg | ENABLE_FUELGUAGE; twl_i2c_write_u8(TWL6030_MODULE_ID1, rd_reg, REG_TOGGLE1); twl_i2c_read_u8(TWL_MODULE_MADC, &rd_reg, TWL6030_GPADC_CTRL); rd_reg = rd_reg | ENABLE_ISOURCE; twl_i2c_write_u8(TWL_MODULE_MADC, rd_reg, TWL6030_GPADC_CTRL); twl_i2c_read_u8(TWL_MODULE_USB, &rd_reg, REG_USB_VBUS_CTRL_SET); rd_reg = rd_reg | VBUS_MEAS; twl_i2c_write_u8(TWL_MODULE_USB, rd_reg, REG_USB_VBUS_CTRL_SET); twl_i2c_read_u8(TWL_MODULE_USB, &rd_reg, REG_USB_ID_CTRL_SET); rd_reg = rd_reg | ID_MEAS; twl_i2c_write_u8(TWL_MODULE_USB, rd_reg, REG_USB_ID_CTRL_SET); /* initialize for USB charging */ twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MBAT_TEMP, CONTROLLER_INT_MASK); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MASK_MCHARGERUSB_THMREG, CHARGERUSB_INT_MASK); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_VOREG_4P2, CHARGERUSB_VOREG); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_VICHRG_1500, CHARGERUSB_VICHRG); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CTRL2_VITERM_100, CHARGERUSB_CTRL2); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CIN_LIMIT_NONE, CHARGERUSB_CINLIMIT); twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CTRLLIMIT2_1500, CHARGERUSB_CTRLLIMIT2); twl_i2c_write_u8(TWL6030_MODULE_BQ, 0xa0, REG_SAFETY_LIMIT); twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &controller_stat, CONTROLLER_STAT1); if (controller_stat & VBUS_DET) twl6030_start_usb_charger(); if (controller_stat & VAC_DET) twl6030_start_ac_charger(); return 0; usb_batt_failed: power_supply_unregister(&di->bk_bat); bk_batt_failed: power_supply_unregister(&di->bat); batt_failed: free_irq(irq, di); chg_irq_fail: irq = platform_get_irq(pdev, 1); free_irq(irq, NULL); err_pdata: batt_irq_fail: temp_setup_fail: kfree(di); return ret; }
static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev) { struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; struct twl6030_bci_device_info *di; int irq = -1; int ret; int i; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); return -EINVAL; } di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) return -ENOMEM; di->platform_data = kmemdup(pdata, sizeof(*pdata), GFP_KERNEL); if (!di->platform_data) { kfree(di); return -ENOMEM; } di->state = STATE_BATTERY; di->monitoring_interval = 15; di->capacity_max_uAh = 570000; di->full_jiffies = msecs_to_jiffies(120 * 1000) + jiffies; di->vbat_jiffies = jiffies; di->dev = &pdev->dev; di->bat.name = "twl6030_battery"; di->bat.supplied_to = twl6030_bci_supplied_to; di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to); di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = twl6030_bci_battery_props; di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props); di->bat.get_property = twl6030_bci_battery_get_property; di->bat_health = POWER_SUPPLY_HEALTH_GOOD; di->usb.name = "twl6030_usb"; di->usb.type = POWER_SUPPLY_TYPE_USB; di->usb.properties = twl6030_usb_props; di->usb.num_properties = ARRAY_SIZE(twl6030_usb_props); di->usb.get_property = twl6030_usb_get_property; platform_set_drvdata(pdev, di); wake_lock_init(&usb_wake_lock, WAKE_LOCK_SUSPEND, "usb_wake_lock"); wake_lock_init(&battery_wake_lock, WAKE_LOCK_SUSPEND, "battery_wake_lock"); di->wq = create_freezable_workqueue(dev_name(&pdev->dev)); /* settings for temperature sensing */ ret = twl6030battery_temp_setup(true); if (ret) goto temp_setup_fail; ret = power_supply_register(&pdev->dev, &di->bat); if (ret) { dev_err(&pdev->dev, "failed to register main battery\n"); goto batt_failed; } ret = power_supply_register(&pdev->dev, &di->usb); if (ret) { dev_err(&pdev->dev, "failed to register usb power supply\n"); goto usb_failed; } di->charge_n1 = 0; di->timer_n1 = 0; INIT_WORK(&di->charge_control_work, twl6030_charge_control_work); INIT_WORK(&di->charge_fault_work, twl6030_charge_fault_work); INIT_WORK(&di->calibration_work, twl6030_calibration_work); INIT_DELAYED_WORK_DEFERRABLE(&di->monitor_work, twl6030_monitor_work); ret = twl6030battery_voltage_setup(di); if (ret) dev_err(&pdev->dev, "voltage measurement setup failed\n"); ret = twl6030battery_current_setup(true); if (ret) dev_err(&pdev->dev, "current measurement setup failed\n"); /* initialize for USB charging */ twl6030_config_limit1_reg(di, pdata->max_charger_voltagemV); twl6030_config_limit2_reg(di, pdata->max_charger_currentmA); ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MBAT_TEMP, CONTROLLER_INT_MASK); if (ret) goto init_failed; ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MASK_MCHARGERUSB_THMREG | MASK_MCURRENT_TERM, CHARGERUSB_INT_MASK); if (ret) goto init_failed; di->charger_outcurrentmA = di->platform_data->max_charger_currentmA; twl6030_set_watchdog(di, 32); di->nb.notifier_call = twl6030_usb_notifier_call; di->otg = otg_get_transceiver(); if (di->otg) { ret = otg_register_notifier(di->otg, &di->nb); if (ret) dev_err(&pdev->dev, "otg register notifier failed %d\n", ret); } else dev_err(&pdev->dev, "otg_get_transceiver failed %d\n", ret); di->charger_incurrentmA = twl6030_get_usb_max_power(di->otg); di->gpadc_vbat_chnl = TWL6030_GPADC_VBAT_CHNL; di->voltage_mV = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl); dev_info(&pdev->dev, "Battery Voltage at Bootup is %d mV\n", di->voltage_mV); /* initialize the voltage history table */ /* TODO: consider the best initial values for the table */ for (i=0; i < VOLTAGE_HISTORY_LENGTH; i++) di->voltage_history[i] = di->voltage_mV; /* start with a rough estimate */ di->capacity = twl6030_estimate_capacity(di); if (di->capacity < 5) di->capacity = 5; if (di->capacity > 50) di->capacity = 50; ret = twl6030backupbatt_setup(); if (ret) dev_err(&pdev->dev, "Backup Bat charging setup failed\n"); /* request charger fault interruption */ irq = platform_get_irq(pdev, 1); ret = request_threaded_irq(irq, NULL, twl6030charger_fault_interrupt, 0, "twl_bci_fault", di); if (ret) { dev_err(&pdev->dev, "could not request irq %d, status %d\n", irq, ret); goto init_failed; } /* request charger ctrl interruption */ irq = platform_get_irq(pdev, 0); ret = request_threaded_irq(irq, NULL, twl6030charger_ctrl_interrupt, 0, "twl_bci_ctrl", di); if (ret) { dev_err(&pdev->dev, "could not request irq %d, status %d\n", irq, ret); goto chg_irq_fail; } twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_STS_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_STS_C); ret = sysfs_create_group(&pdev->dev.kobj, &twl6030_bci_attr_group); if (ret) dev_err(&pdev->dev, "could not create sysfs files\n"); queue_work(di->wq, &di->calibration_work); queue_delayed_work(di->wq, &di->monitor_work, 0); return 0; /* TODO: fix fail exit mess */ chg_irq_fail: irq = platform_get_irq(pdev, 1); free_irq(irq, di); init_failed: power_supply_unregister(&di->usb); usb_failed: power_supply_unregister(&di->bat); batt_failed: if (irq != -1) free_irq(irq, di); temp_setup_fail: wake_lock_destroy(&usb_wake_lock); platform_set_drvdata(pdev, NULL); kfree(di); return ret; }
static int __devinit charger_probe(struct platform_device *pdev) { struct twl4030_charger_platform_data *pdata = pdev->dev.platform_data; struct charger_info *di; struct device *dev = &pdev->dev; int irq = -1; int ret; dev_warn(dev, "enter\n"); if (!pdata) { dev_dbg(dev, "platform_data not available\n"); return -EINVAL; } if (!pdata->supplied_to || pdata->num_supplicants < 1) { dev_err(dev, "a supplicant must be sepcified; " "supplied_to=%p num=%zu\n", pdata->supplied_to, pdata->num_supplicants); return -EINVAL; } di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) return -ENOMEM; platform_set_drvdata(pdev, di); di->dev = &pdev->dev; di->recharge_capacity = 94; di->monitor_interval_jiffies = 15 * HZ; di->usb.name = "twl6030_usb"; di->usb.type = POWER_SUPPLY_TYPE_USB; di->usb.properties = charger_usb_props; di->usb.num_properties = ARRAY_SIZE(charger_usb_props); di->usb.get_property = charger_usb_get_property; di->usb.supplied_to = pdata->supplied_to; di->usb.num_supplicants = pdata->num_supplicants; if (pdata->num_supplicants > 1) { dev_warn(dev, "more than one supplicant specified (%zu), only the " "first will be used\n", pdata->num_supplicants); } wake_lock_init(&di->wake_lock, WAKE_LOCK_SUSPEND, "charger_wake_lock"); mutex_init(&di->mutex); di->wq = create_freezable_workqueue(dev_name(di->dev)); INIT_WORK(&di->work, charger_work); setup_timer(&di->timer, charger_timer, (unsigned long) di); /* see if the bootloader already set and locked the limits */ if (charger_is_volimit_locked() == 1) { /* read the vo and vi reg limits set in the bootloader */ di->charger_voltage_mV = charger_get_volimit_config(); di->charger_outcurrent_mA = charger_get_vilimit_config(); dev_warn(&pdev->dev, "Using limits set by bootloader: %d mV %d mA\n", di->charger_voltage_mV, di->charger_outcurrent_mA); } else { /* use the conservative platform data defaults for safety */ di->charger_voltage_mV = pdata->max_bat_voltage_mV; di->charger_outcurrent_mA = pdata->max_charger_current_mA; charger_config_limit1_reg(di, pdata->max_charger_voltage_mV); charger_config_limit2_reg(di, pdata->max_charger_current_mA); dev_warn(&pdev->dev, "Using default limits: %d mV %d mA\n", di->charger_voltage_mV, di->charger_outcurrent_mA); } di->current_limit_mA = 500; ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MBAT_TEMP, CONTROLLER_INT_MASK); if (ret) goto init_failed; ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MASK_MCHARGERUSB_THMREG | MASK_MCURRENT_TERM, CHARGERUSB_INT_MASK); if (ret) goto init_failed; /* setup the initial watchdog state */ di->watchdog_duration = 32; charger_pet_watchdog(di); ret = power_supply_register(dev, &di->usb); if (ret) { dev_err(dev, "failed to register usb power supply\n"); goto usb_failed; } /* get the current supply type, which may have been determined before * the notifier below has been registered */ ret = twl6030_usb_get_supply_type(); if (ret > 0) { dev_info(dev, "initial power supply type is %d\n", ret); di->charger_supply_type = ret; } di->notifier.notifier_call = charger_usb_notifier_call; ret = twl6030_usb_register_notifier(&di->notifier); if (ret) dev_err(dev, "twl6030_usb_register_notifier failed %d\n", ret); /* request charger fault interrupt */ irq = platform_get_irq(pdev, 1); ret = request_threaded_irq(irq, NULL, charger_fault_interrupt, 0, "twl_charger_fault", di); if (ret) { dev_err(dev, "could not request irq %d, status %d\n", irq, ret); goto init_failed; } /* request charger ctrl interrupt */ irq = platform_get_irq(pdev, 0); ret = request_threaded_irq(irq, NULL, charger_ctrl_interrupt, 0, "twl_charger_ctrl", di); if (ret) { dev_err(dev, "could not request irq %d, status %d\n", irq, ret); goto chg_irq_fail; } di->sdev.name = "invalid_charger"; ret = switch_dev_register(&di->sdev); if (ret) { dev_err(di->dev, "error registering switch device: %d\n", ret); goto chg_irq_fail; } ret = sysfs_create_group(&dev->kobj, &charger_charger_attr_group); if (ret) dev_err(dev, "could not create sysfs files\n"); /* setup the led state */ di->led = twl6030_init_led_state(di->dev); if (!di->led) { dev_err(dev, "failed to alloc led state\n"); goto chg_irq_fail; } /* kick ctrl isr to get initial state */ charger_ctrl_interrupt(0, di); twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_STS_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_STS_C); charger_update_state(di); dev_warn(dev, "exit\n"); return 0; /* TODO: fix fail exit mess */ chg_irq_fail: irq = platform_get_irq(pdev, 1); free_irq(irq, di); init_failed: power_supply_unregister(&di->usb); usb_failed: if (irq != -1) free_irq(irq, di); wake_lock_destroy(&di->wake_lock); platform_set_drvdata(pdev, NULL); kfree(di); dev_warn(di->dev, "exit with error: %d\n", ret); return ret; }
static irqreturn_t powerbutton_irq(int irq, void *_pwr) { struct twl6030_pwr_button *pwr = _pwr; int hw_state; int pwr_val; static int prev_hw_state = 0xFFFF; static int push_release_flag; hw_state = twl6030_readb(pwr, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); pwr_val = !(hw_state & PWR_PWRON_IRQ); printk("%s: power button status %d\n", __func__, pwr_val); //[email protected] => [START] keylock command #if defined(CONFIG_MACH_LGE_COSMO) || defined(CONFIG_MACH_LGE_CX2) if ((prev_hw_state != pwr_val) && (prev_hw_state != 0xFFFF) && (!atcmd_keylock)) { #else if ((prev_hw_state != pwr_val) && (prev_hw_state != 0xFFFF)) { #endif //[email protected] <= [END] push_release_flag = 0; input_report_key(pwr->input_dev, pwr->report_key, pwr_val); input_sync(pwr->input_dev); //[email protected] => [START] keylock command #if defined(CONFIG_MACH_LGE_COSMO) || defined(CONFIG_MACH_LGE_CX2) } else if ((!push_release_flag) && (!atcmd_keylock)) { #else } else if (!push_release_flag) { #endif //[email protected] <= [END] push_release_flag = 1; input_report_key(pwr->input_dev, pwr->report_key, !pwr_val); input_sync(pwr->input_dev); msleep(20); input_report_key(pwr->input_dev, pwr->report_key, pwr_val); input_sync(pwr->input_dev); } else push_release_flag = 0; prev_hw_state = pwr_val; return IRQ_HANDLED; } static int __devinit twl6030_pwrbutton_probe(struct platform_device *pdev) { struct twl6030_pwr_button *pwr_button; int irq = platform_get_irq(pdev, 0); int err = -ENODEV; pr_info("%s: Enter\n", __func__); pwr_button = kzalloc(sizeof(struct twl6030_pwr_button), GFP_KERNEL); if (!pwr_button) return -ENOMEM; pwr_button->input_dev = input_allocate_device(); if (!pwr_button->input_dev) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); goto input_error; } __set_bit(EV_KEY, pwr_button->input_dev->evbit); pwr_button->report_key = KEY_POWER; pwr_button->dev = &pdev->dev; pwr_button->input_dev->evbit[0] = BIT_MASK(EV_KEY); pwr_button->input_dev->keybit[BIT_WORD(pwr_button->report_key)] = BIT_MASK(pwr_button->report_key); pwr_button->input_dev->name = "twl6030_pwrbutton"; pwr_button->input_dev->phys = "twl6030_pwrbutton/input0"; pwr_button->input_dev->dev.parent = &pdev->dev; err = request_threaded_irq(irq, NULL, powerbutton_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "twl6030_pwrbutton", pwr_button); if (err < 0) { dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); goto free_input_dev; } err = input_register_device(pwr_button->input_dev); if (err) { dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); goto free_irq; } twl6030_interrupt_unmask(0x01, REG_INT_MSK_LINE_A); twl6030_interrupt_unmask(0x01, REG_INT_MSK_STS_A); platform_set_drvdata(pdev, pwr_button); return 0; free_irq: free_irq(irq, NULL); free_input_dev: input_free_device(pwr_button->input_dev); input_error: kfree(pwr_button); return err; } static int __devexit twl6030_pwrbutton_remove(struct platform_device *pdev) { struct input_dev *pwr = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); free_irq(irq, pwr); input_unregister_device(pwr); return 0; } struct platform_driver twl6030_pwrbutton_driver = { .probe = twl6030_pwrbutton_probe, .remove = __devexit_p(twl6030_pwrbutton_remove), .driver = { .name = "twl6030_pwrbutton", .owner = THIS_MODULE, }, }; static int __init twl6030_pwrbutton_init(void) { return platform_driver_register(&twl6030_pwrbutton_driver); } module_init(twl6030_pwrbutton_init); static void __exit twl6030_pwrbutton_exit(void) { platform_driver_unregister(&twl6030_pwrbutton_driver); }