Re: [PATCH 2/4] power: ab8500-charger: AB8500 charger driver

From: Andi
Date: Wed Feb 29 2012 - 12:51:00 EST


Hi,

On Wed, Feb 29, 2012 at 5:24 PM, Arun Murthy <arun.murthy@xxxxxxxxxxxxxx> wrote:
> This driver is responsible for detecting the ac/usb plugin and also includes
> function to enable ac/usb charging and re-kick the watchdog.
> It registers with the power supply class and provides information to the user
> space. The information include status of ac/usb charger device.
> This information in turn will be used by the abx500 charging algorithm driver
> to enable/disable and monitor charging.
>
> Signed-off-by: Arun Murthy <arun.murthy@xxxxxxxxxxxxxx>
> Acked-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
> ---
> Âdrivers/power/ab8500_charger.c    | 2789 ++++++++++++++++++++++++++++++++++
> Âinclude/linux/mfd/abx500/ab8500-bm.h | Â554 +++++++
> Â2 files changed, 3343 insertions(+), 0 deletions(-)
> Âcreate mode 100644 drivers/power/ab8500_charger.c
> Âcreate mode 100644 include/linux/mfd/abx500/ab8500-bm.h
>
> diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
> new file mode 100644
> index 0000000..bbc541a
> --- /dev/null
> +++ b/drivers/power/ab8500_charger.c
> @@ -0,0 +1,2789 @@
> +/**
> + * ab8500_charger_init_hw_registers() - Set up charger related registers
> + * @di: Â Â Â Â Â Â Â Âpointer to the ab8500_charger structure
> + *
> + * Set up charger OVV, watchdog and maximum voltage registers as well as
> + * charging of the backup battery
> + */
> +static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
> +{
> + Â Â Â int ret = 0;
> +
> + Â Â Â /* Setup maximum charger current and voltage for ABB cut2.0 */
> + Â Â Â if (!is_ab8500_1p1_or_earlier(di->parent)) {
> + Â Â Â Â Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â Â Â Â Â AB8500_CHARGER,
> + Â Â Â Â Â Â Â Â Â Â Â AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6);
> + Â Â Â Â Â Â Â if (ret) {
> + Â Â Â Â Â Â Â Â Â Â Â dev_err(di->dev,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "failed to set CH_VOLT_LVL_MAX_REG\n");
> + Â Â Â Â Â Â Â Â Â Â Â goto out;
> + Â Â Â Â Â Â Â }
> +
> + Â Â Â Â Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â Â Â Â Â AB8500_CHARGER,
> + Â Â Â Â Â Â Â Â Â Â Â AB8500_CH_OPT_CRNTLVL_MAX_REG, CH_OP_CUR_LVL_1P6);
> + Â Â Â Â Â Â Â if (ret) {
> + Â Â Â Â Â Â Â Â Â Â Â dev_err(di->dev,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "failed to set CH_OPT_CRNTLVL_MAX_REG\n");
> + Â Â Â Â Â Â Â Â Â Â Â goto out;
> + Â Â Â Â Â Â Â }
> + Â Â Â }
> +
> + Â Â Â /* VBUS OVV set to 6.3V and enable automatic current limitiation */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_CHARGER,
> + Â Â Â Â Â Â Â AB8500_USBCH_CTRL2_REG,
> + Â Â Â Â Â Â Â VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "failed to set VBUS OVV\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /* Enable main watchdog in OTP */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD);
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "failed to enable main WD in OTP\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /* Enable main watchdog */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_SYS_CTRL2_BLOCK,
> + Â Â Â Â Â Â Â AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA);
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "faile to enable main watchdog\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /*
> + Â Â Â Â* Due to internal synchronisation, Enable and Kick watchdog bits
> + Â Â Â Â* cannot be enabled in a single write.
> + Â Â Â Â* A minimum delay of 2*32 kHz period (62.5Âs) must be inserted
> + Â Â Â Â* between writing Enable then Kick bits.
> + Â Â Â Â*/
> + Â Â Â udelay(63);

Are you sure about this udelay?

> +
> + Â Â Â /* Kick main watchdog */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_SYS_CTRL2_BLOCK,
> + Â Â Â Â Â Â Â AB8500_MAIN_WDOG_CTRL_REG,
> + Â Â Â Â Â Â Â (MAIN_WDOG_ENA | MAIN_WDOG_KICK));
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "failed to kick main watchdog\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /* Disable main watchdog */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_SYS_CTRL2_BLOCK,
> + Â Â Â Â Â Â Â AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS);
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "failed to disable main watchdog\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /* Set watchdog timeout */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
> + Â Â Â Â Â Â Â AB8500_CH_WD_TIMER_REG, WD_TIMER);
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "failed to set charger watchdog timeout\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /* Backup battery voltage and current */
> + Â Â Â ret = abx500_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_RTC,
> + Â Â Â Â Â Â Â AB8500_RTC_BACKUP_CHG_REG,
> + Â Â Â Â Â Â Â di->bat->bkup_bat_v |
> + Â Â Â Â Â Â Â di->bat->bkup_bat_i);
> + Â Â Â if (ret) {
> + Â Â Â Â Â Â Â dev_err(di->dev, "failed to setup backup battery charging\n");
> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â /* Enable backup battery charging */
> + Â Â Â abx500_mask_and_set_register_interruptible(di->dev,
> + Â Â Â Â Â Â Â AB8500_RTC, AB8500_RTC_CTRL_REG,
> + Â Â Â Â Â Â Â RTC_BUP_CH_ENA, RTC_BUP_CH_ENA);
> + Â Â Â if (ret < 0)
> + Â Â Â Â Â Â Â dev_err(di->dev, "%s mask and set failed\n", __func__);
> +
> +out:
> + Â Â Â return ret;
> +}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/