mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
rk3188:pmu:rt5025:modify some bug for pmu charger & irq & guage
This commit is contained in:
24
arch/arm/mach-rk30/board-pmu-rt5025.c
Executable file → Normal file
24
arch/arm/mach-rk30/board-pmu-rt5025.c
Executable file → Normal file
@@ -37,10 +37,6 @@ static int rt5025_pre_init(struct rt5025_chip *rt5025_chip){
|
||||
ret |= (1<<3); //enable DC4 boost
|
||||
rt5025_reg_write(rt5025_chip->i2c, 0x17,ret);
|
||||
/***********************************************/
|
||||
ret = rt5025_reg_read(rt5025_chip->i2c, 0x07);
|
||||
ret |= (1<<5); //
|
||||
rt5025_reg_write(rt5025_chip->i2c, 0x07,ret);
|
||||
|
||||
/************************************************/
|
||||
return 0;
|
||||
}
|
||||
@@ -283,13 +279,14 @@ static struct rt5025_power_data rt5025_power_data = {
|
||||
},
|
||||
.CHGControl4 = {
|
||||
.bitfield = {
|
||||
.AICR_CON = 1,
|
||||
.AICR = RT5025_AICR_500MA,
|
||||
.ICC = RT5025_ICC_1P8A,
|
||||
.ICC = RT5025_ICC_0P5A,
|
||||
},
|
||||
},
|
||||
.CHGControl5 = {
|
||||
.bitfield = {
|
||||
.DPM = RT5025_DPM_DIS,
|
||||
.DPM = RT5025_DPM_4P5V,
|
||||
},
|
||||
},
|
||||
.CHGControl6 = {
|
||||
@@ -302,10 +299,11 @@ static struct rt5025_power_data rt5025_power_data = {
|
||||
.CHGControl7 = {
|
||||
.bitfield = {
|
||||
.CHGC_EN = 1,
|
||||
.CHG_DCDC_MODE = 1,
|
||||
.CHG_DCDC_MODE = 0,
|
||||
.BATD_EN = 0,
|
||||
},
|
||||
},
|
||||
.fcc = 6200, //6200 mAh
|
||||
};
|
||||
|
||||
static struct rt5025_gpio_data rt5025_gpio_data = {
|
||||
@@ -323,7 +321,7 @@ static struct rt5025_misc_data rt5025_misc_data = {
|
||||
},
|
||||
.VSYSCtrl = {
|
||||
.bitfield = {
|
||||
.VOFF = RT5025_VOFF_3P1V,
|
||||
.VOFF = RT5025_VOFF_3P4V,
|
||||
},
|
||||
},
|
||||
.PwrOnCfg = {
|
||||
@@ -386,7 +384,7 @@ static struct rt5025_irq_data rt5025_irq_data = {
|
||||
},
|
||||
.irq_enable4 = {
|
||||
.bitfield = {
|
||||
.SYSLV = 0,
|
||||
.SYSLV = 1,
|
||||
.DCDC4LVHV = 1,
|
||||
.PWRONLP = 0,
|
||||
.PWRONSP = 0,
|
||||
@@ -412,11 +410,19 @@ static struct rt5025_irq_data rt5025_irq_data = {
|
||||
static void rt5025_charger_event_callback(uint32_t detected)
|
||||
{
|
||||
RTINFO("event detected = 0x%08x\n", detected);
|
||||
if (detected & CHG_EVENT_CHTERMI)
|
||||
{
|
||||
pr_info("charger termination OK\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void rt5025_power_event_callback(uint32_t detected)
|
||||
{
|
||||
RTINFO("event detected = 0x%08x\n", detected);
|
||||
if (detected & PWR_EVENT_SYSLV)
|
||||
{
|
||||
pr_info("sys voltage low\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct rt5025_event_callback rt5025_event_callback = {
|
||||
|
||||
4
arch/arm/mach-rk30/board-rk3168-tb.c
Executable file → Normal file
4
arch/arm/mach-rk30/board-rk3168-tb.c
Executable file → Normal file
@@ -2118,8 +2118,8 @@ static struct pmu_info rt5025_ldo_info[] = {
|
||||
},
|
||||
{
|
||||
.name = "rt5025-ldo3", //vdd10
|
||||
.min_uv = 1200000,
|
||||
.max_uv = 1200000,
|
||||
.min_uv = 1000000,
|
||||
.max_uv = 1000000,
|
||||
},
|
||||
{
|
||||
.name = "rt5025-ldo4", //vccjetta
|
||||
|
||||
@@ -865,6 +865,12 @@ config MFD_RT5025_DEBUG
|
||||
help
|
||||
Enable RT5025 core debug driver.
|
||||
|
||||
config MFD_RT_SHOW_INFO
|
||||
bool "RT5025 debug message"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
Eneable RT5025 debug message
|
||||
|
||||
config MFD_RK610
|
||||
bool "RK610(Jetta) Multimedia support"
|
||||
|
||||
4
drivers/mfd/rt5025-core.c
Executable file → Normal file
4
drivers/mfd/rt5025-core.c
Executable file → Normal file
@@ -193,7 +193,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MFD_RT5025_IRQ */
|
||||
#if 0
|
||||
#if 1
|
||||
#ifdef CONFIG_MFD_RT5025_DEBUG
|
||||
RTINFO("mfd add debug dev\n");
|
||||
printk("%s,line=%d\n", __func__,__LINE__);
|
||||
@@ -219,7 +219,7 @@ out_dev:
|
||||
mfd_remove_devices(chip->dev);
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall_sync(rt5025_core_init);
|
||||
EXPORT_SYMBOL(rt5025_core_init);
|
||||
|
||||
int __devexit rt5025_core_deinit(struct rt5025_chip *chip)
|
||||
{
|
||||
|
||||
2
drivers/mfd/rt5025-debug.c
Executable file → Normal file
2
drivers/mfd/rt5025-debug.c
Executable file → Normal file
@@ -177,7 +177,7 @@ static int __init rt5025_debug_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_debug_driver);
|
||||
}
|
||||
subsys_initcall_sync(rt5025_debug_init);
|
||||
module_init(rt5025_debug_init);
|
||||
|
||||
static void __exit rt5025_debug_exit(void)
|
||||
{
|
||||
|
||||
197
drivers/mfd/rt5025-i2c.c
Executable file → Normal file
197
drivers/mfd/rt5025-i2c.c
Executable file → Normal file
@@ -16,9 +16,27 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/rt5025.h>
|
||||
|
||||
#define ROCKCHIP_I2C_RATE (200*1000)
|
||||
|
||||
static inline int rt5025_read_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
#if 1
|
||||
int ret;
|
||||
unsigned char reg_addr = reg;
|
||||
struct i2c_msg i2c_msg[2];
|
||||
i2c_msg[0].addr = i2c->addr;
|
||||
i2c_msg[0].flags = i2c->flags;
|
||||
i2c_msg[0].len = 1;
|
||||
i2c_msg[0].buf = ®_addr;
|
||||
i2c_msg[0].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
i2c_msg[1].addr = i2c->addr;
|
||||
i2c_msg[1].flags = i2c->flags | I2C_M_RD;
|
||||
i2c_msg[1].len = bytes;
|
||||
i2c_msg[1].buf = dest;
|
||||
i2c_msg[1].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, i2c_msg, 2);
|
||||
#else
|
||||
int ret;
|
||||
if (bytes > 1)
|
||||
ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
|
||||
@@ -28,7 +46,7 @@ static inline int rt5025_read_device(struct i2c_client *i2c,
|
||||
return ret;
|
||||
*(unsigned char *)dest = (unsigned char)ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,17 +56,75 @@ int rt5025_reg_block_read(struct i2c_client *i2c, \
|
||||
return rt5025_read_device(i2c, reg, bytes, dest);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_block_read);
|
||||
#if 0
|
||||
|
||||
static inline int rt5025_write_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
#if 1
|
||||
int ret;
|
||||
struct i2c_msg i2c_msg;
|
||||
char *tx_buf = (char*)kmalloc(bytes+1, GFP_KERNEL);
|
||||
tx_buf[0] = reg;
|
||||
memcpy(tx_buf+1, dest, bytes);
|
||||
i2c_msg.addr = i2c->addr;
|
||||
i2c_msg.flags = i2c->flags;
|
||||
i2c_msg.len = bytes + 1;
|
||||
i2c_msg.buf = tx_buf;
|
||||
i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
|
||||
kfree(tx_buf);
|
||||
#else
|
||||
int ret;
|
||||
if (bytes > 1)
|
||||
ret = i2c_smbus_write_i2c_block_data(i2c, reg, bytes, dest);
|
||||
else {
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, dest);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(unsigned char *)dest = (unsigned char)ret;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rt5025_reg_block_write(struct i2c_client *i2c, \
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
return rt5025_write_device(i2c, reg, bytes, dest);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_block_write);
|
||||
|
||||
int rt5025_reg_read(struct i2c_client *i2c, int reg)
|
||||
{
|
||||
struct rt5025_chip* chip = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
#if 1
|
||||
unsigned char reg_addr = reg;
|
||||
unsigned char reg_data = 0;
|
||||
struct i2c_msg i2c_msg[2];
|
||||
RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg);
|
||||
mutex_lock(&chip->io_lock);
|
||||
i2c_msg[0].addr = i2c->addr;
|
||||
i2c_msg[0].flags = i2c->flags;
|
||||
i2c_msg[0].len = 1;
|
||||
i2c_msg[0].buf = ®_addr;
|
||||
i2c_msg[0].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
i2c_msg[1].addr = i2c->addr;
|
||||
i2c_msg[1].flags = i2c->flags | I2C_M_RD;
|
||||
i2c_msg[1].len = 1;
|
||||
i2c_msg[1].buf = ®_data;
|
||||
i2c_msg[1].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, i2c_msg, 2);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
#else
|
||||
RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg);
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = i2c_smbus_read_byte_data(i2c, reg);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
return ret;
|
||||
#endif
|
||||
return reg_data;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_read);
|
||||
|
||||
@@ -56,88 +132,58 @@ int rt5025_reg_write(struct i2c_client *i2c, int reg, unsigned char data)
|
||||
{
|
||||
struct rt5025_chip* chip = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
printk("%s,line=%d\n", __func__,__LINE__);
|
||||
|
||||
// RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
|
||||
// (unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
|
||||
#if 1
|
||||
unsigned char xfer_data[2];
|
||||
struct i2c_msg i2c_msg;
|
||||
RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
|
||||
xfer_data[0] = reg;
|
||||
xfer_data[1] = data;
|
||||
mutex_lock(&chip->io_lock);
|
||||
i2c_msg.addr = i2c->addr;
|
||||
i2c_msg.flags = i2c->flags;
|
||||
i2c_msg.len = 2;
|
||||
i2c_msg.buf = xfer_data;
|
||||
i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
#else
|
||||
RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
|
||||
mutex_lock(&chip->io_lock);
|
||||
printk("%s,line=%d \n", __func__,__LINE__);
|
||||
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, data);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
printk("%s,line=%d %d \n", __func__,__LINE__,ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_write);
|
||||
#else
|
||||
int rt5025_reg_read(struct i2c_client *i2c, int reg)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_msg msgs[2];
|
||||
int ret;
|
||||
unsigned char *dest;
|
||||
u8 val;
|
||||
|
||||
dest = &val;
|
||||
|
||||
if(!i2c)
|
||||
return ret;
|
||||
|
||||
adap = i2c->adapter;
|
||||
|
||||
msgs[0].addr = i2c->addr;
|
||||
msgs[0].buf = ®
|
||||
msgs[0].flags = i2c->flags;
|
||||
msgs[0].len = 1;
|
||||
msgs[0].scl_rate = 200*1000;
|
||||
|
||||
msgs[1].buf = dest;
|
||||
msgs[1].addr = i2c->addr;
|
||||
msgs[1].flags = i2c->flags | I2C_M_RD;
|
||||
msgs[1].len = 1;
|
||||
msgs[1].scl_rate = 200*1000;
|
||||
ret = i2c_transfer(adap, msgs, 2);
|
||||
|
||||
// printk("***run in %s %d msgs[1].buf = %d\n",__FUNCTION__,__LINE__,*(msgs[1].buf));
|
||||
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_read);
|
||||
|
||||
int rt5025_reg_write(struct i2c_client *i2c, int reg, unsigned char data)
|
||||
{
|
||||
|
||||
int ret=-1;
|
||||
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_msg msg;
|
||||
char tx_buf[2];
|
||||
|
||||
if(!i2c)
|
||||
return ret;
|
||||
|
||||
adap = i2c->adapter;
|
||||
tx_buf[0] = reg;
|
||||
tx_buf[1] = data;
|
||||
|
||||
msg.addr = i2c->addr;
|
||||
msg.buf = &tx_buf[0];
|
||||
msg.len = 1 +1;
|
||||
msg.flags = i2c->flags;
|
||||
msg.scl_rate = 200*1000;
|
||||
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_write);
|
||||
#endif
|
||||
int rt5025_assign_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask, unsigned char data)
|
||||
{
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(i2c);
|
||||
unsigned char value;
|
||||
int ret;
|
||||
#if 1
|
||||
struct i2c_msg i2c_msg;
|
||||
u8 xfer_data[2] = {0};
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = rt5025_read_device(i2c, reg, 1, &value);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
value &= ~mask;
|
||||
value |= (data&mask);
|
||||
xfer_data[0] = reg;
|
||||
xfer_data[1] = value;
|
||||
i2c_msg.addr = i2c->addr;
|
||||
i2c_msg.flags = i2c->flags;
|
||||
i2c_msg.len = 2;
|
||||
i2c_msg.buf = xfer_data;
|
||||
i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
|
||||
#else
|
||||
mutex_lock(&chip->io_lock);
|
||||
|
||||
ret = rt5025_read_device(i2c, reg, 1, &value);
|
||||
@@ -146,7 +192,8 @@ int rt5025_assign_bits(struct i2c_client *i2c, int reg,
|
||||
goto out;
|
||||
value &= ~mask;
|
||||
value |= (data&mask);
|
||||
ret = rt5025_reg_write(i2c,reg,value);
|
||||
ret = i2c_smbus_write_byte_data(i2c,reg,value);
|
||||
#endif
|
||||
out:
|
||||
mutex_unlock(&chip->io_lock);
|
||||
return ret;
|
||||
@@ -198,8 +245,8 @@ static int __devinit rt5025_i2c_probe(struct i2c_client *client, const struct i2
|
||||
|
||||
rt5025_read_device(client,0x00,1,&val);
|
||||
if (val != 0x81){
|
||||
printk("The PMIC is not RT5025\n");
|
||||
return 0;
|
||||
printk("The PMIC is not RT5025\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = rt5025_core_init(chip, pdata);
|
||||
if (ret < 0)
|
||||
@@ -231,7 +278,7 @@ static int __devexit rt5025_i2c_remove(struct i2c_client *client)
|
||||
rt5025_core_deinit(chip);
|
||||
#if 0
|
||||
if (chip->event_callback)
|
||||
kfree(chip->event_callback);a
|
||||
kfree(chip->event_callback);
|
||||
#endif
|
||||
kfree(chip);
|
||||
return 0;
|
||||
|
||||
35
drivers/mfd/rt5025-irq.c
Executable file → Normal file
35
drivers/mfd/rt5025-irq.c
Executable file → Normal file
@@ -43,8 +43,21 @@ static void rt5025_work_func(struct work_struct *work)
|
||||
unsigned char irq_stat[10] = {0};
|
||||
uint32_t chg_event = 0, pwr_event = 0;
|
||||
|
||||
if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
if (!ii->chip->power_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)
|
||||
{
|
||||
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]);
|
||||
RTINFO("stat value = %02x\n", rt5025_reg_read(ii->i2c, RT5025_REG_CHGSTAT));
|
||||
@@ -63,33 +76,37 @@ static void rt5025_work_func(struct work_struct *work)
|
||||
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);
|
||||
#endif /* CONFIG_POWER_RT5025 */
|
||||
|
||||
enable_irq(ii->irq);
|
||||
//enable_irq(ii->irq);
|
||||
}
|
||||
|
||||
static irqreturn_t rt5025_interrupt(int irqno, void *param)
|
||||
{
|
||||
struct rt5025_irq_info *ii = (struct rt5025_irq_info *)param;
|
||||
|
||||
disable_irq_nosync(ii->irq);
|
||||
//disable_irq_nosync(ii->irq);
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit rt5025_interrupt_init(struct rt5025_irq_info* ii)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
RTINFO("\n");
|
||||
ii->wq = create_workqueue("rt5025_wq");
|
||||
INIT_DELAYED_WORK(&ii->delayed_work, rt5025_work_func);
|
||||
|
||||
#if 0
|
||||
if (gpio_is_valid(ii->intr_pin))
|
||||
{
|
||||
ret = gpio_request(ii->intr_pin, "rt5025_interrupt");
|
||||
@@ -99,6 +116,7 @@ static int __devinit rt5025_interrupt_init(struct rt5025_irq_info* ii)
|
||||
ret = gpio_direction_input(ii->intr_pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
if (request_irq(ii->irq, rt5025_interrupt, IRQ_TYPE_EDGE_FALLING|IRQF_DISABLED, "RT5025_IRQ", ii))
|
||||
{
|
||||
@@ -106,17 +124,20 @@ static int __devinit rt5025_interrupt_init(struct rt5025_irq_info* ii)
|
||||
return -EINVAL;
|
||||
}
|
||||
enable_irq_wake(ii->irq);
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(100));
|
||||
#if 0
|
||||
|
||||
if (!gpio_get_value(ii->intr_pin))
|
||||
{
|
||||
disable_irq_nosync(ii->irq);
|
||||
//disable_irq_nosync(ii->irq);
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit rt5025_interrupt_deinit(struct rt5025_irq_info* ii)
|
||||
@@ -160,7 +181,7 @@ static int __devinit rt5025_irq_probe(struct platform_device *pdev)
|
||||
ii->dev = &pdev->dev;
|
||||
ii->chip = chip;
|
||||
ii->intr_pin = pdata->intr_pin;
|
||||
ii->irq = gpio_to_irq(pdata->intr_pin);
|
||||
ii->irq = chip->irq;//gpio_to_irq(pdata->intr_pin);
|
||||
if (pdata->cb)
|
||||
ii->event_cb = pdata->cb;
|
||||
|
||||
|
||||
271
drivers/power/rt5025-gauge.c
Executable file → Normal file
271
drivers/power/rt5025-gauge.c
Executable file → Normal file
@@ -116,11 +116,23 @@ struct rt5025_gauge_chip {
|
||||
/* charge coulomb counter */
|
||||
u32 chg_cc;
|
||||
u32 chg_cc_unuse;
|
||||
//u32 chg_cc_raw; // JY: May not necessary
|
||||
/* discharge coulomb counter */
|
||||
u32 dchg_cc;
|
||||
u32 dchg_cc_unuse;
|
||||
//u32 dchg_cc_raw; // JY: May not necessary
|
||||
|
||||
// JY add variable
|
||||
bool soc_init;
|
||||
u32 rm;
|
||||
u32 rm_old;
|
||||
u8 soc_old;
|
||||
// ---------------
|
||||
|
||||
u32 fcc;
|
||||
/* battery capacity */
|
||||
u8 soc;
|
||||
u32 soc_precise;
|
||||
u16 time_interval;
|
||||
u16 pre_gauge_timer;
|
||||
|
||||
@@ -147,6 +159,9 @@ struct rt5025_gauge_chip {
|
||||
u8 temp_recover_cnt;
|
||||
};
|
||||
|
||||
static u32 battery_vcell_table[] = {3000, 3418, 3598, 3650, 3679, 3722, 3766, 3790, 3826, 3914, 3973, 4046, 4130, 4190};
|
||||
static u32 battery_soc_table[] = {0, 2, 5, 7, 14, 24, 40, 49, 58, 71, 80, 89, 98, 100};
|
||||
|
||||
struct rt5025_gauge_chip *chip;
|
||||
u8 irq_thres[LAST_TYPE];
|
||||
|
||||
@@ -155,13 +170,95 @@ void rt5025_set_status(int status)
|
||||
chip->status = status;
|
||||
}
|
||||
|
||||
static int get_vcell_segment_index(u32* pX, size_t size, u32 x)
|
||||
{
|
||||
unsigned int i;
|
||||
if (x <= *pX)
|
||||
return 0;
|
||||
for (i=0; i<size; i++)
|
||||
{
|
||||
if (x<=*(pX+i))
|
||||
break;
|
||||
}
|
||||
#if 0 // for linear interpolation
|
||||
#else
|
||||
if (i>=(size-2))
|
||||
return size-3;
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
static u32 rt5025_vcell2soc(u32* pX, u32* pY, size_t size, u32 _x)
|
||||
{
|
||||
#if 0 // Linear interpolation
|
||||
int index;
|
||||
int x1, x2;
|
||||
int y, y1, y2;
|
||||
index = get_vcell_segment_index(pX, size, _x);
|
||||
if (_x<*pX)
|
||||
return 0;
|
||||
if (_x>=*(pX+size-1))
|
||||
return 100;
|
||||
if (_x == *(pX+index))
|
||||
return *(pY+index);
|
||||
x1 = *(pX+index-1);
|
||||
x2 = *(pX+index);
|
||||
y1 = *(pY+index-1);
|
||||
y2 = *(pY+index);
|
||||
|
||||
y = (_x-x1)*(y2-y1)*100/(x2-x1);
|
||||
y /= 100;
|
||||
y += y1;
|
||||
|
||||
return y;
|
||||
#else // Lagrange interpolation
|
||||
int index;
|
||||
int32_t x1, x2, x3;
|
||||
int32_t y1, y2, y3;
|
||||
int32_t a1, a2, a3, b1, b2, b3;
|
||||
int32_t x = _x;
|
||||
if (_x<*pX)
|
||||
return 0;
|
||||
if (_x>=*(pX+size-1))
|
||||
return 100;
|
||||
index = get_vcell_segment_index(pX, size, _x);
|
||||
pX+=index;
|
||||
pY+=index;
|
||||
x1 = *pX;
|
||||
x2 = *(pX+1);
|
||||
x3 = *(pX+2);
|
||||
y1 = *pY;
|
||||
y2 = *(pY+1);
|
||||
y3 = *(pY+2);
|
||||
if (x == x1)
|
||||
return y1;
|
||||
if (x == x2)
|
||||
return y2;
|
||||
if (x == x3)
|
||||
return y3;
|
||||
a1 = y1*(x-x2)*(x-x3);
|
||||
a2 = y2*(x-x1)*(x-x3);
|
||||
a3 = y3*(x-x1)*(x-x2);
|
||||
b1 = (x1-x2)*(x1-x3);
|
||||
b2 = (x2-x1)*(x2-x3);
|
||||
b3 = (x3-x1)*(x3-x2);
|
||||
|
||||
return (100*a1/b1+100*a2/b2+100*a3/b3)/100;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int rt5025_read_reg(struct i2c_client *client,
|
||||
u8 reg, u8 *data, u8 len)
|
||||
{
|
||||
#if 1
|
||||
int ret;
|
||||
|
||||
ret = rt5025_reg_block_read(client, reg, len, data);
|
||||
#else
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_msg msgs[2];
|
||||
int ret;
|
||||
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = client->flags;
|
||||
msgs[0].len = 1;
|
||||
@@ -173,37 +270,46 @@ static int rt5025_read_reg(struct i2c_client *client,
|
||||
msgs[1].len = len;
|
||||
msgs[1].buf = data;
|
||||
msgs[1].scl_rate = 200*1000;
|
||||
|
||||
|
||||
ret = i2c_transfer(adap, msgs, 2);
|
||||
|
||||
#endif
|
||||
return (ret == 2)? len : ret;
|
||||
}
|
||||
|
||||
static int rt5025_write_reg(struct i2c_client *client,
|
||||
u8 reg, u8 *data, u8 len)
|
||||
{
|
||||
#if 1
|
||||
int ret;
|
||||
|
||||
ret = rt5025_reg_block_write(client, reg, len, data);
|
||||
#else
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
||||
int ret;
|
||||
char *tx_buf = (char *)kmalloc(len + 1, GFP_KERNEL);
|
||||
|
||||
if(!tx_buf)
|
||||
char* tx_buf = (char *)kmalloc(len + 1, GFP_KERNEL);
|
||||
|
||||
if (!tx_buf)
|
||||
return -ENOMEM;
|
||||
tx_buf[0] = reg;
|
||||
memcpy(tx_buf+1, data, len);
|
||||
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags;
|
||||
msg.len = len + 1;
|
||||
msg.buf = (char *)tx_buf;
|
||||
msg.scl_rate = 200*1000;
|
||||
msg.scl_rate = 200*1000;
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
kfree(tx_buf);
|
||||
|
||||
#endif
|
||||
return (ret == 1) ? len : ret;
|
||||
}
|
||||
|
||||
static void rt5025_gauge_alarm(struct alarm *alarm)
|
||||
{
|
||||
pr_info("%s: alarmed \n", __func__);
|
||||
wake_lock(&chip->monitor_wake_lock);
|
||||
schedule_delayed_work(&chip->monitor_work, 0);
|
||||
}
|
||||
@@ -371,13 +477,26 @@ static void rt5025_get_chg_cc(struct i2c_client *client)
|
||||
}
|
||||
qh_old = (data[0]<<8) + data[1];
|
||||
ql_old = (data[2]<<8) + data[3];
|
||||
//pr_info("%s qh_old %04x ql_old %04x\n", __func__, qh_old, ql_old);
|
||||
|
||||
if (rt5025_read_reg(client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
|
||||
printk(KERN_ERR "%s: Failed to read QCHG\n", __func__);
|
||||
}
|
||||
qh_new = (data[0]<<8) + data[1];
|
||||
ql_new = (data[2]<<8) + data[3];
|
||||
|
||||
//pr_info("%s qh_new %04x ql_new %04x\n", __func__, qh_new, ql_new);
|
||||
|
||||
#if 0
|
||||
if (qh_new > qh_old){
|
||||
cc_masec = qh_new*91266 + ((ql_new*22)>>4);
|
||||
}else if (qh_new == qh_old){
|
||||
if (ql_new >= ql_old){
|
||||
cc_masec = qh_new*91266 + ((ql_new*22)>>4);
|
||||
}else {
|
||||
cc_masec = qh_old*91266 + ((ql_old*22)>>4);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (qh_new > qh_old){
|
||||
cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
|
||||
}else if (qh_new == qh_old){
|
||||
@@ -386,18 +505,28 @@ static void rt5025_get_chg_cc(struct i2c_client *client)
|
||||
}else {
|
||||
cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
offset = chip->curr_offset * chip->time_interval;
|
||||
|
||||
if (cc_masec != 0){
|
||||
#if 0
|
||||
cc_masec /= 1000;
|
||||
#else
|
||||
cc_masec = (cc_masec - offset) / 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
RTINFO("[RT5025] chg_cc_mAsec: %d\n", cc_masec);
|
||||
|
||||
#if 0
|
||||
chip->chg_cc = cc_masec;
|
||||
chip->chg_cc_unuse = 0;
|
||||
#else
|
||||
chip->chg_cc = (cc_masec + chip->chg_cc_unuse) / 3600;
|
||||
chip->chg_cc_unuse = (cc_masec + chip->chg_cc_unuse) % 3600;
|
||||
#endif
|
||||
RTINFO("[RT5025] chg_cc_mAH: %d\n", chip->chg_cc);
|
||||
rt5025_clear_cc(CHG);
|
||||
}
|
||||
@@ -413,13 +542,26 @@ static void rt5025_get_dchg_cc(struct i2c_client *client)
|
||||
}
|
||||
qh_old = (data[0]<<8) + data[1];
|
||||
ql_old = (data[2]<<8) + data[3];
|
||||
//pr_info("%s qh_old %04x ql_old %04x\n", __func__, qh_old, ql_old);
|
||||
|
||||
if (rt5025_read_reg(client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
|
||||
printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
|
||||
}
|
||||
qh_new = (data[0]<<8) + data[1];
|
||||
ql_new = (data[2]<<8) + data[3];
|
||||
|
||||
// pr_info("%s qh_new %04x ql_new %04x\n", __func__, qh_new, ql_new);
|
||||
|
||||
#if 0
|
||||
if (qh_new > qh_old){
|
||||
cc_masec = qh_new*91266 + ((ql_new*22)>>4);
|
||||
}else if (qh_new == qh_old){
|
||||
if (ql_new >= ql_old){
|
||||
cc_masec = qh_new*91266 + ((ql_new*22)>>4);
|
||||
}else {
|
||||
cc_masec = qh_old*91266 + ((ql_old*22)>>4);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (qh_new > qh_old){
|
||||
cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
|
||||
}else if (qh_new == qh_old){
|
||||
@@ -428,18 +570,28 @@ static void rt5025_get_dchg_cc(struct i2c_client *client)
|
||||
}else {
|
||||
cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
offset = chip->curr_offset * chip->time_interval;
|
||||
|
||||
if (cc_masec != 0){
|
||||
#if 0
|
||||
cc_masec /= 1000;
|
||||
#else
|
||||
cc_masec = (cc_masec - offset) / 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
RTINFO("[RT5025] dchg_cc_mAsec: %d\n", cc_masec);
|
||||
|
||||
#if 0
|
||||
chip->dchg_cc = cc_masec;
|
||||
chip->dchg_cc_unuse = 0;
|
||||
#else
|
||||
chip->dchg_cc = (cc_masec + chip->dchg_cc_unuse) / 3600;
|
||||
chip->dchg_cc_unuse = (cc_masec + chip->dchg_cc_unuse) % 3600;
|
||||
#endif
|
||||
RTINFO("[RT5025] dchg_cc_mAH: %d\n", chip->dchg_cc);
|
||||
rt5025_clear_cc(DCHG);
|
||||
}
|
||||
@@ -475,9 +627,95 @@ static void rt5025_get_timer(struct i2c_client *client)
|
||||
RTINFO("[RT5025] timer %d , interval %d\n", gauge_timer,chip->time_interval);
|
||||
}
|
||||
|
||||
static void rt5025_gauge_init_soc(struct i2c_client *client)
|
||||
{
|
||||
/* Update voltage */
|
||||
rt5025_get_vcell(client);
|
||||
/* Update current */
|
||||
rt5025_get_current(client);
|
||||
/* Update external temperature */
|
||||
rt5025_get_external_temp(client);
|
||||
// JY add
|
||||
if (chip->soc_init)
|
||||
{
|
||||
chip->soc = chip->soc_old;
|
||||
chip->rm = chip->rm_old;
|
||||
}
|
||||
else
|
||||
{
|
||||
chip->soc = rt5025_vcell2soc(battery_vcell_table, battery_soc_table, ARRAY_SIZE(battery_vcell_table), chip->vcell);
|
||||
chip->soc_precise = (u32)(chip->soc);
|
||||
chip->soc_init = true;
|
||||
chip->soc_old = chip->soc;
|
||||
chip->rm = (chip->soc *chip->fcc)/100;
|
||||
chip->rm_old = chip->rm;
|
||||
}
|
||||
// ----------------
|
||||
/*
|
||||
chip->soc = rt5025_vcell2soc(battery_vcell_table, battery_soc_table, ARRAY_SIZE(battery_vcell_table), chip->vcell);
|
||||
chip->soc_precise = (u32)(chip->soc);
|
||||
*/
|
||||
pr_info("%s: vcell = %d, soc = %d\n", __func__, chip->vcell, chip->soc);
|
||||
/* upsampling (extend more 12 bits)*/
|
||||
}
|
||||
|
||||
static void rt5025_get_soc(struct i2c_client *client)
|
||||
{
|
||||
chip->soc = 50;
|
||||
//fcc = full charged capacity (battery capacity)
|
||||
int chg_cc = chip->chg_cc;
|
||||
int dchg_cc = chip->dchg_cc;
|
||||
|
||||
// JY new implement
|
||||
chip->rm = chip->rm_old + (chg_cc - dchg_cc);
|
||||
if (chip->rm < 0)
|
||||
{
|
||||
chip->rm = 0;
|
||||
chip->chg_cc = 0;
|
||||
chip->dchg_cc = 0;
|
||||
}
|
||||
else if (chip->rm > chip->fcc)
|
||||
{
|
||||
chip->rm = chip->fcc;
|
||||
chip->chg_cc = chip->fcc;
|
||||
chip->dchg_cc = 0;
|
||||
}
|
||||
|
||||
chip->soc_precise = (chip->rm *100)/chip->fcc;
|
||||
|
||||
chip->soc = (chip->soc_precise);
|
||||
|
||||
if (chip->soc > chip->soc_old+1)
|
||||
{
|
||||
chip->soc = chip->soc_old + 1;
|
||||
}
|
||||
else if (chip->soc < chip->soc_old-1)
|
||||
{
|
||||
chip->soc = chip->soc_old -1;
|
||||
}
|
||||
|
||||
if (chip->soc < 0)
|
||||
chip->soc = 0;
|
||||
else if (chip->soc > 100)
|
||||
chip->soc = 100;
|
||||
|
||||
chip->rm_old = chip->rm;
|
||||
chip->soc_old = chip->soc;
|
||||
// --------------------
|
||||
|
||||
/* JY mark it
|
||||
|
||||
chip->soc_precise = chip->soc_precise + ((chg_cc-dchg_cc)*100)/chip->fcc;
|
||||
|
||||
pr_info("%s chg_cc = %d\n", __func__, chg_cc);
|
||||
pr_info("%s dchg_cc = %d\n", __func__, dchg_cc);
|
||||
pr_info("%s soc_precise = %d\n", __func__, chip->soc_precise);
|
||||
chip->soc = (chip->soc_precise);
|
||||
if (chip->soc < 0)
|
||||
chip->soc = 0;
|
||||
else if (chip->soc > 100)
|
||||
chip->soc = 100;
|
||||
*/
|
||||
//chip->soc = 50;
|
||||
}
|
||||
|
||||
static void rt5025_channel_cc(bool enable)
|
||||
@@ -775,7 +1013,13 @@ int rt5025_gauge_init(struct rt5025_power_info *info)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->client = info->i2c;
|
||||
chip->fcc = info->fcc;
|
||||
chip->info = info;
|
||||
// JY add
|
||||
chip->soc_init = false;
|
||||
chip->rm = chip->fcc/2;
|
||||
chip->rm_old = chip->rm;
|
||||
// ------------
|
||||
chip->battery.name = "rt5025-battery";
|
||||
chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
chip->battery.get_property = rt5025_get_property;
|
||||
@@ -798,6 +1042,7 @@ int rt5025_gauge_init(struct rt5025_power_info *info)
|
||||
"rt-battery-monitor");
|
||||
/* enable channel */
|
||||
rt5025_register_init(info->i2c);
|
||||
rt5025_gauge_init_soc(info->i2c);
|
||||
|
||||
/* enable gauge IRQ */
|
||||
rt5025_alert_init(info->i2c);
|
||||
|
||||
91
drivers/power/rt5025-power.c
Executable file → Normal file
91
drivers/power/rt5025-power.c
Executable file → Normal file
@@ -19,6 +19,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mfd/rt5025.h>
|
||||
#include <linux/power/rt5025-power.h>
|
||||
#include <linux/power/rt5025-gauge.h>
|
||||
@@ -33,6 +34,7 @@ static char *rt5025_supply_list[] = {
|
||||
"rt5025-battery",
|
||||
};
|
||||
|
||||
#if 0
|
||||
static int rt5025_set_charging_current_switch (struct i2c_client *i2c, int onoff)
|
||||
{
|
||||
int ret;
|
||||
@@ -52,6 +54,34 @@ static int rt5025_set_charging_buck(struct i2c_client *i2c, int onoff)
|
||||
ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 data = 0;
|
||||
|
||||
//ICC Setting
|
||||
if (cur_value > 2000)
|
||||
data |= 0x0f<<3;
|
||||
else if (cur_value >= 500 && cur_value <= 2000)
|
||||
{
|
||||
data = (cur_value-500)/100;
|
||||
data<<=3;
|
||||
}
|
||||
|
||||
|
||||
//AICR Setting
|
||||
if (cur_value > 1000)
|
||||
data |= 0x03<<1;
|
||||
else if (cur_value > 500 && cur_value <= 1000)
|
||||
data |= 0x02<<1;
|
||||
else if (cur_value > 100 && cur_value >= 500)
|
||||
data |= 0x01<<1;
|
||||
|
||||
rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGCC_MASK, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_val)
|
||||
{
|
||||
@@ -59,8 +89,10 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
|
||||
switch (new_val)
|
||||
{
|
||||
case 0x00:
|
||||
#if 0
|
||||
rt5025_set_charging_current_switch(info->i2c, 1);
|
||||
rt5025_set_charging_buck(info->i2c, 1);
|
||||
#endif
|
||||
info->chg_stat = 0x00;
|
||||
if (info->event_callback)
|
||||
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
|
||||
@@ -72,14 +104,18 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
|
||||
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
|
||||
break;
|
||||
case 0x02:
|
||||
#if 0
|
||||
rt5025_set_charging_current_switch(info->i2c, 0);
|
||||
#endif
|
||||
info->chg_stat = 0x02;
|
||||
if (info->event_callback)
|
||||
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_FULL);
|
||||
break;
|
||||
case 0x03:
|
||||
#if 0
|
||||
rt5025_set_charging_buck(info->i2c, 0);
|
||||
rt5025_set_charging_current_switch(info->i2c, 0);
|
||||
#endif
|
||||
info->chg_stat = 0x03;
|
||||
if (info->event_callback)
|
||||
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
|
||||
@@ -129,6 +165,9 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
|
||||
power_supply_changed(&info->usb);
|
||||
}
|
||||
|
||||
if (old_acval != new_acval || old_usbval != new_usbval)
|
||||
schedule_delayed_work(&info->usb_detect_work, 0); //no delay
|
||||
|
||||
new_chgval = (chgstatval&RT5025_CHGSTAT_MASK)>>RT5025_CHGSTAT_SHIFT;
|
||||
if (new_acval || new_usbval)
|
||||
{
|
||||
@@ -139,8 +178,10 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
rt5025_set_charging_buck(info->i2c, 0);
|
||||
rt5025_set_charging_current_switch(info->i2c, 0);
|
||||
#endif
|
||||
info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
|
||||
if (info->event_callback)
|
||||
info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
|
||||
@@ -171,8 +212,54 @@ 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);
|
||||
struct rt5025_power_info *pi = (struct rt5025_power_info *)container_of(delayed_work, struct rt5025_power_info, usb_detect_work);
|
||||
|
||||
pr_info("rt5025: %s ++", __func__);
|
||||
|
||||
mutex_lock(&pi->var_lock);
|
||||
if (pi->ac_online)
|
||||
{
|
||||
rt5025_set_charging_current(pi->i2c, 1000);
|
||||
pi->usb_cnt = 0;
|
||||
}
|
||||
else if (pi->usb_online)
|
||||
{
|
||||
pr_info("%s: usb_cnt %d\n", __func__, pi->usb_cnt);
|
||||
switch(dwc_vbus_status())
|
||||
{
|
||||
case 2: // USB Wall charger
|
||||
rt5025_set_charging_current(pi->i2c, 1000);
|
||||
pr_info("rt5025: detect usb wall charger\n");
|
||||
break;
|
||||
case 1: //normal USB
|
||||
default:
|
||||
rt5025_set_charging_current(pi->i2c, 500);
|
||||
pr_info("rt5025: detect normal usb\n");
|
||||
break;
|
||||
}
|
||||
if (pi->usb_cnt++ < 60)
|
||||
schedule_delayed_work(&pi->usb_detect_work, 1*HZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
//default to prevent over current charging
|
||||
rt5025_set_charging_current(pi->i2c, 500);
|
||||
//reset usb_cnt;
|
||||
pi->usb_cnt = 0;
|
||||
}
|
||||
mutex_unlock(&pi->var_lock);
|
||||
|
||||
pr_info("rt5025: %s --", __func__);
|
||||
}
|
||||
|
||||
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
|
||||
@@ -191,6 +278,7 @@ static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct
|
||||
|
||||
rt5025_power_charge_detect(info);
|
||||
|
||||
RTINFO("--\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -208,6 +296,9 @@ static int __devinit rt5025_power_probe(struct platform_device *pdev)
|
||||
|
||||
pi->i2c = chip->i2c;
|
||||
pi->dev = &pdev->dev;
|
||||
pi->fcc = pdata->power_data->fcc;
|
||||
mutex_init(&pi->var_lock);
|
||||
INIT_DELAYED_WORK(&pi->usb_detect_work, usb_detect_work_func);
|
||||
|
||||
ret = rt5025_gauge_init(pi);
|
||||
if (ret)
|
||||
|
||||
@@ -181,7 +181,7 @@ struct rt5025_power_data {
|
||||
}CHGControl3;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv:1;
|
||||
unsigned char AICR_CON:1;
|
||||
unsigned char AICR:2;
|
||||
unsigned char ICC:4;
|
||||
unsigned char CHG_RST:1;
|
||||
@@ -215,6 +215,7 @@ struct rt5025_power_data {
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl7;
|
||||
u32 fcc;
|
||||
};
|
||||
|
||||
struct rt5025_gpio_data {
|
||||
@@ -398,6 +399,10 @@ struct rt5025_power_info {
|
||||
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;
|
||||
@@ -438,6 +443,7 @@ extern int rt5025_power_charge_detect(struct rt5025_power_info *);
|
||||
#endif /* CONFIG_POEWR_RT5025 */
|
||||
|
||||
extern int rt5025_reg_block_read(struct i2c_client *, int, int, void *);
|
||||
extern int rt5025_reg_block_write(struct i2c_client *, int, int, void *);
|
||||
extern int rt5025_reg_read(struct i2c_client *, int);
|
||||
extern int rt5025_reg_write(struct i2c_client *, int, unsigned char);
|
||||
extern int rt5025_assign_bits(struct i2c_client *, int, unsigned char, unsigned char);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define RT5025_CHGBUCKEN_MASK 0x02
|
||||
#define RT5025_CHGCEN_MASK 0x10
|
||||
#define RT5025_CHGCC_MASK 0x7E
|
||||
|
||||
#define RT5025_CHGSTAT_MASK 0x30
|
||||
#define RT5025_CHGSTAT_SHIFT 4
|
||||
|
||||
Reference in New Issue
Block a user