コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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, &reg_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, &reg_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;
}
コード例 #4
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;
}
コード例 #5
0
/*
 * 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;
}
コード例 #6
0
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;
}
コード例 #7
0
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;
}
コード例 #8
0
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;
}
コード例 #9
0
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;
}
コード例 #10
0
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;
}
コード例 #11
0
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;
}
コード例 #12
0
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;
}
コード例 #13
0
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;
}
コード例 #14
0
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);
}