Merge branch 'develop-3.0' of ssh://10.10.10.29/rk/kernel into develop-3.0

This commit is contained in:
wlf
2013-08-10 11:02:02 +08:00
20 changed files with 2725 additions and 1273 deletions

View File

@@ -303,7 +303,7 @@ static struct rt5025_power_data rt5025_power_data = {
.BATD_EN = 0,
},
},
.fcc = 6200, //6200 mAh
// .fcc = 6200, //6200 mAh
};
static struct rt5025_gpio_data rt5025_gpio_data = {
@@ -379,7 +379,7 @@ static struct rt5025_irq_data rt5025_irq_data = {
.TIMEOUT_PC = 1,
.CHVSREGI = 0,
.CHTREGI = 0,
.CHRCHGI = 0,
.CHRCHGI = 1,
},
},
.irq_enable4 = {
@@ -407,6 +407,27 @@ static struct rt5025_irq_data rt5025_irq_data = {
},
};
//temp unit: 'c*10 degree
static int jeita_temp[4] = { 0, 150, 500, 600};
static u8 jeita_scalar[4] = { 0x2d, 0x25, 0x12, 0x0e};
//cc unit: xxx mA
static int jeita_temp_cc[][5] = {{ 500, 500, 500, 500, 500}, // not plugin
{ 0 , 250, 500, 250, 0}, // normal USB
{ 0, 500, 1000, 500, 0}, // USB charger
{ 0, 500, 1000, 500, 0}}; // AC Adapter
//cv unit: xxx mV
static int jeita_temp_cv[][5] = {{ 4200, 4200, 4200, 4200, 4200}, // not plugin
{ 4200, 4200, 4200, 4200, 4200}, // normal USB
{ 4200, 4200, 4200, 4200, 4200}, // USB charger
{ 4200, 4200, 4200, 4200, 4200}}; // AC Adapter
static struct rt5025_jeita_data rt5025_jeita_data = {
.temp = jeita_temp,
.temp_scalar = jeita_scalar,
.temp_cc = jeita_temp_cc,
.temp_cv = jeita_temp_cv,
};
static void rt5025_charger_event_callback(uint32_t detected)
{
RTINFO("event detected = 0x%08x\n", detected);
@@ -449,6 +470,7 @@ static struct rt5025_platform_data rt5025_data = {
.gpio_data = &rt5025_gpio_data,
.misc_data = &rt5025_misc_data,
.irq_data = &rt5025_irq_data,
.jeita_data = &rt5025_jeita_data,
.cb = &rt5025_event_callback,
.intr_pin = 81, //GPIO81
};

2
drivers/mfd/ricoh619.c Normal file → Executable file
View File

@@ -715,7 +715,7 @@ static int ricoh619_i2c_probe(struct i2c_client *client,
mutex_init(&ricoh619->io_lock);
ret = ricoh619_read(ricoh619->dev, 0x36, &control);
if ((control < 0) || (control == 0xff)) {
if ((control < 0) || (control == 0xff) || (control == 0)) {
printk(KERN_INFO "The device is not ricoh619\n");
return 0;
}

View File

@@ -47,6 +47,16 @@ static struct mfd_cell power_devs[] = {
.id = -1,
.num_resources = 0,
},
{
.name = RT5025_DEVICE_NAME "-swjeita",
.id = -1,
.num_resources = 0,
},
{
.name = RT5025_DEVICE_NAME "-battery",
.id = -1,
.num_resources = 0,
},
};
#endif /* CONFIG_POWER_RT5025 */
@@ -95,7 +105,6 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
int ret = 0;
RTINFO("Start to initialize all device\n");
printk("%s,line=%d\n", __func__,__LINE__);
#ifdef CONFIG_REGULATOR_RT5025
if (pdata && pdata->regulator[0]) {
@@ -117,7 +126,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
#endif /* CONFIG_REGULATOR_RT5025 */
#ifdef CONFIG_POWER_RT5025
if (pdata && pdata->power_data) {
if (pdata && pdata->power_data && pdata->jeita_data) {
RTINFO("mfd add power dev\n");
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
@@ -155,7 +164,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
}
}
#endif /* CONFIG_GPIO_RT5025 */
\
#ifdef CONFIG_MFD_RT5025_MISC
if (pdata && pdata->misc_data) {
RTINFO("mfd add misc dev\n");
@@ -193,10 +202,9 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
}
}
#endif /* CONFIG_MFD_RT5025_IRQ */
#if 1
#ifdef CONFIG_MFD_RT5025_DEBUG
RTINFO("mfd add debug dev\n");
printk("%s,line=%d\n", __func__,__LINE__);
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
ret = mfd_add_devices(chip->dev, 0, &debug_devs[0],
ARRAY_SIZE(debug_devs),
@@ -211,8 +219,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
goto out_dev;
}
#endif /* CONFIG_MFD_RT5025_DEBUG */
#endif
RTINFO("Initialize all device successfully\n");
return ret;
out_dev:

View File

@@ -31,8 +31,9 @@ static struct i2c_client *client;
static struct dentry *debugfs_rt_dent;
static struct dentry *debugfs_peek;
static struct dentry *debugfs_poke;
static struct dentry *debugfs_regs;
static unsigned char read_data;
static unsigned char read_data[10];
static int reg_debug_open(struct inode *inode, struct file *file)
{
@@ -65,12 +66,23 @@ static int get_parameters(char *buf, long int *param1, int num_of_par)
return 0;
}
#define LOG_FORMAT "0x%02x\n0x%02x\n0x%02x\n0x%02x\n0x%02x\n"
static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
size_t count, loff_t *ppos)
{
char lbuf[8];
snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
char *access_str = filp->private_data;
char lbuf[150];
if (!strcmp(access_str, "regs"))
{
RTINFO("read regs file\n");
/* read regs */
snprintf(lbuf, sizeof(lbuf), LOG_FORMAT LOG_FORMAT, read_data[0], \
read_data[1], read_data[2], read_data[3], read_data[4], read_data[5], \
read_data[6], read_data[7], read_data[8], read_data[9]);
}
else
snprintf(lbuf, sizeof(lbuf), "0x%02x\n", read_data[0]);
return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
}
@@ -105,7 +117,26 @@ static ssize_t reg_debug_write(struct file *filp,
rc = get_parameters(lbuf, param, 1);
if ((param[0] <= 0xFF) && (rc == 0))
{
read_data = rt5025_reg_read(client, param[0]);
read_data[0] = rt5025_reg_read(client, param[0]);
}
else
rc = -EINVAL;
} else if (!strcmp(access_str, "regs")) {
/* read */
rc = get_parameters(lbuf, param, 1);
if ((param[0] <= 0xFF) && (rc == 0))
{
rt5025_reg_block_read(client, param[0], 10, read_data);
RTINFO("regs 0 = 0x%02x\n", read_data[0]);
RTINFO("regs 1 = 0x%02x\n", read_data[1]);
RTINFO("regs 2 = 0x%02x\n", read_data[2]);
RTINFO("regs 3 = 0x%02x\n", read_data[3]);
RTINFO("regs 4 = 0x%02x\n", read_data[4]);
RTINFO("regs 5 = 0x%02x\n", read_data[5]);
RTINFO("regs 6 = 0x%02x\n", read_data[6]);
RTINFO("regs 7 = 0x%02x\n", read_data[7]);
RTINFO("regs 8 = 0x%02x\n", read_data[8]);
RTINFO("regs 9 = 0x%02x\n", read_data[9]);
}
else
rc = -EINVAL;
@@ -145,6 +176,10 @@ static int __devinit rt5025_debug_probe(struct platform_device *pdev)
debugfs_poke = debugfs_create_file("poke",
S_IFREG | S_IRUGO, debugfs_rt_dent,
(void *) "poke", &reg_debug_ops);
debugfs_regs = debugfs_create_file("regs",
S_IFREG | S_IRUGO, debugfs_rt_dent,
(void *) "regs", &reg_debug_ops);
}
platform_set_drvdata(pdev, di);

View File

@@ -40,33 +40,40 @@ static void rt5025_work_func(struct work_struct *work)
{
struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
struct rt5025_irq_info *ii = (struct rt5025_irq_info *)container_of(delayed_work, struct rt5025_irq_info, delayed_work);
unsigned char irq_stat[10] = {0};
unsigned char irq_stat[6] = {0};
uint32_t chg_event = 0, pwr_event = 0;
#ifdef CONFIG_POWER_RT5025
if (!ii->chip->power_info)
if (!ii->chip->power_info || !ii->chip->jeita_info || !ii->chip->battery_info)
{
queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(1));
return;
}
#endif
//if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
#if 0
if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
{
irq_stat[1] = rt5025_reg_read(ii->i2c, 0x31);
irq_stat[3] = rt5025_reg_read(ii->i2c, 0x33);
irq_stat[5] = rt5025_reg_read(ii->i2c, 0x35);
irq_stat[7] = rt5025_reg_read(ii->i2c, 0x37);
irq_stat[9] = rt5025_reg_read(ii->i2c, 0x39);
RTINFO("irq1->%02x, irq2->%02x, irq3->%02x\n", irq_stat[1], irq_stat[3], irq_stat[5]);
RTINFO("irq4->%02x, irq5->%02x\n", irq_stat[7], irq_stat[9]);
#endif
irq_stat[0] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS1);
irq_stat[1] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS2);
irq_stat[2] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS3);
irq_stat[3] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS4);
irq_stat[4] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS5);
irq_stat[5] = rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQFLG);
RTINFO("irq1->0x%02x, irq2->0x%02x, irq3->0x%02x\n", irq_stat[0], irq_stat[1], irq_stat[2]);
RTINFO("irq4->0x%02x, irq5->0x%02x, irq6->0x%02x\n", irq_stat[3], irq_stat[4], irq_stat[5]);
RTINFO("stat value = %02x\n", rt5025_reg_read(ii->i2c, RT5025_REG_CHGSTAT));
chg_event = irq_stat[1]<<16 | irq_stat[3]<<8 | irq_stat[5];
pwr_event = irq_stat[7]<<8 | irq_stat[9];
chg_event = irq_stat[0]<<16 | irq_stat[1]<<8 | irq_stat[2];
pwr_event = irq_stat[3]<<8 | irq_stat[4];
#ifdef CONFIG_POWER_RT5025
if (chg_event & CHARGER_DETECT_MASK)
{
if (chg_event & CHG_EVENT_CHTERMI)
ii->chip->power_info->chg_term++;
rt5025_power_charge_detect(ii->chip->power_info);
}
#endif /* CONFIG_POWER_RT5025 */
if (ii->event_cb)
{
@@ -75,15 +82,18 @@ static void rt5025_work_func(struct work_struct *work)
if (pwr_event)
ii->event_cb->power_event_callkback(pwr_event);
}
}
#if 0
}
else
dev_err(ii->dev, "read irq stat io fail\n");
#endif
#ifdef CONFIG_POWER_RT5025
rt5025_power_passirq_to_gauge(ii->chip->power_info);
if (irq_stat[5] & RT5025_FLG_TEMP)
rt5025_swjeita_irq_handler(ii->chip->jeita_info, irq_stat[5] & RT5025_FLG_TEMP);
if (irq_stat[5] & RT5025_FLG_VOLT)
rt5025_gauge_irq_handler(ii->chip->battery_info, irq_stat[5] & RT5025_FLG_VOLT);
#endif /* CONFIG_POWER_RT5025 */
//enable_irq(ii->irq);
@@ -170,7 +180,6 @@ static int __devinit rt5025_irq_probe(struct platform_device *pdev)
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct rt5025_platform_data *pdata = chip->dev->platform_data;
struct rt5025_irq_info *ii;
printk("%s,line=%d\n", __func__,__LINE__);
RTINFO("\n");
ii = kzalloc(sizeof(*ii), GFP_KERNEL);
@@ -201,6 +210,20 @@ static int __devexit rt5025_irq_remove(struct platform_device *pdev)
return 0;
}
static void rt5025_irq_shutdown(struct platform_device *pdev)
{
struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
if (ii->irq)
free_irq(ii->irq, ii);
if (ii->wq)
{
cancel_delayed_work_sync(&ii->delayed_work);
flush_workqueue(ii->wq);
}
}
static struct platform_driver rt5025_irq_driver =
{
.driver = {
@@ -209,6 +232,7 @@ static struct platform_driver rt5025_irq_driver =
},
.probe = rt5025_irq_probe,
.remove = __devexit_p(rt5025_irq_remove),
.shutdown = rt5025_irq_shutdown,
};
static int __init rt5025_irq_init(void)

1
drivers/mfd/rt5025-misc.c Executable file → Normal file
View File

@@ -49,7 +49,6 @@ static int __devinit rt5025_misc_probe(struct platform_device *pdev)
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct rt5025_platform_data *pdata = chip->dev->platform_data;
struct rt5025_misc_info *mi;
printk("%s,line=%d\n", __func__,__LINE__);
mi = kzalloc(sizeof(*mi), GFP_KERNEL);
if (!mi)

2
drivers/power/Makefile Executable file → Normal file
View File

@@ -49,4 +49,4 @@ obj-$(CONFIG_PLAT_RK) += rk29_charger_display.o
obj-$(CONFIG_BATTERY_RK30_ADC_FAC) += rk30_factory_adc_battery.o
obj-$(CONFIG_CW2015_BATTERY) += cw2015_battery.o
obj-$(CONFIG_BATTERY_RICOH619) += ricoh619-battery.o
obj-$(CONFIG_POWER_RT5025) += rt5025-power.o rt5025-gauge.o
obj-$(CONFIG_POWER_RT5025) += rt5025-power.o rt5025-battery.o rt5025-swjeita.o

1658
drivers/power/rt5025-battery.c Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,6 @@
#include <linux/workqueue.h>
#include <linux/mfd/rt5025.h>
#include <linux/power/rt5025-power.h>
#include <linux/power/rt5025-gauge.h>
#include <linux/delay.h>
@@ -34,6 +33,7 @@ static char *rt5025_supply_list[] = {
"rt5025-battery",
};
#if 0
static int rt5025_set_charging_current_switch (struct i2c_client *i2c, int onoff)
{
@@ -62,6 +62,7 @@ static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
u8 data = 0;
//ICC Setting
#if 0
if (cur_value > 2000)
data |= 0x0f<<3;
else if (cur_value >= 500 && cur_value <= 2000)
@@ -69,7 +70,7 @@ static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
data = (cur_value-500)/100;
data<<=3;
}
#endif
//AICR Setting
if (cur_value > 1000)
@@ -79,7 +80,7 @@ static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
else if (cur_value > 100 && cur_value >= 500)
data |= 0x01<<1;
rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGCC_MASK, data);
rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGAICR_MASK, data);
return ret;
}
@@ -94,22 +95,52 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
rt5025_set_charging_buck(info->i2c, 1);
#endif
info->chg_stat = 0x00;
#if 1
if (info->chip->battery_info)
{
if (info->chg_term == 0)
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_DISCHARGING);
else if (info->chg_term > 0)
{
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
info->chg_term = 0;
}
}
#else
if (info->event_callback)
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
#endif
break;
case 0x01:
//rt5025_set_charging_current_switch(info->i2c, 1);
info->chg_stat = 0x01;
#if 1
if (info->chip->battery_info)
{
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING);
info->chg_term = 0;
}
#else
if (info->event_callback)
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
#endif
break;
case 0x02:
#if 0
rt5025_set_charging_current_switch(info->i2c, 0);
#endif
info->chg_stat = 0x02;
#if 1
if (info->chip->battery_info)
{
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
info->chg_term = 0;
}
#else
if (info->event_callback)
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_FULL);
#endif
break;
case 0x03:
#if 0
@@ -117,8 +148,21 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
rt5025_set_charging_current_switch(info->i2c, 0);
#endif
info->chg_stat = 0x03;
#if 1
if (info->chip->battery_info)
{
if (info->chg_term == 0)
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING);
else if (info->chg_term > 1)
{
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
info->chg_term = 0;
}
}
#else
if (info->event_callback)
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
#endif
break;
default:
break;
@@ -126,6 +170,7 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
return ret;
}
#if 0
int rt5025_power_passirq_to_gauge(struct rt5025_power_info *info)
{
if (info->event_callback)
@@ -133,6 +178,7 @@ int rt5025_power_passirq_to_gauge(struct rt5025_power_info *info)
return 0;
}
EXPORT_SYMBOL(rt5025_power_passirq_to_gauge);
#endif
int rt5025_power_charge_detect(struct rt5025_power_info *info)
{
@@ -169,6 +215,7 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
schedule_delayed_work(&info->usb_detect_work, 0); //no delay
new_chgval = (chgstatval&RT5025_CHGSTAT_MASK)>>RT5025_CHGSTAT_SHIFT;
if (new_acval || new_usbval)
{
if (old_chgval != new_chgval)
@@ -183,8 +230,15 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
rt5025_set_charging_current_switch(info->i2c, 0);
#endif
info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
if (info->chip->jeita_info)
rt5025_notify_charging_cable(info->chip->jeita_info, JEITA_NO_CHARGE);
#if 1
if (info->chip->battery_info)
rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_NOT_CHARGING);
#else
if (info->event_callback)
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
#endif
}
return ret;
@@ -212,8 +266,10 @@ static int rt5025_adap_get_props(struct power_supply *psy,
return 0;
}
extern int dwc_vbus_status(void);
static void usb_detect_work_func(struct work_struct *work)
{
struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
@@ -225,6 +281,7 @@ static void usb_detect_work_func(struct work_struct *work)
if (pi->ac_online)
{
rt5025_set_charging_current(pi->i2c, 1000);
rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_AC_ADAPTER);
pi->usb_cnt = 0;
}
else if (pi->usb_online)
@@ -234,11 +291,13 @@ static void usb_detect_work_func(struct work_struct *work)
{
case 2: // USB Wall charger
rt5025_set_charging_current(pi->i2c, 1000);
rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_USB_TA);
pr_info("rt5025: detect usb wall charger\n");
break;
case 1: //normal USB
default:
rt5025_set_charging_current(pi->i2c, 500);
rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NORMAL_USB);
pr_info("rt5025: detect normal usb\n");
break;
}
@@ -249,6 +308,7 @@ static void usb_detect_work_func(struct work_struct *work)
{
//default to prevent over current charging
rt5025_set_charging_current(pi->i2c, 500);
rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NO_CHARGE);
//reset usb_cnt;
pi->usb_cnt = 0;
}
@@ -259,13 +319,14 @@ static void usb_detect_work_func(struct work_struct *work)
static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct rt5025_power_data* pd)
{
RTINFO("++\n");
info->ac_online = 0;
info->usb_online =0;
//init charger buckck & charger current en to disable stat
info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
#if 0
if (info->event_callback)
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
#endif
rt5025_set_bits(info->i2c, RT5025_REG_CHGCTL4, RT5025_CHGRST_MASK);
udelay(200);
//init register setting
@@ -278,7 +339,6 @@ static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct
rt5025_power_charge_detect(info);
RTINFO("--\n");
return 0;
}
@@ -288,25 +348,26 @@ static int __devinit rt5025_power_probe(struct platform_device *pdev)
struct rt5025_platform_data *pdata = chip->dev->platform_data;
struct rt5025_power_info *pi;
int ret = 0;
printk("%s,line=%d\n", __func__,__LINE__);
pi = kzalloc(sizeof(*pi), GFP_KERNEL);
if (!pi)
return -ENOMEM;
pi->i2c = chip->i2c;
pi->dev = &pdev->dev;
pi->fcc = pdata->power_data->fcc;
pi->chip = chip;
mutex_init(&pi->var_lock);
INIT_DELAYED_WORK(&pi->usb_detect_work, usb_detect_work_func);
#if 0
ret = rt5025_gauge_init(pi);
if (ret)
goto out;
#endif
platform_set_drvdata(pdev, pi);
pi->ac.name = "rt5025-ac";
pi->ac.name = "rt5025-dc";
pi->ac.type = POWER_SUPPLY_TYPE_MAINS;
pi->ac.supplied_to = rt5025_supply_list;
pi->ac.properties = rt5025_adap_props;
@@ -340,18 +401,23 @@ out:
static int rt5025_power_suspend(struct platform_device *pdev, pm_message_t state)
{
#if 0
struct rt5025_power_info *pi = platform_get_drvdata(pdev);
if (pi->event_callback)
pi->event_callback->rt5025_gauge_suspend();
#endif
return 0;
}
static int rt5025_power_resume(struct platform_device *pdev)
{
#if 0
struct rt5025_power_info *pi = platform_get_drvdata(pdev);
if (pi->event_callback)
pi->event_callback->rt5025_gauge_resume();
#endif
return 0;
}
@@ -360,8 +426,10 @@ static int __devexit rt5025_power_remove(struct platform_device *pdev)
struct rt5025_power_info *pi = platform_get_drvdata(pdev);
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
#if 0
if (pi->event_callback)
pi->event_callback->rt5025_gauge_remove();
#endif
power_supply_unregister(&pi->usb);
power_supply_unregister(&pi->ac);
chip->power_info = NULL;

397
drivers/power/rt5025-swjeita.c Executable file
View File

@@ -0,0 +1,397 @@
/* drivers/power/rt5025-swjeita.c
* swjeita Driver for Richtek RT5025 PMIC
* Multi function device - multi functional baseband PMIC swjeita part
*
* Copyright (C) 2013
* Author: CY Huang <cy_huang@richtek.com>
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mfd/rt5025.h>
#include <linux/power/rt5025-swjeita.h>
#define TEMP_TOLERANCE 10 // 'c*10 gap for tolerance
static int rt5025_set_charging_cc_switch (struct i2c_client *i2c, int onoff)
{
int ret;
RTINFO("onoff = %d\n", onoff);
if (onoff)
ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK);
else
ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK);
return ret;
}
static int rt5025_set_charging_cc(struct i2c_client *i2c, int cur_value)
{
int ret;
u8 data;
RTINFO("current value = %d\n", cur_value);
if (cur_value < 500)
data = 0;
else if (cur_value > 2000)
data = 0xf<<RT5025_CHGICC_SHIFT;
else
data = ((cur_value-500)/100)<<RT5025_CHGICC_SHIFT;
ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, data);
if (cur_value == 0)
rt5025_set_charging_cc_switch(i2c, 0);
else
rt5025_set_charging_cc_switch(i2c, 1);
return ret;
}
static int rt5025_set_charging_cv(struct i2c_client *i2c, int voltage)
{
int ret;
u8 data;
RTINFO("voltage = %d\n", voltage);
if (voltage < 3500)
data = 0;
else if (voltage > 4440)
data = 0x2f<<RT5025_CHGCV_SHIFT;
else
data = ((voltage-3500)/20)<<RT5025_CHGCV_SHIFT;
ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, data);
return ret;
}
static int rt5025_sel_external_temp_index(struct rt5025_swjeita_info *swji)
{
int temp = swji->cur_temp;
int sect_index;
RTINFO("\n");
if (temp < swji->temp[0])
sect_index = 0;
else if (temp >= swji->temp[0] && temp < swji->temp[1])
sect_index = 1;
else if (temp >= swji->temp[1] && temp < swji->temp[2])
sect_index = 2;
else if (temp >= swji->temp[2] && temp < swji->temp[3])
sect_index = 3;
else if (temp >= swji->temp[3])
sect_index = 4;
RTINFO("sect_index = %d\n", sect_index);
return sect_index;
}
static int rt5025_get_external_temp_index(struct rt5025_swjeita_info *swji)
{
u8 data[2];
long int temp;
int sect_index;
RTINFO("\n");
if (rt5025_reg_block_read(swji->i2c, RT5025_REG_AINH, 2, data) < 0)
pr_err("%s: failed to read ext_temp register\n", __func__);
temp = (data[0]*256+data[1])*61/100;
temp = (temp * (-91738) +81521000)/100000;
swji->cur_temp = temp;
RTINFO("cur_section = %d, cur_temp = %d\n", swji->cur_section, swji->cur_temp);
switch (swji->cur_section)
{
case 0:
if (temp < swji->temp[0]+TEMP_TOLERANCE)
sect_index = rt5025_sel_external_temp_index(swji);
else
sect_index = swji->cur_section;
break;
case 1:
if (temp <= swji->temp[0]-TEMP_TOLERANCE || temp >= swji->temp[1]+TEMP_TOLERANCE)
sect_index = rt5025_sel_external_temp_index(swji);
else
sect_index = swji->cur_section;
break;
case 2:
if (temp <= swji->temp[1]-TEMP_TOLERANCE || temp >= swji->temp[2]+TEMP_TOLERANCE)
sect_index = rt5025_sel_external_temp_index(swji);
else
sect_index = swji->cur_section;
break;
case 3:
if (temp <= swji->temp[2]-TEMP_TOLERANCE || temp >= swji->temp[3]+TEMP_TOLERANCE)
sect_index = rt5025_sel_external_temp_index(swji);
else
sect_index = swji->cur_section;
break;
case 4:
if (temp <= swji->temp[3]-TEMP_TOLERANCE)
sect_index = rt5025_sel_external_temp_index(swji);
else
sect_index = swji->cur_section;
break;
default:
sect_index = swji->cur_section;
break;
}
RTINFO("sect_index = %d\n", sect_index);
return sect_index;
}
static inline int rt5025_set_ainadc_onoff(struct rt5025_swjeita_info *swji, int enable)
{
int ret;
RTINFO("enable = %d\n", enable);
if (enable)
ret = rt5025_set_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_AINEN_MASK);
else
ret = rt5025_clr_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_AINEN_MASK);
return ret;
}
static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
{
int ret = 0;
RTINFO("index = %d\n", index);
switch (index)
{
case 0:
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[0]);
break;
case 1:
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[0]);
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
break;
case 2:
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[1]);
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[2]);
break;
case 3:
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[3]);
break;
case 4:
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[3]);
break;
}
return ret;
}
static int rt5025_exttemp_alert_switch(struct rt5025_swjeita_info *swji, int onoff)
{
if (!onoff)
{
rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
}
else
{
switch (swji->cur_section)
{
case 0:
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
break;
case 1:
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
break;
case 2:
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
break;
case 3:
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
break;
case 4:
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
break;
}
}
RTINFO("index=%d, onoff=%d\n", swji->cur_section, onoff);
return 0;
}
int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_type)
{
int sect_index;
int ret = 0;
RTINFO("cable_type = %d\n", cable_type);
rt5025_exttemp_alert_switch(swji, 0);
sect_index = rt5025_get_external_temp_index(swji);
if (swji->cur_section != sect_index || swji->init_once == 0)
{
rt5025_set_exttemp_alert(swji, sect_index);
swji->cur_section = sect_index;
swji->init_once = 1;
}
switch (cable_type)
{
case JEITA_NORMAL_USB:
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
break;
case JEITA_USB_TA:
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
break;
case JEITA_AC_ADAPTER:
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
break;
case JEITA_NO_CHARGE:
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
break;
}
swji->cur_cable = cable_type;
rt5025_exttemp_alert_switch(swji, 1);
return ret;
}
EXPORT_SYMBOL(rt5025_notify_charging_cable);
int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *swji, unsigned char event)
{
int ret = 0;
RTINFO("event = 0x%02x\n", event);
if (event&(RT5025_TMXEN_MASK|RT5025_TMNEN_MASK))
rt5025_notify_charging_cable(swji, swji->cur_cable);
return ret;
}
EXPORT_SYMBOL(rt5025_swjeita_irq_handler);
static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
{
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct rt5025_platform_data *pdata = chip->dev->platform_data;
struct rt5025_swjeita_info *swji;
int ret = 0;
swji = kzalloc(sizeof(*swji), GFP_KERNEL);
if (!swji)
return -ENOMEM;
#if 0 // for debug pdata->jeita_data
for (ret=0; ret<4; ret++)
RTINFO("jeita temp value %d\n", pdata->jeita_data->temp[ret]);
for (ret=0; ret<4; ret++)
{
RTINFO("jeita temp_cc value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cc[ret][0], \
pdata->jeita_data->temp_cc[ret][1], pdata->jeita_data->temp_cc[ret][2], \
pdata->jeita_data->temp_cc[ret][3], pdata->jeita_data->temp_cc[ret][4]);
}
for (ret=0; ret<4; ret++)
{
RTINFO("jeita temp_cv value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cv[ret][0], \
pdata->jeita_data->temp_cv[ret][1], pdata->jeita_data->temp_cv[ret][2], \
pdata->jeita_data->temp_cv[ret][3], pdata->jeita_data->temp_cv[ret][4]);
}
for (ret=0; ret<4; ret++)
{
RTINFO("temp_scalar[%d] = 0x%02x\n", ret, pdata->jeita_data->temp_scalar[ret]);
}
ret = 0;
#endif /* #if 0 */
swji->i2c = chip->i2c;
swji->chip = chip;
swji->cur_section = 2; //initial as the normal temperature
swji->cur_cable = JEITA_NO_CHARGE;
swji->temp = pdata->jeita_data->temp;
swji->temp_scalar = pdata->jeita_data->temp_scalar;
swji->temp_cc = pdata->jeita_data->temp_cc;
swji->temp_cv = pdata->jeita_data->temp_cv;
platform_set_drvdata(pdev, swji);
rt5025_set_ainadc_onoff(swji, 1);
mdelay(100);
rt5025_notify_charging_cable(swji, swji->cur_cable);
chip->jeita_info = swji;
RTINFO("rt5025-swjeita driver is successfully loaded\n");
return ret;
}
static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
{
struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
swji->chip->jeita_info = NULL;
kfree(swji);
return 0;
}
static int rt5025_swjeita_suspend(struct platform_device *pdev, pm_message_t state)
{
struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
swji->suspend = 1;
return 0;
}
static int rt5025_swjeita_resume(struct platform_device *pdev)
{
struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
swji->suspend = 0;
return 0;
}
static struct platform_driver rt5025_swjeita_driver =
{
.driver = {
.name = RT5025_DEVICE_NAME "-swjeita",
.owner = THIS_MODULE,
},
.probe = rt5025_swjeita_probe,
.remove = __devexit_p(rt5025_swjeita_remove),
.suspend = rt5025_swjeita_suspend,
.resume = rt5025_swjeita_resume,
};
static int __init rt5025_swjeita_init(void)
{
return platform_driver_register(&rt5025_swjeita_driver);
}
module_init(rt5025_swjeita_init);
static void __exit rt5025_swjeita_exit(void)
{
platform_driver_unregister(&rt5025_swjeita_driver);
}
module_exit(rt5025_swjeita_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
MODULE_DESCRIPTION("Swjeita driver for RT5025");
MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-swjeita");

View File

@@ -35,6 +35,8 @@ struct rt5025_regulator_info {
int vol_mask;
int enable_bit;
int enable_reg;
int mode_bit;
int mode_reg;
};
//for DCDC1
@@ -121,10 +123,10 @@ static int rt5025_list_voltage(struct regulator_dev *rdev, unsigned index)
return (index>=info->vol_output_size)? \
-EINVAL: \
info->vol_output_list[index ];
info->vol_output_list[index];
}
//#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
static int rt5025_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
@@ -147,7 +149,7 @@ static int rt5025_get_voltage_sel(struct regulator_dev *rdev)
return ret;
return (ret & info->vol_mask) >> info->vol_shift;
}
//#else
#else
static int rt5025_find_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
@@ -169,6 +171,7 @@ static int rt5025_set_voltage(struct regulator_dev *rdev,
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
unsigned char data;
if (check_range(info, min_uV, max_uV)) {
dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
min_uV, max_uV);
@@ -176,20 +179,22 @@ static int rt5025_set_voltage(struct regulator_dev *rdev,
}
data = rt5025_find_voltage(rdev,min_uV,max_uV);
data <<= info->vol_shift;
return rt5025_assign_bits(info->i2c, info->vol_reg, info->vol_mask, data);
}
static int rt5025_get_voltage(struct regulator_dev *rdev)
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
int ret;
ret = rt5025_get_voltage_sel(rdev);
ret = rt5025_reg_read(info->i2c, info->vol_reg);
if (ret < 0)
return ret;
return rt5025_list_voltage(rdev, ret );
ret = (ret & info->vol_mask) >> info->vol_shift;
return rt5025_list_voltage(rdev, ret);
}
//#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
static int rt5025_enable(struct regulator_dev *rdev)
{
@@ -218,102 +223,61 @@ static int rt5025_is_enabled(struct regulator_dev *rdev)
return (ret & (info->enable_bit))?1:0;
}
static int rt5025_dcdc_get_mode(struct regulator_dev *rdev)
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
int buck = rdev_get_id(rdev) - 0;
int ret;
uint8_t control;
ret = rt5025_reg_read(info->i2c, 0x0c);
if (ret < 0) {
return ret;
}
if (buck ==0){
control =(ret & 0x80)>>7;
}
else if (buck ==1){
control =(ret & 0x40)>>6;
}
else if (buck ==2){
control =(ret & 0x20)>>5;
}
else{
return -1;
}
switch (control) {
case 0:
return REGULATOR_MODE_FAST;
case 1:
return REGULATOR_MODE_NORMAL;
default:
return -1;
}
}
static int rt5025_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
int buck = rdev_get_id(rdev) - 0;
int ret;
uint8_t control;
ret = rt5025_reg_read(info->i2c, 0x0c);
if (buck ==0){
control =ret &(~ (1 <<7));
}
else if (buck ==1){
control =ret &(~ (1 <<6));
}
else if (buck ==2){
control =ret &(~ (1 <<5));
}
else{
return -1;
}
switch(mode)
{
case REGULATOR_MODE_FAST:
return rt5025_reg_write(info->i2c, 0x0c,control);
case REGULATOR_MODE_NORMAL:
return rt5025_reg_write(info->i2c, 0x0c,(control | (1 <<(7-buck))));
default:
printk("error:pmu_rt5025 only powersave pwm & auto mode\n");
return -EINVAL;
}
}
static int rt5025_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector,
unsigned int new_selector)
{
int old_volt, new_volt;
old_volt = rt5025_list_voltage(rdev, old_selector);
if (old_volt < 0)
return old_volt;
new_volt = rt5025_list_voltage(rdev, new_selector);
if (new_volt < 0)
return new_volt;
return DIV_ROUND_UP(abs(old_volt - new_volt), 25000);
static int rt5025_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
int ret;
if (!info->mode_bit)
ret = 0;
else
{
switch (mode)
{
case REGULATOR_MODE_NORMAL:
ret = rt5025_set_bits(info->i2c, info->mode_reg, info->mode_bit);
break;
case REGULATOR_MODE_FAST:
ret = rt5025_clr_bits(info->i2c, info->mode_reg, info->mode_bit);
break;
default:
ret = -EINVAL;
break;
}
}
return ret;
}
static unsigned int rt5025_get_mode(struct regulator_dev *rdev)
{
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
unsigned int mode;
int data;
if (!info->mode_bit)
mode = REGULATOR_MODE_NORMAL;
else
{
data = rt5025_reg_read(info->i2c, info->mode_reg);
mode = (data & info->mode_bit)?REGULATOR_MODE_NORMAL:REGULATOR_MODE_FAST;
}
return mode;
}
static struct regulator_ops rt5025_regulator_ops = {
.list_voltage = rt5025_list_voltage,
//#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
// .get_voltage_sel = rt5025_get_voltage_sel,
// .set_voltage_sel = rt5025_set_voltage_sel,
//#else
#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
.get_voltage_sel = rt5025_get_voltage_sel,
.set_voltage_sel = rt5025_set_voltage_sel,
#else
.set_voltage = rt5025_set_voltage,
.get_voltage = rt5025_get_voltage,
//#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
.enable = rt5025_enable,
.disable = rt5025_disable,
.is_enabled = rt5025_is_enabled,
.get_mode = rt5025_dcdc_get_mode,
.set_mode = rt5025_dcdc_set_mode,
.set_voltage_time_sel = rt5025_dcdc_set_voltage_time_sel,
.set_mode = rt5025_set_mode,
.get_mode = rt5025_get_mode,
};
#define RT5025_DCDCVOUT_LIST1 rt5025_vol_output_list1
@@ -358,6 +322,8 @@ static struct regulator_ops rt5025_regulator_ops = {
.vol_mask = RT5025_DCDCVOUT_MASK##_id, \
.enable_reg = RT5025_DCDC_OUTPUT_EN, \
.enable_bit = RT5025_DCDCEN_MASK##_id, \
.mode_reg = RT5025_REG_DCDCVRC, \
.mode_bit = RT5025_DCDCMODE_MASK##_id \
}
#define RT5025_LDO(_id, min, max) \
@@ -379,6 +345,8 @@ static struct regulator_ops rt5025_regulator_ops = {
.vol_mask = RT5025_LDOVOUT_MASK##_id, \
.enable_reg = RT5025_LDO_OUTPUT_EN, \
.enable_bit = RT5025_LDOEN_MASK##_id, \
.mode_reg = RT5025_REG_LDOVRC, \
.mode_bit = RT5025_LDOMODE_MASK##_id, \
}
static struct rt5025_regulator_info rt5025_regulator_info[] =

9
include/linux/mfd/rt5025-irq.h Executable file → Normal file
View File

@@ -16,9 +16,18 @@
#define RT5025_REG_CHGSTAT 0x01
#define RT5025_REG_IRQEN1 0x30
#define RT5025_REG_IRQSTATUS1 0x31
#define RT5025_REG_IRQEN2 0x32
#define RT5025_REG_IRQSTATUS2 0x33
#define RT5025_REG_IRQEN3 0x34
#define RT5025_REG_IRQSTATUS3 0x35
#define RT5025_REG_IRQEN4 0x36
#define RT5025_REG_IRQSTATUS4 0x37
#define RT5025_REG_IRQEN5 0x38
#define RT5025_REG_IRQSTATUS5 0x39
#define RT5025_REG_GAUGEIRQFLG 0x51
#define RT5025_FLG_TEMP 0x30
#define RT5025_FLG_VOLT 0x07
#endif /* #ifndef __LINUX_RT5025_IRQ_H */

235
include/linux/mfd/rt5025.h Executable file → Normal file
View File

@@ -14,6 +14,7 @@
#define __LINUX_MFD_RT5025_H
#include <linux/power_supply.h>
#include <linux/android_alarm.h>
#define RT5025_DEVICE_NAME "RT5025"
@@ -215,7 +216,6 @@ struct rt5025_power_data {
}bitfield;
unsigned char val;
}CHGControl7;
u32 fcc;
};
struct rt5025_gpio_data {
@@ -337,6 +337,21 @@ struct rt5025_irq_data {
}irq_enable5;
};
enum {
JEITA_NO_CHARGE,
JEITA_NORMAL_USB,
JEITA_USB_TA,
JEITA_AC_ADAPTER,
JEITA_CHARGER_MAX,
};
struct rt5025_jeita_data {
int* temp;
u8* temp_scalar;
int (*temp_cc)[5];
int (*temp_cv)[5];
};
#define CHG_EVENT_INACOVP (0x80<<16)
#define CHG_EVENT_INAC_PLUGIN (0x40<<16)
#define CHG_EVENT_INUSBOVP (0x10<<16)
@@ -360,7 +375,9 @@ struct rt5025_irq_data {
#define CHARGER_DETECT_MASK (CHG_EVENT_INAC_PLUGIN | CHG_EVENT_INUSB_PLUGIN | \
CHG_EVENT_CHSLPI_INAC | CHG_EVENT_CHSLPI_INUSB | \
CHG_EVENT_CHBADI_INAC | CHG_EVENT_CHBADI_INUSB)
CHG_EVENT_CHBADI_INAC | CHG_EVENT_CHBADI_INUSB | \
CHG_EVENT_CHTERMI | CHG_EVENT_CHRCHGI)
#define PWR_EVENT_OTIQ (0x80<<8)
#define PWR_EVENT_DCDC1LV (0x40<<8)
@@ -374,7 +391,7 @@ struct rt5025_irq_data {
#define PWR_EVENT_KPSHDN (0x80<<0)
#define PWR_EVNET_PWRONR (0x40<<0)
#define PWR_EVENT_PWRONF (0x20<<0)
#define PWR_EVENT_RESETB (0x10<<0)
#define PWR_EVENT_RESETB (0x10<<0)
#define PWR_EVENT_GPIO2IE (0x08<<0)
#define PWR_EVENT_GPIO1IE (0x04<<0)
#define PWR_EVENT_GPIO0IE (0x02<<0)
@@ -393,38 +410,13 @@ struct rt5025_event_callback {
#endif
};
struct rt5025_power_info {
struct i2c_client *i2c;
struct device *dev;
struct rt5025_gauge_callbacks *event_callback;
struct power_supply ac;
struct power_supply usb;
struct mutex var_lock;
struct delayed_work usb_detect_work;
int usb_cnt;
u32 fcc;
unsigned ac_online:1;
unsigned usb_online:1;
unsigned chg_stat:3;
};
struct rt5025_chip {
struct i2c_client *i2c;
struct workqueue_struct *wq;
struct device *dev;
struct rt5025_power_info *power_info;
int suspend;
int irq;
struct delayed_work delayed_work;
struct mutex io_lock;
};
struct rt5025_platform_data {
struct regulator_init_data* regulator[RT5025_MAX_REGULATOR];
struct rt5025_power_data* power_data;
struct rt5025_gpio_data* gpio_data;
struct rt5025_misc_data* misc_data;
struct rt5025_irq_data* irq_data;
struct rt5025_jeita_data* jeita_data;
struct rt5025_event_callback *cb;
int (*pre_init)(struct rt5025_chip *rt5025_chip);
/** Called after subdevices are set up */
@@ -432,14 +424,195 @@ struct rt5025_platform_data {
int intr_pin;
};
struct rt5025_power_info {
struct i2c_client *i2c;
struct device *dev;
struct rt5025_chip *chip;
//struct rt5025_gauge_callbacks *event_callback;
struct power_supply ac;
struct power_supply usb;
struct mutex var_lock;
struct delayed_work usb_detect_work;
int usb_cnt;
int chg_term;
unsigned ac_online:1;
unsigned usb_online:1;
unsigned chg_stat:3;
};
struct rt5025_swjeita_info {
struct i2c_client *i2c;
struct rt5025_chip *chip;
int *temp;
u8 *temp_scalar;
int (*temp_cc)[5];
int (*temp_cv)[5];
int cur_section;
int cur_cable;
int cur_temp;
int init_once;
int suspend;
};
struct rt5025_battery_info {
struct i2c_client *client;
struct rt5025_chip *chip;
//struct rt5025_gauge_callbacks cb;
struct power_supply battery;
struct delayed_work monitor_work;
struct wake_lock monitor_wake_lock;
struct wake_lock low_battery_wake_lock;
//#if RT5025_TEST_WAKE_LOCK
struct wake_lock test_wake_lock;
//#endif
struct alarm wakeup_alarm;
bool temp_range_0_5;
bool temp_range_5_10;
bool temp_range_10_15;
bool temp_range_15_20;
bool temp_range_20_30;
bool temp_range_30_35;
bool temp_range_35_40;
bool temp_range_40_45;
bool temp_range_45_50;
bool range_0_5_done;
bool range_5_10_done;
bool range_10_15_done;
bool range_15_20_done;
bool range_20_30_done;
bool range_30_35_done;
bool range_35_40_done;
bool range_40_45_done;
bool range_45_50_done;
bool suspend_poll;
ktime_t last_poll;
// ktime_t last_event;
struct timespec last_event;
u16 update_time;
/* previous battery voltage */
u16 pre_vcell;
/* previous battery current */
s16 pre_curr;
/* battery voltage */
u16 vcell;
/* battery current */
s16 curr;
/* battery current offset */
u16 curr_offset;
/* AIN voltage */
u16 ain_volt;
/* battery external temperature */
s16 ext_temp;
/* charge coulomb counter */
u32 chg_cc;
u32 chg_cc_unuse;
/* discharge coulomb counter */
u32 dchg_cc;
u32 dchg_cc_unuse;
/* battery capacity */
u16 soc;
u16 temp_soc;
u16 pre_soc;
u16 time_interval;
u16 pre_gauge_timer;
u8 online;
u8 status;
u8 internal_status;
u8 health;
u8 present;
/* IRQ flag */
u8 irq_flag;
/* max voltage IRQ flag */
bool max_volt_irq;
/* min voltage1 IRQ flag */
bool min_volt1_irq;
/* min voltage2 IRQ flag */
bool min_volt2_irq;
/* max temperature IRQ flag */
bool max_temp_irq;
/* min temperature IRQ flag */
bool min_temp_irq;
bool min_volt2_alert;
u8 temp_high_cnt;
u8 temp_low_cnt;
u8 temp_recover_cnt;
bool init_cap;
bool avg_flag;
/* remain capacity */
u32 rm;
/* SOC permille */
u16 permille;
/* full capccity */
u16 fcc_aging;
u16 fcc;
u16 dc;
s16 tempcmp;
#if 0
u32 time_to_empty;
u32 time_to_full;
#endif
bool edv_flag;
bool edv_detection;
u8 edv_cnt;
bool tp_flag;
u8 tp_cnt;
u8 cycle_cnt;
u32 acc_dchg_cap;
bool smooth_flag;
u16 gauge_timer;
s16 curr_raw;
bool init_once;
bool device_suspend;
u8 test_temp;
};
struct rt5025_chip {
struct i2c_client *i2c;
struct workqueue_struct *wq;
struct device *dev;
struct rt5025_power_info *power_info;
struct rt5025_swjeita_info *jeita_info;
struct rt5025_battery_info *battery_info;
int suspend;
int irq;
struct delayed_work delayed_work;
struct mutex io_lock;
};
#ifdef CONFIG_MFD_RT5025_MISC
extern void rt5025_power_off(void);
#endif /* CONFIG_MFD_RT5025_MISC */
#ifdef CONFIG_POWER_RT5025
extern int rt5025_gauge_init(struct rt5025_power_info *);
extern int rt5025_power_passirq_to_gauge(struct rt5025_power_info *);
extern void rt5025_gauge_set_status(struct rt5025_battery_info *, int);
extern void rt5025_gauge_set_online(struct rt5025_battery_info *, bool);
extern void rt5025_gauge_irq_handler(struct rt5025_battery_info *, u8);
extern int rt5025_power_charge_detect(struct rt5025_power_info *);
extern int rt5025_notify_charging_cable(struct rt5025_swjeita_info *, int);
extern int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *, unsigned char);
#endif /* CONFIG_POEWR_RT5025 */
extern int rt5025_reg_block_read(struct i2c_client *, int, int, void *);

View File

@@ -0,0 +1,26 @@
battery_graph_prop rt5025_battery_param1[] =
{
{4190, 1000},
{4153, 980},
{4067, 890},
{3991, 800},
{3931, 710},
{3845, 580},
{3799, 490},
{3776, 400},
{3743, 240},
{3695, 140},
{3660, 70},
{3642, 50},
{3509, 20},
{3300, 0},
};
battery_graph_prop rt5025_battery_param2[] =
{
{450,30},
{250, 0},
{50,-90},
{50, 10},
{3400, 6900},
};

View File

@@ -0,0 +1,125 @@
/*
* include/linux/power/rt5025-battery.h
* Include header file for Richtek RT5025 battery Driver
*
* Copyright (C) 2013 Richtek Electronics
* cy_huang <cy_huang@richtek.com>
*
* 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.
*/
#ifndef __LINUX_RT5025_BATTERY_H
#define __LINUX_RT5025_BATTERY_H
#define ROCKCHIP_BATTERY_6200MAH
#undef ROCKCHIP_BATTERY_2100MAH
#define RT5025_REG_IRQ_CTL 0x50
#define RT5025_REG_IRQ_FLAG 0x51
#define RT5025_REG_VALRT_MAXTH 0x53
#define RT5025_REG_VALRT_MIN1TH 0x54
#define RT5025_REG_VALRT_MIN2TH 0x55
#define RT5025_REG_TALRT_MAXTH 0x56
#define RT5025_REG_TALRT_MINTH 0x57
#define RT5025_REG_VCELL_MSB 0x58
#define RT5025_REG_VCELL_LSB 0x59
#define RT5025_REG_INT_TEMPERATUE_MSB 0x5B
#define RT5025_REG_INT_TEMPERATUE_LSB 0x5C
#define RT5025_REG_EXT_TEMPERATUE_MSB 0x5E
#define RT5025_REG_EXT_TEMPERATUE_LSB 0x5F
#define RT5025_REG_TIMER 0x60
#define RT5025_REG_CHANNEL_MSB 0x62
#define RT5025_REG_CHANNEL_LSB 0x63
#define RT5025_REG_CURRENT_MSB 0x76
#define RT5025_REG_CURRENT_LSB 0x77
#define RT5025_REG_QCHGH_MSB 0x78
#define RT5025_REG_QCHGH_LSB 0x79
#define RT5025_REG_QCHGL_MSB 0x7A
#define RT5025_REG_QCHGL_LSB 0x7B
#define RT5025_REG_QDCHGH_MSB 0x7C
#define RT5025_REG_QDCHGH_LSB 0x7D
#define RT5025_REG_QDCHGL_MSB 0x7E
#define RT5025_REG_QDCHGL_LSB 0x7F
#define IRQ_CTL_BIT_TMX (1 << 5)
#define IRQ_CTL_BIT_TMN (1 << 4)
#define IRQ_CTL_BIT_VMX (1 << 2)
#define IRQ_CTL_BIT_VMN1 (1 << 1)
#define IRQ_CTL_BIT_VMN2 (1 << 0)
#define IRQ_FLG_BIT_TMX (1 << 5)
#define IRQ_FLG_BIT_TMN (1 << 4)
#define IRQ_FLG_BIT_VMX (1 << 2)
#define IRQ_FLG_BIT_VMN1 (1 << 1)
#define IRQ_FLG_BIT_VMN2 (1 << 0)
#define CHANNEL_H_BIT_CLRQDCHG (1 << 7)
#define CHANNEL_H_BIT_CLRQCHG (1 << 6)
#define CHANNEL_L_BIT_CADC_EN (1 << 7)
#define CHANNEL_L_BIT_INTEMPCH (1 << 6)
#define CHANNEL_L_BIT_AINCH (1 << 2)
#define CHANNEL_L_BIT_VBATSCH (1 << 1)
#define CHANNEL_L_BIT_VADC_EN (1 << 0)
#define NORMAL_POLL 30 /* 30 sec */
#define TP_POLL 5 /* 5 sec */
#define EDV_POLL 1 /* 1 sec */
#define SMOOTH_POLL 5 /* 5 sec */
#define SUSPEND_POLL (30*60) /* 30 min */
#define INIT_POLL 1
#define LOW_BAT_WAKE_LOK_TIME 120
#define HIGH_TEMP_THRES 650
#define HIGH_TEMP_RECOVER 430
#define LOW_TEMP_THRES (-30)
#define LOW_TEMP_RECOVER 0
#define TEMP_ABNORMAL_COUNT 3
#define EDV_HYS 100
#define IRQ_THRES_UNIT 1953
#define TALRTMAX_VALUE 0x38 //65.39'C
#define TALRTMIN_VALUE 0x9 //-18.75'C
#define TRLS_VALUE 55 //5'C ; unit:mV
#define VRLS_VALUE 100 //100mV
#define DEADBAND 10
//#define SLEEP_CURRENT 3 //mA
typedef enum{
CHG,
DCHG
}operation_mode;
typedef struct{
int x;
int y;
}battery_graph_prop;
typedef enum {
MAXTEMP,
MINTEMP,
MAXVOLT,
MINVOLT1,
MINVOLT2,
TEMP_RLS,
VOLT_RLS,
LAST_TYPE,
}alert_type;
#if defined(ROCKCHIP_BATTERY_6200MAH)
#include <linux/power/rockchip-6200ma-bat.h>
#elif defined(ROCKCHIP_BATTERY_2100MAH)
#include <linux/power/rockchip-2100ma-bat.h>
#else
#include <linux/power/rockchip-general-bat.h>
#endif
#define VALRTMIN2_VALUE (rt5025_battery_param2[4].x * 100 / IRQ_THRES_UNIT + 1) //EDV0 voltage
#endif /* #ifndef __LINUX_RT5025_BATTERY_H */

View File

@@ -1,37 +0,0 @@
/*
* rt5025_gauge.h
* fuel-gauge driver
* revision 0.1
*/
#ifndef __LINUX_RT5025_GAUGE_H_
#define __LINUX_RT5025_GAUGE_H_
#define GPIO_GAUGE_ALERT 4
struct rt5025_gauge_callbacks {
void (*rt5025_gauge_irq_handler)(void);
void (*rt5025_gauge_set_status)(int status);
void (*rt5025_gauge_suspend)(void);
void (*rt5025_gauge_resume)(void);
void (*rt5025_gauge_remove)(void);
};
typedef enum{
CHG,
DCHG
}operation_mode;
typedef enum{
MAXTEMP,
MINTEMP,
MAXVOLT,
MINVOLT1,
MINVOLT2,
TEMP_RLS,
VOLT_RLS,
LAST_TYPE
}alert_type;
#endif /* #ifndef __LINUX_RT5025_GAUGE_H_ */

View File

@@ -25,7 +25,7 @@
#define RT5025_CHGBUCKEN_MASK 0x02
#define RT5025_CHGCEN_MASK 0x10
#define RT5025_CHGCC_MASK 0x7E
#define RT5025_CHGAICR_MASK 0x06
#define RT5025_CHGSTAT_MASK 0x30
#define RT5025_CHGSTAT_SHIFT 4

View File

@@ -0,0 +1,35 @@
/*
* include/linux/power/rt5025-swjeita.h
* Include header file for Richtek RT5025 Core Jeita Driver
*
* Copyright (C) 2013 Richtek Electronics
* cy_huang <cy_huang@richtek.com>
*
* 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.
*/
#ifndef __LINUX_RT5025_SWJEITA_H
#define __LINUX_RT5025_SWJEITA_H
#define RT5025_REG_CHGCTL3 0x03
#define RT5025_REG_CHGCTL4 0x04
#define RT5025_REG_CHGCTL7 0x07
#define RT5025_REG_AINH 0x5E
#define RT5025_REG_CHANNELL 0x63
#define RT5025_REG_IRQCTL 0x50
#define RT5025_REG_TALRTMAX 0x56
#define RT5025_REG_TALRTMIN 0x57
#define RT5025_CHGCCEN_MASK 0x10
#define RT5025_CHGICC_SHIFT 3
#define RT5025_CHGICC_MASK 0x78
#define RT5025_CHGCV_SHIFT 2
#define RT5025_CHGCV_MASK 0xFC
#define RT5025_AINEN_MASK 0x04
#define RT5025_TMXEN_MASK 0x20
#define RT5025_TMNEN_MASK 0x10
#endif /* #ifndef __LINUX_RT5025_SWJEITA_H */

13
include/linux/regulator/rt5025-regulator.h Executable file → Normal file
View File

@@ -25,6 +25,8 @@
#define RT5025_REG_LDOCTRL6 0x12
#define RT5025_REG_DCDCEN 0x17
#define RT5025_REG_LDOEN 0x18
#define RT5025_REG_DCDCVRC 0x0B
#define RT5025_REG_LDOVRC 0x00
#define RT5025_DCDCVOUT1 RT5025_REG_DCDCCTRL1
#define RT5025_DCDCVOUT2 RT5025_REG_DCDCCTRL2
@@ -73,4 +75,15 @@
#define RT5025_LDOEN_MASK5 0x10
#define RT5025_LDOEN_MASK6 0x20
#define RT5025_DCDCMODE_MASK1 0x40
#define RT5025_DCDCMODE_MASK2 0x20
#define RT5025_DCDCMODE_MASK3 0x10
#define RT5025_DCDCMODE_MASK4 0x00
#define RT5025_LDOMODE_MASK1 0x00
#define RT5025_LDOMODE_MASK2 0x00
#define RT5025_LDOMODE_MASK3 0x00
#define RT5025_LDOMODE_MASK4 0x00
#define RT5025_LDOMODE_MASK5 0x00
#define RT5025_LDOMODE_MASK6 0x00
#endif /* __LINUX_RT5025_REGULATOR_H */