Ejemplo n.º 1
0
static int __init otg_wakelock_init(void)
{
	int ret;

	otgwl_xceiv = otg_get_transceiver();

	if (!otgwl_xceiv) {
		pr_err("%s: No OTG transceiver found\n", __func__);
		return -ENODEV;
	}

	snprintf(vbus_lock.name, sizeof(vbus_lock.name), "vbus-%s",
		 dev_name(otgwl_xceiv->dev));
	wake_lock_init(&vbus_lock.wakelock, WAKE_LOCK_SUSPEND,
		       vbus_lock.name);

	otgwl_nb.notifier_call = otgwl_otg_notifications;
	ret = otg_register_notifier(otgwl_xceiv, &otgwl_nb);

	if (ret) {
		pr_err("%s: otg_register_notifier on transceiver %s"
		       " failed\n", __func__,
		       dev_name(otgwl_xceiv->dev));
		otgwl_xceiv = NULL;
		wake_lock_destroy(&vbus_lock.wakelock);
		return ret;
	}

	otgwl_handle_event(otgwl_xceiv->last_event);
	return ret;
}
Ejemplo n.º 2
0
static int omap2430_musb_init(struct musb *musb)
{
	u32 l;
	int status = 0;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);

	status = pm_runtime_get_sync(dev);
	if (status < 0) {
		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
		goto err1;
	}

	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	musb->nb.notifier_call = musb_otg_notifications;
	status = otg_register_notifier(musb->xceiv, &musb->nb);

	if (status)
		dev_dbg(musb->controller, "notification register failed\n");

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);

	return 0;

err1:
	return status;
}
Ejemplo n.º 3
0
static int __devinit isp1704_charger_probe(struct platform_device *pdev)
{
	struct isp1704_charger	*isp;
	int			ret = -ENODEV;

	isp = kzalloc(sizeof *isp, GFP_KERNEL);
	if (!isp)
		return -ENOMEM;

	isp->otg = otg_get_transceiver();
	if (!isp->otg)
		goto fail0;

	ret = isp1704_test_ulpi(isp);
	if (ret < 0)
		goto fail1;

	isp->dev = &pdev->dev;
	platform_set_drvdata(pdev, isp);

	isp->psy.name		= "isp1704";
	isp->psy.type		= POWER_SUPPLY_TYPE_USB;
	isp->psy.properties	= power_props;
	isp->psy.num_properties	= ARRAY_SIZE(power_props);
	isp->psy.get_property	= isp1704_charger_get_property;

	ret = power_supply_register(isp->dev, &isp->psy);
	if (ret)
		goto fail1;

	/*
	 * REVISIT: using work in order to allow the otg notifications to be
	 * made atomically in the future.
	 */
	INIT_WORK(&isp->work, isp1704_charger_work);

	isp->nb.notifier_call = isp1704_notifier_call;

	ret = otg_register_notifier(isp->otg, &isp->nb);
	if (ret)
		goto fail2;

	dev_info(isp->dev, "registered with product id %s\n", isp->model);

	return 0;
fail2:
	power_supply_unregister(&isp->psy);
fail1:
	otg_put_transceiver(isp->otg);
fail0:
	kfree(isp);

	dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);

	return ret;
}
Ejemplo n.º 4
0
int __init musb_platform_init(struct musb *musb)
{
	u32 l;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;
	int status;
	u32 val;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	/* Fixme this can be enabled when load the gadget driver also*/
	musb_platform_resume(musb);

	/*powerup the phy as romcode would have put the phy in some state
	* which is impacting the core retention if the gadget driver is not
	* loaded.
	*/
	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	if (is_host_enabled(musb))
		musb->board_set_vbus = omap_set_vbus;

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
	plat->is_usb_active = is_musb_active;

	wake_lock_init(&plat->musb_lock, WAKE_LOCK_SUSPEND, "musb_wake_lock");
	if (cpu_is_omap44xx()) {
		phymux_base = ioremap(0x4A100000, SZ_1K);
		ctrl_base = ioremap(0x4A002000, SZ_1K);

		/* register for transciever notification*/
		status = otg_register_notifier(musb->xceiv, &musb->nb);

		if (status) {
			DBG(1, "notification register failed\n");
			wake_lock_destroy(&plat->musb_lock);
		}
		ctrl_base = ioremap(0x4A002000, SZ_1K);
		if (!ctrl_base) {
			dev_err(dev, "ioremap failed\n");
			return -ENOMEM;
		}
	}
	
	/* configure in force idle/ standby */
	musb_writel(musb->mregs, OTG_FORCESTDBY, 1);
	val = musb_readl(musb->mregs, OTG_SYSCONFIG);
	val &= ~(SMARTIDLEWKUP | NOSTDBY | ENABLEWAKEUP);
	val |= FORCEIDLE | FORCESTDBY;
	musb_writel(musb->mregs, OTG_SYSCONFIG,	val);


	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
	
	return 0;
}
Ejemplo n.º 5
0
static int pda_power_probe(struct platform_device *pdev)
{
	int ret = 0;

	dev = &pdev->dev;

	if (pdev->id != -1) {
		dev_err(dev, "it's meaningless to register several "
			"pda_powers; use id = -1\n");
		ret = -EINVAL;
		goto wrongid;
	}

	pdata = pdev->dev.platform_data;

	if (pdata->init) {
		ret = pdata->init(dev);
		if (ret < 0)
			goto init_failed;
	}

	update_status();

	if (!pdata->wait_for_status)
		pdata->wait_for_status = 500;

	if (!pdata->wait_for_charger)
		pdata->wait_for_charger = 500;

	if (!pdata->polling_interval)
		pdata->polling_interval = 2000;

	if (!pdata->ac_max_uA)
		pdata->ac_max_uA = 500000;

	setup_timer(&charger_timer, charger_timer_func, 0);

	ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");

	if (pdata->supplied_to) {
		pda_psy_ac.supplied_to = pdata->supplied_to;
		pda_psy_ac.num_supplicants = pdata->num_supplicants;
		pda_psy_usb.supplied_to = pdata->supplied_to;
		pda_psy_usb.num_supplicants = pdata->num_supplicants;
	}

	ac_draw = regulator_get(dev, "ac_draw");
	if (IS_ERR(ac_draw)) {
		dev_dbg(dev, "couldn't get ac_draw regulator\n");
		ac_draw = NULL;
		ret = PTR_ERR(ac_draw);
	}

	transceiver = otg_get_transceiver();
	if (transceiver && !pdata->is_usb_online) {
		pdata->is_usb_online = otg_is_usb_online;
	}
	if (transceiver && !pdata->is_ac_online) {
		pdata->is_ac_online = otg_is_ac_online;
	}

	if (pdata->is_ac_online) {
		ret = power_supply_register(&pdev->dev, &pda_psy_ac);
		if (ret) {
			dev_err(dev, "failed to register %s power supply\n",
				pda_psy_ac.name);
			goto ac_supply_failed;
		}

		if (ac_irq) {
			ret = request_irq(ac_irq->start, power_changed_isr,
					  get_irq_flags(ac_irq), ac_irq->name,
					  &pda_psy_ac);
			if (ret) {
				dev_err(dev, "request ac irq failed\n");
				goto ac_irq_failed;
			}
		} else {
			polling = 1;
		}
	}

	if (pdata->is_usb_online) {
		ret = power_supply_register(&pdev->dev, &pda_psy_usb);
		if (ret) {
			dev_err(dev, "failed to register %s power supply\n",
				pda_psy_usb.name);
			goto usb_supply_failed;
		}

		if (usb_irq) {
			ret = request_irq(usb_irq->start, power_changed_isr,
					  get_irq_flags(usb_irq),
					  usb_irq->name, &pda_psy_usb);
			if (ret) {
				dev_err(dev, "request usb irq failed\n");
				goto usb_irq_failed;
			}
		} else {
			polling = 1;
		}
	}

	if (transceiver && pdata->use_otg_notifier) {
		otg_nb.notifier_call = otg_handle_notification;
		ret = otg_register_notifier(transceiver, &otg_nb);
		if (ret) {
			dev_err(dev, "failure to register otg notifier\n");
			goto otg_reg_notifier_failed;
		}
		polling = 0;
	}

	if (polling) {
		dev_dbg(dev, "will poll for status\n");
		setup_timer(&polling_timer, polling_timer_func, 0);
		mod_timer(&polling_timer,
			  jiffies + msecs_to_jiffies(pdata->polling_interval));
	}

	if (ac_irq || usb_irq)
		device_init_wakeup(&pdev->dev, 1);

	return 0;

otg_reg_notifier_failed:
	if (pdata->is_usb_online && usb_irq)
		free_irq(usb_irq->start, &pda_psy_usb);
usb_irq_failed:
	if (pdata->is_usb_online)
		power_supply_unregister(&pda_psy_usb);
usb_supply_failed:
	if (pdata->is_ac_online && ac_irq)
		free_irq(ac_irq->start, &pda_psy_ac);
	if (transceiver)
		otg_put_transceiver(transceiver);
ac_irq_failed:
	if (pdata->is_ac_online)
		power_supply_unregister(&pda_psy_ac);
ac_supply_failed:
	if (ac_draw) {
		regulator_put(ac_draw);
		ac_draw = NULL;
	}
	if (pdata->exit)
		pdata->exit(dev);
init_failed:
wrongid:
	return ret;
}
static int cpcap_otg_probe(struct platform_device *pdev)
{
	struct cpcap_otg_data *cpcap;
	struct resource *res;
	unsigned long val;
	int err;

	cpcap = kzalloc(sizeof(struct cpcap_otg_data), GFP_KERNEL);
	if (!cpcap)
		return -ENOMEM;

	cpcap->otg.dev = &pdev->dev;
	cpcap->otg.label = "cpcap-otg";
	cpcap->otg.state = OTG_STATE_UNDEFINED;
	cpcap->otg.set_host = cpcap_otg_set_host;
	cpcap->otg.set_peripheral = cpcap_otg_set_peripheral;
	cpcap->otg.set_suspend = cpcap_otg_set_suspend;
	cpcap->otg.set_power = cpcap_otg_set_power;
	cpcap->host = pdev->dev.platform_data;
	wake_lock_init(&cpcap->wake_lock, WAKE_LOCK_SUSPEND, "cpcap_otg");

	platform_set_drvdata(pdev, cpcap);

	cpcap->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(cpcap->clk)) {
		dev_err(&pdev->dev, "Can't get otg clock\n");
		err = PTR_ERR(cpcap->clk);
		goto err_clk;
	}

	err = clk_enable(cpcap->clk);
	if (err)
		goto err_clken;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "Failed to get I/O memory\n");
		err = -ENXIO;
		goto err_io;
	}
	cpcap->regs = ioremap(res->start, resource_size(res));
	if (!cpcap->regs) {
		err = -ENOMEM;
		goto err_io;
	}

	val = readl(cpcap->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET);
	val |= TEGRA_VBUS_WAKEUP_SW_ENABLE | TEGRA_ID_SW_ENABLE;
	val |= TEGRA_ID_SW_VALUE;
	val &= ~(TEGRA_VBUS_WAKEUP_SW_VALUE);
	writel(val, cpcap->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET);

	clk_disable(cpcap->clk);
	cpcap->otg.state = OTG_STATE_A_SUSPEND;

	ATOMIC_INIT_NOTIFIER_HEAD(&cpcap->otg.notifier);
	cpcap->nb.notifier_call = cpcap_otg_notify;
	otg_register_notifier(&cpcap->otg, &cpcap->nb);

	err = otg_set_transceiver(&cpcap->otg);
	if (err) {
		dev_err(&pdev->dev, "can't register transceiver (%d)\n", err);
		goto err_otg;
	}

	return 0;

err_otg:
	iounmap(cpcap->regs);
err_io:
	clk_disable(cpcap->clk);
err_clken:
	clk_put(cpcap->clk);
err_clk:
	wake_lock_destroy(&cpcap->wake_lock);
	platform_set_drvdata(pdev, NULL);
	kfree(cpcap);
	return err;
}
Ejemplo n.º 7
0
static int omap2430_musb_init(struct musb *musb)
{
	u32 l;
	int status = 0;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	musb->otg_notifier_wq = create_singlethread_workqueue("musb-otg");
	if (!musb->otg_notifier_wq) {
		pr_err("HS USB OTG: cannot allocate otg event wq\n");
		status = -ENOMEM;
		goto err1;
	}
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
	omap2430_async_resume(musb);
#endif
	status = pm_runtime_get_sync(dev);
#ifndef CONFIG_USB_SAMSUNG_OMAP_NORPM
	if (status < 0) {
		dev_err(dev, "pm_runtime_get_sync FAILED");
		goto err2;
	}
#endif

	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	musb->nb.notifier_call = musb_otg_notifications;
	status = otg_register_notifier(musb->xceiv, &musb->nb);

	if (status)
		dev_dbg(musb->controller, "notification register failed\n");

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);

	musb->otg_enum_delay = INIT_OTG_DELAY;

	pm_runtime_put_noidle(musb->controller);
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
	musb->reserve_async_suspend++;
#endif
	return 0;

err2:
	destroy_workqueue(musb->otg_notifier_wq);
err1:
	otg_put_transceiver(musb->xceiv);
	pm_runtime_disable(dev);
	return status;
}
Ejemplo n.º 8
0
static int omap2430_musb_init(struct musb *musb)
{
	u32 l, status = 0;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	omap2430_low_level_init(musb);

	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
	l &= ~ENABLEWAKEUP;	/* disable wakeup */
	l &= ~NOSTDBY;		/* remove possible nostdby */
	l |= SMARTSTDBY;	/* enable smart standby */
	l &= ~AUTOIDLE;		/* disable auto idle */
	l &= ~NOIDLE;		/* remove possible noidle */
	l |= SMARTIDLE;		/* enable smart idle */
	/*
	 * MUSB AUTOIDLE don't work in 3430.
	 * Workaround by Richard Woodruff/TI
	 */
	if (!cpu_is_omap3430())
		l |= AUTOIDLE;		/* enable auto idle */
	musb_writel(musb->mregs, OTG_SYSCONFIG, l);

	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	musb->nb.notifier_call = musb_otg_notifications;
	status = otg_register_notifier(musb->xceiv, &musb->nb);

	if (status)
		DBG(1, "notification register failed\n");

	/* check whether cable is already connected */
	if (musb->xceiv->state ==OTG_STATE_B_IDLE)
		musb_otg_notifications(&musb->nb, 1,
					musb->xceiv->gadget);

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);

	return 0;
}
Ejemplo n.º 9
0
static int omap2430_musb_init(struct musb *musb)
{
	u32 l;
	int status = 0;
	struct device *dev = musb->controller;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	musb->otg_notifier_wq = create_singlethread_workqueue("musb-otg");
	if (!musb->otg_notifier_wq) {
		pr_err("HS USB OTG: cannot allocate otg event wq\n");
		status = -ENOMEM;
		goto err1;
	}

	status = pm_runtime_get_sync(dev);
	if (status < 0) {
		dev_err(dev, "pm_runtime_get_sync FAILED");
		goto err2;
	}

	/* Set OTG_INTERFSEL to ULPI for correct charger detection.
	 * This should be later set to UTMI.
	 */
	l = musb_readl(musb->mregs, OTG_INTERFSEL);
	l |= ULPI_12PIN;
	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	musb->nb.notifier_call = musb_otg_notifications;
	status = otg_register_notifier(musb->xceiv, &musb->nb);

	if (status)
		dev_dbg(musb->controller, "notification register failed\n");

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);

	return 0;

err2:
	destroy_workqueue(musb->otg_notifier_wq);
err1:
	otg_put_transceiver(musb->xceiv);
	pm_runtime_disable(dev);
	return status;
}
Ejemplo n.º 10
0
/*Charger Module Initialization*/
static int max8903_charger_probe(struct platform_device *pdev)
{

	struct max8903_charger *mc;
	int ret;
	struct resource *r;

	/*allocate mem*/
	mc = kzalloc(sizeof(*mc), GFP_KERNEL);
	if (!mc)
		return -ENOMEM;

	platform_set_drvdata(pdev, mc);

	printk("MAX8903: Charger Initializing...\n");
	//INIT_DELAYED_WORK(&mc->max8903_charger_detect_work, max8903_charger_detect);
	/* Create power supplies for WALL/USB which are the only 2 ext supplies*/
	mc->adapter.name            = "ac";
	mc->adapter.type            = POWER_SUPPLY_TYPE_MAINS;
	mc->adapter.properties      = power_props;
	mc->adapter.num_properties  = ARRAY_SIZE(power_props);
	mc->adapter.get_property    = &adapter_get_property;

	mc->usb.name            = "usb";
	mc->usb.type            = POWER_SUPPLY_TYPE_USB;
	mc->usb.properties      = power_props;
	mc->usb.num_properties  = ARRAY_SIZE(power_props);
	mc->usb.get_property    = usb_get_property;

	mc->adapter_online = 0;
	mc->adapter_active = 0;
	mc->adapter_curr_limit = USB_CURRENT_LIMIT_HIGH; /* default limit is high limit */
	mc->usb_online = 0;
	mc->usb_active = 0;

	ret = power_supply_register(&pdev->dev, &mc->adapter);
	if (ret) {
		printk("MAX8903: Failed to register WALL CHARGER\n");
		goto exit0;
	}

	ret = power_supply_register(&pdev->dev, &mc->usb);
	if (ret) {
		printk("MAX8903: Failed to register USB CHARGER\n");
		goto exit1;
	}

	/*****************/
	/* Get resources */
	/*****************/
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_EN);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_EN);
		goto exit1;
	}
	mc->max8903_gpio_chg_en = r->start;
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_FLT);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_FLT);
		goto exit1;
	}
	mc->max8903_gpio_chg_flt = r->start;
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_IUSB);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_IUSB);
		goto exit1;
	}
	mc->max8903_gpio_chg_iusb = r->start;
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_USUS);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_USUS);
		goto exit1;
	}
	mc->max8903_gpio_chg_usus = r->start;
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_ILM);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_ILM);
		goto exit1;
	}
	mc->max8903_gpio_chg_ilm = r->start;
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_UOK);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_UOK);
		goto exit1;
	}
	mc->max8903_gpio_chg_uok = r->start;
	r = platform_get_resource_byname(pdev, IORESOURCE_IO, MAX8903_TOKEN_GPIO_CHG_DOK);
	if (!r) {
		dev_err(&pdev->dev, "failed to get resource: %s\n", MAX8903_TOKEN_GPIO_CHG_DOK);
		goto exit1;
	}
	mc->max8903_gpio_chg_dok = r->start;

	/******************************/
	/* Control pins configuration */
	/******************************/

	/*~DOK Status*/
	if (gpio_request(mc->max8903_gpio_chg_dok, MAX8903_TOKEN_GPIO_CHG_DOK) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_dok\n");
		goto exit2;
	}
	gpio_direction_input(mc->max8903_gpio_chg_dok);
	/*~UOK Status*/
	if (gpio_request(mc->max8903_gpio_chg_uok, MAX8903_TOKEN_GPIO_CHG_UOK) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_uok\n");
		goto exit3;
	}
	gpio_direction_input(mc->max8903_gpio_chg_uok);
	/*IUSB control*/
	if (gpio_request(mc->max8903_gpio_chg_iusb,  MAX8903_TOKEN_GPIO_CHG_IUSB) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_iusb\n");
		goto exit5;
	}
	gpio_direction_output(mc->max8903_gpio_chg_iusb, CHG_IUSB_SELECT_500mA);

	/*USUS control*/
	if (gpio_request(mc->max8903_gpio_chg_usus, MAX8903_TOKEN_GPIO_CHG_USUS) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_usus\n");
		goto exit6;
	}
	gpio_direction_output(mc->max8903_gpio_chg_usus, DISABLED); // leave USUS disabled until we connect

	/*~CEN control */
	if (gpio_request(mc->max8903_gpio_chg_en, MAX8903_TOKEN_GPIO_CHG_EN) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_en\n");
		goto exit7;
	}
	gpio_direction_output(mc->max8903_gpio_chg_en, DISABLED);

	if (gpio_request(mc->max8903_gpio_chg_ilm, MAX8903_TOKEN_GPIO_CHG_ILM) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_ilm\n");
		goto exit8;
	}
	gpio_direction_output(mc->max8903_gpio_chg_ilm, CHG_ILM_SELECT_USB);    /* set to USB  current limit by default */

	if (gpio_request(mc->max8903_gpio_chg_flt, MAX8903_TOKEN_GPIO_CHG_FLT) < 0) {
		printk(KERN_ERR "Can't get GPIO for max8903 chg_flt\n");
		goto exit9;
	}
	gpio_direction_input(mc->max8903_gpio_chg_flt);

	/*~FLT status*/
	mc->flt_irq= gpio_to_irq(mc->max8903_gpio_chg_flt) ;
	ret  = request_irq( mc->flt_irq,
			max8903_fault_interrupt,
			IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_DISABLED,
			"max8903-fault-irq",
			mc);

	printk("MAX8903: Request CHARGER FLT IRQ successfully!\n");
	if (ret < 0) {
		printk(KERN_ERR "MAX8903: Can't Request IRQ for max8903 flt_irq\n");
		goto exita;
	}

	/*
	   create sysfs for manufacture testing coverage on charging
	   the operator should be able to write 1 to turn on the charging and 0 to
	   turn off the charging to verify the charging circuit is functioning
	   */
	ret = sysfs_create_group(&pdev->dev.kobj, &max8903_attr_group);

	if (ret){
		printk(KERN_ERR "MAX8903: Can't Create Sysfs Entry for FTM\n");
		goto exitd;
	}

	// Register charger work and notification callback.
	INIT_DELAYED_WORK_DEFERRABLE(&mc->usb_work, max8903_usb_charger_work);
	mc->nb.notifier_call = twl6030_usb_notifier_call;
	mc->otg = otg_get_transceiver();
	if (!mc->otg) {
		dev_err(&pdev->dev, "otg_get_transceiver() failed\n");
		goto exitn;
	}
	ret = otg_register_notifier(mc->otg, &mc->nb);
	if (ret) {
		dev_err(&pdev->dev, "otg register notifier failed %d\n", ret);
		goto exitn;
	}

	max8903_usb_charger_atboot(mc);

	return 0;

exitn:
	cancel_delayed_work_sync(&mc->usb_work);
	sysfs_remove_group(&pdev->dev.kobj, &max8903_attr_group);

exitd:
	free_irq(mc->flt_irq,mc);
exita:
	gpio_free(mc->max8903_gpio_chg_flt);
exit9:
	gpio_free(mc->max8903_gpio_chg_ilm);
exit8:
	gpio_free(mc->max8903_gpio_chg_en);
exit7:
	gpio_free(mc->max8903_gpio_chg_usus);
exit6:
	gpio_free(mc->max8903_gpio_chg_iusb);
exit5:
	gpio_free(mc->max8903_gpio_chg_uok);
exit3:
	gpio_free(mc->max8903_gpio_chg_dok);
exit2:
	power_supply_unregister(&mc->usb);
exit1:
	power_supply_unregister(&mc->adapter);
exit0:
	kfree(mc);
	return ret;
}
static int __devinit bq2416x_charger_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	struct bq2416x_device_info *di;
	struct bq2416x_platform_data *pdata = client->dev.platform_data;
	int ret;
	u8 read_reg = 0;
	enum plugin_status plugin_stat;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	di->dev = &client->dev;
	di->client = client;

	i2c_set_clientdata(client, di);

	ret = bq2416x_read_byte(di, &read_reg, REG_PART_REVISION);

	if (ret < 0) {
		dev_err(&client->dev, "chip not present at address %x\n",
								client->addr);
		ret = -EINVAL;
		goto err_kfree;
	}
#if 0
	if ((read_reg & 0x18) == 0x00 && (client->addr == 0x6a))
		di->bqchip_version = BQ24156;
#endif 
	
	if ((read_reg & 0x18) == 0x00 && (client->addr == 0x6b))
		di->bqchip_version = BQ24161;

	if (di->bqchip_version == 0) {
		dev_dbg(&client->dev, "unknown bq chip\n");
		dev_dbg(&client->dev, "Chip address %x", client->addr);
		dev_dbg(&client->dev, "bq chip version reg value %x", read_reg);
		ret = -EINVAL;
		goto err_kfree;
	}


	//	di->nb.notifier_call = bq2416x_charger_event;
	
#if 0
	 bq2415x_config_safety_reg(di, pdata->max_charger_currentmA,
						pdata->max_charger_voltagemV);
	 di->cin_limit = 900;
	 di->term_currentmA = pdata->termination_currentmA;
	 bq2415x_config_control_reg(di);
	 bq2415x_config_voltage_reg(di);
	 bq2415x_config_current_reg(di);
#endif 
       /*set gpio_174 to control CD pin to disable/enable bq24161 IC*/
	 gpio_request(BQ2416X_GPIO_174, "gpio_174_cd");
	 /* set charger CD pin to low level and enable it to supply power normally*/
	 gpio_direction_output(BQ2416X_GPIO_174, 0);
     ret = bq2416x_get_max_charge_voltage(di);
	 if(!ret){
		di->max_voltagemV = pdata->max_charger_voltagemV;
	 }

	 di->voltagemV = di->max_voltagemV;

	 ret = bq2416x_get_max_charge_current(di);
	 if(!ret){
		di->max_currentmA = pdata->max_charger_currentmA;
	 }

	 di->currentmA = CURRENT_USB_CHARGE_IN ;
        di->term_currentmA = CURRENT_TERM_CHARGE_IN;
	 di->dppm_voltagemV = VOLT_DPPM_ADJUST;
	 di->cin_limit = CURRENT_USB_LIMIT_IN; 


		di->enable_hotcold_temp_charge = set_one;
	di->enable_low_chg = DISABLE_LOW_CHG;/*set normally charge mode*/
	di->enable_iterm = ENABLE_ITERM; /*enable charge current termination*/
	di->factory_flag = 0;
	 di->enable_ce = ENABLE_CE;
	 di->hz_mode = 0;
	 di->cd_active = 0;
	 
	INIT_DELAYED_WORK_DEFERRABLE(&di->bq2416x_charger_work,
				bq2416x_charger_work);

#if BQ2416X_USE_WAKE_LOCK
	wake_lock_init(&di->charger_wake_lock, WAKE_LOCK_SUSPEND, "charger_wake_lock");
#endif

	//BLOCKING_INIT_NOTIFIER_HEAD(&notifier_list);

	di->active = 0;
	di->params.enable = 1;
	di->cfg_params = 1;
	
	 bq2416x_config_control_reg(di);
	 bq2416x_config_voltage_reg(di);
	 bq2416x_config_current_reg(di);
	 bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);	
	 bq2416x_config_safety_reg(di);
	
#if 0
	ret = bq2416x_read_byte(di, &read_reg, REG_SPECIAL_CHARGER_VOLTAGE);
	if (!(read_reg & 0x08)) {
		di->active = 1;
		schedule_delayed_work(&di->bq2415x_charger_work, 0);
	}
#endif

	ret = sysfs_create_group(&client->dev.kobj, &bq2416x_attr_group);
	if (ret)
		dev_dbg(&client->dev, "could not create sysfs files\n");


	//twl6030_register_notifier(&di->nb, 1);
	INIT_WORK(&di->usb_work, bq2416x_usb_charger_work);

//r00186667, 2011/08/02, otg register for receive USB/AC plugin event.begin   
	di->nb_otg.notifier_call = bq2416x_usb_notifier_call;
	di->otg = otg_get_transceiver();
	ret = otg_register_notifier(di->otg, &di->nb_otg);
	if (ret)
		dev_err(&client->dev, "otg register notifier failed %d\n", ret);
//r00186667, 2011/08/02, otg register for receive USB/AC plugin event.end  

//r00186667, 2011/08/02, get the boot event type.begin  
    plugin_stat = get_plugin_device_status();
    if( PLUGIN_USB_CHARGER == plugin_stat){
		di->event = USB_EVENT_VBUS;
    }else if (PLUGIN_AC_CHARGER == plugin_stat){
         di->event = USB_EVENT_CHARGER;
    }else{
		di->event = USB_EVENT_NONE;
	}
	schedule_work(&di->usb_work);
//r00186667, 2011/08/02, get the boot event type.end  
	return 0;

err_kfree:
	kfree(di);	
	
	return ret;
}
Ejemplo n.º 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;
}
Ejemplo n.º 13
0
static int __devinit isp1704_charger_probe(struct platform_device *pdev)
{
	struct isp1704_charger	*isp;
	int			ret = -ENODEV;

	isp = kzalloc(sizeof *isp, GFP_KERNEL);
	if (!isp)
		return -ENOMEM;

	isp->otg = otg_get_transceiver();
	if (!isp->otg)
		goto fail0;

	isp->dev = &pdev->dev;
	platform_set_drvdata(pdev, isp);

	isp1704_charger_set_power(isp, 1);

	ret = isp1704_test_ulpi(isp);
	if (ret < 0)
		goto fail1;

	isp->psy.name		= "isp1704";
	isp->psy.type		= POWER_SUPPLY_TYPE_USB;
	isp->psy.properties	= power_props;
	isp->psy.num_properties	= ARRAY_SIZE(power_props);
	isp->psy.get_property	= isp1704_charger_get_property;

	ret = power_supply_register(isp->dev, &isp->psy);
	if (ret)
		goto fail1;

	/*
	 * REVISIT: using work in order to allow the otg notifications to be
	 * made atomically in the future.
	 */
	INIT_WORK(&isp->work, isp1704_charger_work);

	isp->nb.notifier_call = isp1704_notifier_call;

	ret = otg_register_notifier(isp->otg, &isp->nb);
	if (ret)
		goto fail2;

	dev_info(isp->dev, "registered with product id %s\n", isp->model);

	/*
	 * Taking over the D+ pullup.
	 *
	 * FIXME: The device will be disconnected if it was already
	 * enumerated. The charger driver should be always loaded before any
	 * gadget is loaded.
	 */
	if (isp->otg->gadget)
		usb_gadget_disconnect(isp->otg->gadget);

	/* Detect charger if VBUS is valid (the cable was already plugged). */
	ret = otg_io_read(isp->otg, ULPI_USB_INT_STS);
	isp1704_charger_set_power(isp, 0);
	if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) {
		isp->event = USB_EVENT_VBUS;
		schedule_work(&isp->work);
	}

	return 0;
fail2:
	power_supply_unregister(&isp->psy);
fail1:
	otg_put_transceiver(isp->otg);
fail0:
	kfree(isp);

	dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);

	return ret;
}
Ejemplo n.º 14
0
static int __init twl4030_bci_probe(struct platform_device *pdev)
{
    struct twl4030_bci *bci;
    int ret;
    u32 reg;

    bci = kzalloc(sizeof(*bci), GFP_KERNEL);
    if (bci == NULL)
        return -ENOMEM;

    bci->dev = &pdev->dev;
    bci->irq_chg = platform_get_irq(pdev, 0);
    bci->irq_bci = platform_get_irq(pdev, 1);

    platform_set_drvdata(pdev, bci);

    bci->ac.name = "twl4030_ac";
    bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
    bci->ac.properties = twl4030_charger_props;
    bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
    bci->ac.get_property = twl4030_bci_get_property;

    ret = power_supply_register(&pdev->dev, &bci->ac);
    if (ret) {
        dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
        goto fail_register_ac;
    }

    bci->usb.name = "twl4030_usb";
    bci->usb.type = POWER_SUPPLY_TYPE_USB;
    bci->usb.properties = twl4030_charger_props;
    bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
    bci->usb.get_property = twl4030_bci_get_property;

    ret = power_supply_register(&pdev->dev, &bci->usb);
    if (ret) {
        dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
        goto fail_register_usb;
    }

    ret = request_threaded_irq(bci->irq_chg, NULL,
                               twl4030_charger_interrupt, 0, pdev->name, bci);
    if (ret < 0) {
        dev_err(&pdev->dev, "could not request irq %d, status %d\n",
                bci->irq_chg, ret);
        goto fail_chg_irq;
    }

    ret = request_threaded_irq(bci->irq_bci, NULL,
                               twl4030_bci_interrupt, 0, pdev->name, bci);
    if (ret < 0) {
        dev_err(&pdev->dev, "could not request irq %d, status %d\n",
                bci->irq_bci, ret);
        goto fail_bci_irq;
    }

    INIT_WORK(&bci->work, twl4030_bci_usb_work);

    bci->transceiver = otg_get_transceiver();
    if (bci->transceiver != NULL) {
        bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
        otg_register_notifier(bci->transceiver, &bci->otg_nb);
    }

    /* Enable interrupts now. */
    reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
                 TWL4030_TBATOR1 | TWL4030_BATSTS);
    ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
                           TWL4030_INTERRUPTS_BCIIMR1A);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
        goto fail_unmask_interrupts;
    }

    reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
    ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
                           TWL4030_INTERRUPTS_BCIIMR2A);
    if (ret < 0)
        dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);

    twl4030_charger_enable_ac(true);
    twl4030_charger_enable_usb(bci, true);

    return 0;

fail_unmask_interrupts:
    if (bci->transceiver != NULL) {
        otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
        otg_put_transceiver(bci->transceiver);
    }
    free_irq(bci->irq_bci, bci);
fail_bci_irq:
    free_irq(bci->irq_chg, bci);
fail_chg_irq:
    power_supply_unregister(&bci->usb);
fail_register_usb:
    power_supply_unregister(&bci->ac);
fail_register_ac:
    platform_set_drvdata(pdev, NULL);
    kfree(bci);

    return ret;
}
static int __devinit bq2416x_charger_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	struct bq2416x_device_info *di;
	struct bq2416x_platform_data *pdata = client->dev.platform_data;
	int ret;
	u8 read_reg = 0;
	enum plugin_status plugin_stat;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	di->dev = &client->dev;
	di->client = client;

	i2c_set_clientdata(client, di);

	ret = bq2416x_read_byte(di, &read_reg, REG_PART_REVISION_REG04);

	if (ret < 0) {
		dev_err(&client->dev, "chip not present at address %x\n",
								client->addr);
		ret = -EINVAL;
		goto err_kfree;
	} 
	
	if ((read_reg & 0x18) == 0x00 && (client->addr == 0x6b))
		di->bqchip_version = BQ24161;

	if (di->bqchip_version == 0) {
		dev_dbg(&client->dev, "unknown bq chip\n");
		dev_dbg(&client->dev, "Chip address %x", client->addr);
		dev_dbg(&client->dev, "bq chip version reg value %x", read_reg);
		ret = -EINVAL;
		goto err_kfree;
	}
	//	di->nb.notifier_call = bq2416x_charger_event;

    /*set gpio_174 to control CD pin to disable/enable bq24161 IC*/
	 gpio_request(ENABLE_BQ2416x_CHARGER, "gpio_174_cd");
	 /* set charger CD pin to low level and enable it to supply power normally*/
	 gpio_direction_output(ENABLE_BQ2416x_CHARGER, 0);

     ret = bq2416x_get_max_charge_voltage(di);
	 if(!ret){
		di->max_voltagemV = pdata->max_charger_voltagemV;
	 }

	 ret = bq2416x_get_max_charge_current(di);
	 if(!ret){
		di->max_currentmA = pdata->max_charger_currentmA;
	 }

     di->max_cin_currentmA = IINLIM_1000;
	 di->voltagemV = di->max_voltagemV;
	 di->currentmA = ICHG_MIN_550 ;
     di->term_currentmA = ITERM_MIN_50;
	 di->dppm_voltagemV = VINDPM_MIN_4200;
	 di->cin_limit = IINLIM_500; 
    di->safety_timer = TMR_X_9;
	di->enable_low_chg = DISABLE_LOW_CHG;/*set normally charge mode*/
	di->enable_iterm = ENABLE_ITERM; /*enable charge current termination*/
    di->supply_sel = SUPPLY_SEL_IN;
	di->factory_flag = 0;
	di->enable_ce = ENABLE_CHARGER;
	di->hz_mode = DIS_HIZ;
	di->cd_active = 0;
	 
	INIT_DELAYED_WORK_DEFERRABLE(&di->bq2416x_charger_work,
				bq2416x_charger_work);


	wake_lock_init(&di->charger_wake_lock, WAKE_LOCK_SUSPEND, "charger_wake_lock");


	//BLOCKING_INIT_NOTIFIER_HEAD(&notifier_list);

	di->params.enable = 1;
	di->cfg_params = 1;
	
	 bq2416x_config_control_reg(di);
	 bq2416x_config_voltage_reg(di);
	 bq2416x_config_current_reg(di);
	 bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);	
	 bq2416x_config_safety_reg(di);

	ret = sysfs_create_group(&client->dev.kobj, &bq2416x_attr_group);
	if (ret)
		dev_dbg(&client->dev, "could not create sysfs files\n");

	//twl6030_register_notifier(&di->nb, 1);

	INIT_WORK(&di->usb_work, bq2416x_usb_charger_work);

	di->nb_otg.notifier_call = bq2416x_usb_notifier_call;
	di->otg = otg_get_transceiver();
	ret = otg_register_notifier(di->otg, &di->nb_otg);
	if (ret)
		dev_err(&client->dev, "otg register notifier failed %d\n", ret);
 
    plugin_stat = get_plugin_device_status();
    if( PLUGIN_USB_CHARGER == plugin_stat){
		di->event = USB_EVENT_VBUS;
    }else if (PLUGIN_AC_CHARGER == plugin_stat){
         di->event = USB_EVENT_CHARGER;
    }else{
		di->event = USB_EVENT_NONE;
	}
	schedule_work(&di->usb_work);
	return 0;

err_kfree:
	kfree(di);	
	
	return ret;
}