/*
* Copyright 2012 ST Ericsson.
*
* Power supply driver for ST Ericsson pm2xxx_charger charger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/workqueue.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/pm2301_charger.h>
#include <linux/gpio.h>
#include <linux/pm_runtime.h>
#include <linux/pm.h>
#include "pm2301_charger.h"
#define to_pm2xxx_charger_ac_device_info(x) container_of((x), \
struct pm2xxx_charger, ac_chg)
#define SLEEP_MIN 50
#define SLEEP_MAX 100
#define PM2XXX_AUTOSUSPEND_DELAY 500
static int pm2xxx_interrupt_registers[] = {
PM2XXX_REG_INT1,
PM2XXX_REG_INT2,
PM2XXX_REG_INT3,
PM2XXX_REG_INT4,
PM2XXX_REG_INT5,
PM2XXX_REG_INT6,
};
static enum power_supply_property pm2xxx_charger_ac_props[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_AVG,
};
static int pm2xxx_charger_voltage_map[] = {
3500,
3525,
3550,
3575,
3600,
3625,
3650,
3675,
3700,
3725,
3750,
3775,
3800,
3825,
3850,
3875,
3900,
3925,
3950,
3975,
4000,
4025,
4050,
4075,
4100,
4125,
4150,
4175,
4200,
4225,
4250,
4275,
4300,
};
static int pm2xxx_charger_current_map[] = {
200,
200,
400,
600,
800,
1000,
1200,
1400,
1600,
1800,
2000,
2200,
2400,
2600,
2800,
3000,
};
static const struct i2c_device_id pm2xxx_ident[] = {
{ "pm2301", 0 },
{ }
};
static void set_lpn_pin(struct pm2xxx_charger *pm2)
{
if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) {
gpio_set_value(pm2->lpn_pin, 1);
usleep_range(SLEEP_MIN, SLEEP_MAX);
}
}
static void clear_lpn_pin(struct pm2xxx_charger *pm2)
{
if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin))
gpio_set_value(pm2->lpn_pin, 0);
}
static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val)
{
int ret;
/* wake up the device */
pm_runtime_get_sync(pm2->dev);
ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg,