Merge "[Feature][R305][task-view-1918] add charger code for V4"
diff --git a/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c b/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
index 59504bb..baf731e 100755
--- a/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
+++ b/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
@@ -1336,6 +1336,17 @@
{3530,12}, {3590,10}, {3450,5}
};
+struct sgm41513_charge_current_limit zx234502_charger_temp_current[] =
+{
+ //grade above below current voltage_limit
+ {POWER_SUPPLY_HEALTH_UNKNOWN, 1700, -1, 0, -1}, //ntc offline
+ {POWER_SUPPLY_HEALTH_COLD, 1273, 1700, 0, -1},
+ {POWER_SUPPLY_HEALTH_COOL, 1057, 1273, 900, -1},
+ {POWER_SUPPLY_HEALTH_GOOD, 623, 1057, 1740, -1},
+ {POWER_SUPPLY_HEALTH_WARM, 434, 623, 840, -1},
+ {POWER_SUPPLY_HEALTH_OVERHEAT, -1, 434, 0, -1}
+};
+
static struct sgm41513_platform_data sgm41513_charger_platform = {
.gpio_int = PIN_CHARGE_INT, //gpio55
.gpio_int_fun_sel = CHARGE_INT_FUNC_SEL,
@@ -1343,6 +1354,12 @@
.charging_size = SGM41513_BAT_VOLTAGE_LEN,
.discharging = &sgm41513_bat_volage_discharge,
.discharging_size = SGM41513_BAT_VOLTAGE_LEN,
+ .temp_current_map = &zx234502_charger_temp_current,
+ .temp_current_map_size = ARRAY_SIZE(zx234502_charger_temp_current),
+ .max_charge_voltage = 4400,
+ .max_input_current = 2300,
+ .pre_charge_current = 110,
+ .terminate_charge_current = 110,
.ts_flag = FALSE,
.boost_flag = TRUE,
};
diff --git a/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c b/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
index 795a832..45428c6 100755
--- a/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
+++ b/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
@@ -34,13 +34,36 @@
#include <linux/debugfs.h>
#include <asm/uaccess.h>
+#define OUT_5V_GPIO ZX29_GPIO_119
+#define DCIN_5V_GPIO ZX29_GPIO_125
+#define DCIN_5V_GPIO_FUNC_GPIO GPIO125_GPIO125
+#define DCIN_5V_GPIO_FUNC_EXT_INT GPIO125_EXT_INT14
+#define DCIN_5V_DT_INT PCU_EX14_INT
+
+#define CHG_PLUG_IN GPIO_LOW
+#define CHG_PLUG_OUT GPIO_HIGH
+
#define DBG_CHARGE 1
+
+#define CHANGE_ROLE_VOTAGE 3600
//*
extern int get_typec_role(void);
extern set_typec_try_role(int type);
//*/
+enum type_usb_detect_stage
+{
+ USB_STATUS_UNKOWN = 0,
+ USB_STATUS_DETECTING,
+ USB_STATUS_CONNECTED,
+ USB_STATUS_DISCONNECTING,
+ USB_STATUS_DISCONNECTED
+};
+
static int ce_enabled = 0;
+//const int green_voltage_level = 3650;
+//const int red_voltage_level = 3510;
+
/*
* The FAULT register is latched by the sgm41513 (except for NTC_FAULT)
* so the first read after a fault returns the latched value and subsequent
@@ -61,17 +84,31 @@
kernel_ulong_t model;
unsigned int gpio_int;
unsigned int irq;
+ unsigned int chgin_irq;
struct mutex bs_reg_lock;
bool first_time; /*let the first reset do not ask mmi*/
bool charger_health_valid;
bool battery_health_valid;
bool battery_status_valid;
+ bool dcin_5v_pulgin_flag;
+ volatile int current_charging_flag;
+ volatile int last_reported_charging_flag;
+ volatile int during_voltage_query_flag;
+ volatile bool discharging_flag;
+ enum type_usb_detect_stage usb_detect_flag;
+ volatile bool power_role_switch_only;
+ volatile int dwc_otg_chg_inform_status;
+ volatile bool can_switch_role_flag;
+ bool battery_online_flag;
+ unsigned int usb_plug_in_out_check_cnt;
+ u8 reg08;
u8 reg09;
u8 cbis_curr_reg;
u8 pis_curr_reg;
u8 cfis_curr_reg;
u8 ciis_pre_reg;
+ u8 pre_reg08;
u8 pre_reg09;
u8 pis_pre_reg;
u8 cfis_pre_reg;
@@ -79,6 +116,7 @@
u8 boost_online_flag;
struct delayed_work boostWorkStruct ;
struct delayed_work charge_monitor_work;
+ volatile bool charge_monitor_work_running_flag;
struct workqueue_struct *boostQueue;
struct semaphore chgirq_sem;
struct task_struct *chg_irq_thread;
@@ -91,46 +129,22 @@
//struct sgm41513_platform_data *g_platform_data = NULL;
struct sgm41513_dev_info *g_bdi = NULL;
-/* REG01[2:0] (ISET_DCIN) in mAh */
-static const int sgm41513_in_ilimit_values[] = {
- 150, 450, 850, 1000, 1500, 2000, 2500, 3000
-};
-/* REG01[6:3] (VINDPM) in mVh */
-static const int sgm41513_vindpm_values[] = {
- 3880, 3960, 4040, 4120,
- 4200,4280, 4360, 4440,
- 4520,4600, 4680, 4760,
- 4840,4920, 5000, 5080,
-};
-
/*
- * The tables below provide a 2-way mapping for the value that goes in
- * the register field and the real-world value that it represents.
- * The index of the array is the value that goes in the register; the
- * number at that index in the array is the real-world value that it
- * represents.
- */
-/* REG02[7:2] (ISETA) in mAh */
-static const int sgm41513_isc_ichg_values[] = {
- 512, 576, 640, 704, 768, 832, 896, 960,
- 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472,
- 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984,
- 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496,
- 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008,
- 3072, 3136, 3200, 3264, 3328, 3392, 3456, 3520,
- 3584, 3648, 3712, 3776, 3840, 3904, 3968, 4032,
- 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544
-};
+static int g_last_real_voltage = 0;
+int can_cc_hardreset(void) {
+ int ret;
+ if (g_bdi == NULL)
+ return 0;
+ if (g_bdi->charger.type == POWER_SUPPLY_PCAC__AC)
+ ret = g_last_real_voltage > red_voltage_level;
+ else
+ ret = ce_enabled == 0 ? (get_adc1_voltage() > red_voltage_level) : (g_last_real_voltage > red_voltage_level);
+
+ printk("cy: can_cc_hardreset %d, g_last_real_voltage %d, voltage %d\n", ret, g_last_real_voltage, get_adc1_voltage());
+ return ret;
+}
+*/
-/* REG04[3:1] (VSETA) in mV */
-static const int sgm41513_cvc_vseta_values[] = {
- 4100, 4150, 4200, 4250, 4300, 4350, 4400, 4450,
-};
-
-/* REG02[7:5] (VSYS_MIN) in mV */
-static const int sgm41513_vsc_sysmin_values[] = {
- 3100, 3200, 3300, 3400, 3500, 3600, 3700,3800
-};
static int stopchg_flag = 0;
/*
* Return the index in 'tbl' of greatest value that is less than or equal to
@@ -232,211 +246,12 @@
return sgm41513_write_mask(bdi, reg, mask, shift, idx);
}
-//#ifdef CONFIG_SYSFS
-#if 0
-/*
- * There are a numerous options that are configurable on the sgm41513
- * that go well beyond what the power_supply properties provide access to.
- * Provide sysfs access to them so they can be examined and possibly modified
- * on the fly. They will be provided for the charger power_supply object only
- * and will be prefixed by 'f_' to make them easier to recognize.
- */
-
-struct sgm41513_sysfs_field_info {
- struct device_attribute attr;
- u8 reg;
- u8 mask;
- u8 shift;
-};
-
-
-#define SGM41513_SYSFS_FIELD(_name, r, f, m, store) \
-{ \
- .attr = __ATTR(f_##_name, m, sgm41513_sysfs_show, store), \
- .reg = SGM41513_REG_##r, \
- .mask = SGM41513_REG_##r##_##f##_MASK, \
- .shift = SGM41513_REG_##r##_##f##_SHIFT, \
-}
-
-#define SGM41513_SYSFS_FIELD_RW(_name, r, f) \
- SGM41513_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO, \
- sgm41513_sysfs_store)
-
-#define SGM41513_SYSFS_FIELD_RO(_name, r, f) \
- SGM41513_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)
-
-static ssize_t sgm41513_sysfs_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-static ssize_t sgm41513_sysfs_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-
-/* On i386 ptrace-abi.h defines SS that breaks the macro calls below. */
-//#undef SS
-
-static struct sgm41513_sysfs_field_info sgm41513_sysfs_field_tbl[] = {
- /* sysfs name reg field in reg */
- SGM41513_SYSFS_FIELD_RW(chg_reset, MS, CHGRST),
- SGM41513_SYSFS_FIELD_RW(pmuon, MS, PMUON),
- SGM41513_SYSFS_FIELD_RW(en_ship, MS, ENSHIP),
- SGM41513_SYSFS_FIELD_RW(en_otg, MS, ENOTG),
- SGM41513_SYSFS_FIELD_RW(chg_config, MS, ENCHG),
- SGM41513_SYSFS_FIELD_RW(en_powerbank, MS, PWRBNK),
- SGM41513_SYSFS_FIELD_RW(insus, MS, INSUS),
- SGM41513_SYSFS_FIELD_RW(in_limit, ISC, ISET_DCIN),
- SGM41513_SYSFS_FIELD_RW(vsys_min, VSC, VSYS_MIN),
- SGM41513_SYSFS_FIELD_RW(ichg, CCC, ISETA),
- SGM41513_SYSFS_FIELD_RW(force_ichg_50pct, CCC, ICHG_50PCT),
- SGM41513_SYSFS_FIELD_RW(iprechg, CVC, IPRECHG),
- SGM41513_SYSFS_FIELD_RW(vbat_full, CVC, VBAT),
- SGM41513_SYSFS_FIELD_RW(vpre_to_fast, CVC, VBATFC),
- SGM41513_SYSFS_FIELD_RW(en_timer, CTC, EN_TIMER),
- SGM41513_SYSFS_FIELD_RW(en_2timer, CTC, EN_2XTIMER),
- SGM41513_SYSFS_FIELD_RW(stopchg_flag, OTGC, OTGV),
- SGM41513_SYSFS_FIELD_RW(iotg_limit, OTGC, OTGI_LIM),
- SGM41513_SYSFS_FIELD_RW(ents_otg, OTGC, ENTS_OTG),
- SGM41513_SYSFS_FIELD_RO(en_therm, THR, EN_THERM),
- SGM41513_SYSFS_FIELD_RW(therm_threshold, THR, THERM_THLD),
- SGM41513_SYSFS_FIELD_RW(en_2det, THR, EN_2DET),
- SGM41513_SYSFS_FIELD_RW(en_1det, THR, EN_1DET),
- SGM41513_SYSFS_FIELD_RW(en_jeita, THR, EN_JEITA),
- SGM41513_SYSFS_FIELD_RW(en_ilimitdj, THR, EN_ILIMITDJ),
- SGM41513_SYSFS_FIELD_RW(tscold, TS, COLD),
- SGM41513_SYSFS_FIELD_RW(tscool, TS, COOL),
- SGM41513_SYSFS_FIELD_RW(tswarm, TS, WARM),
- SGM41513_SYSFS_FIELD_RW(tshot, TS, HOT),
- SGM41513_SYSFS_FIELD_RW(ntcdet, PTS,NTCDET),
- SGM41513_SYSFS_FIELD_RW(int_clear, CIIS, INT),
- SGM41513_SYSFS_FIELD_RO(ciis_reg, CIIS, ALL),
- SGM41513_SYSFS_FIELD_RW(mask_chgrun, CIIM, MASK_CHGRUN),
- SGM41513_SYSFS_FIELD_RW(mask_inlimit, CIIM, MASK_INLIMIT),
- SGM41513_SYSFS_FIELD_RW(mask_thr, CIIM, MASK_THR),
- SGM41513_SYSFS_FIELD_RW(mask_ts, CIIM, MASK_TS),
- SGM41513_SYSFS_FIELD_RW(mask_dcdet, CIIM, MASK_DCDET),
- SGM41513_SYSFS_FIELD_RO(cbis_reg, CBIS, ALL),
- SGM41513_SYSFS_FIELD_RW(mask_pg, CBIM, MASK_DCIN_PG),
- SGM41513_SYSFS_FIELD_RW(mask_batlow, CBIM, MASK_BATLOW),
- SGM41513_SYSFS_FIELD_RW(mask_nobat, CBIM, MASK_NOBAT),
- SGM41513_SYSFS_FIELD_RW(mask_eoc, CBIM, MASK_EOC),
- SGM41513_SYSFS_FIELD_RW(mask_timer, CBIM, MASK_SAFE_TIMER),
- SGM41513_SYSFS_FIELD_RW(mask_otg_fault, CBIM, MASK_OTG_FAULT),
- SGM41513_SYSFS_FIELD_RO(pis_reg, PIS, ALL),
- SGM41513_SYSFS_FIELD_RW(mask_pwron_it, PIM, MASK_POWERON_IT),
- SGM41513_SYSFS_FIELD_RW(mask_pwron_lp, PIM, MASK_POWERON_LP),
- SGM41513_SYSFS_FIELD_RO(cfis_reg, CFIS, ALL),
- SGM41513_SYSFS_FIELD_RO(version_info, VER, INFO),
-};
-
-static struct attribute *
- sgm41513_sysfs_attrs[ARRAY_SIZE(sgm41513_sysfs_field_tbl) + 1];
-
-static const struct attribute_group sgm41513_sysfs_attr_group = {
- .attrs = sgm41513_sysfs_attrs,
-};
-
-static void sgm41513_sysfs_init_attrs(void)
-{
- int i, limit = ARRAY_SIZE(sgm41513_sysfs_field_tbl);
-
- for (i = 0; i < limit; i++)
- sgm41513_sysfs_attrs[i] = &sgm41513_sysfs_field_tbl[i].attr.attr;
-
- sgm41513_sysfs_attrs[limit] = NULL; /* Has additional entry for this */
-}
-
-static struct sgm41513_sysfs_field_info *sgm41513_sysfs_field_lookup(
- const char *name)
-{
- int i, limit = ARRAY_SIZE(sgm41513_sysfs_field_tbl);
-
- for (i = 0; i < limit; i++)
- if (!strcmp(name, sgm41513_sysfs_field_tbl[i].attr.attr.name))
- break;
-
- if (i >= limit)
- return NULL;
-
- return &sgm41513_sysfs_field_tbl[i];
-}
-
-static ssize_t sgm41513_sysfs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct power_supply *psy = dev_get_drvdata(dev);
- struct sgm41513_dev_info *bdi =
- container_of(psy, struct sgm41513_dev_info, charger);
- struct sgm41513_sysfs_field_info *info;
- int ret;
- u8 v;
-
- info = sgm41513_sysfs_field_lookup(attr->attr.name);
- if (!info)
- return -EINVAL;
-
- ret = sgm41513_read_mask(bdi, info->reg, info->mask, info->shift, &v);
- if (ret)
- return ret;
-
- return scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
-}
-
-static ssize_t sgm41513_sysfs_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct power_supply *psy = dev_get_drvdata(dev);
- struct sgm41513_dev_info *bdi =
- container_of(psy, struct sgm41513_dev_info, charger);
- struct sgm41513_sysfs_field_info *info;
- int ret;
- u8 v;
-
- info = sgm41513_sysfs_field_lookup(attr->attr.name);
- if (!info)
- return -EINVAL;
-
- ret = kstrtou8(buf, 0, &v);
- if (ret < 0)
- return ret;
-
- ret = sgm41513_write_mask(bdi, info->reg, info->mask, info->shift, v);
- if (ret)
- return ret;
-
- return count;
-}
-
-static int sgm41513_sysfs_create_group(struct sgm41513_dev_info *bdi)
-{
- sgm41513_sysfs_init_attrs();
-
- return sysfs_create_group(&bdi->charger.dev->kobj,
- &sgm41513_sysfs_attr_group);
-}
-
-static void sgm41513_sysfs_remove_group(struct sgm41513_dev_info *bdi)
-{
- sysfs_remove_group(&bdi->charger.dev->kobj, &sgm41513_sysfs_attr_group);
-}
-#else
static int sgm41513_sysfs_create_group(struct sgm41513_dev_info *bdi)
{
return 0;
}
static inline void sgm41513_sysfs_remove_group(struct sgm41513_dev_info *bdi) {}
-#endif
-
-#if 0
-/*set the Vsys min*/
-static int sgm41513_set_vsys_min(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
-{
- return sgm41513_set_field_val(bdi, SGM41513_REG_VSC,
- SGM41513_REG_VSC_VSYS_MIN_MASK, SGM41513_REG_VSC_VSYS_MIN_SHIFT,
- sgm41513_cvc_vseta_values,
- ARRAY_SIZE(sgm41513_cvc_vseta_values), val->intval);
- //return 0
-}
-#endif
//#define func_trace() do{printk("cy: functrace %s:%d\n", __func__, __LINE__);}while(0)
#define func_trace() do{}while(0)
@@ -448,14 +263,14 @@
func_trace();
/* Reset the registers */
- ret = sgm41513_write_mask(bdi, SGM41513_REG08,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,0x1);
+ ret = sgm41513_write_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,0x1);
if (ret < 0)
return ret;
/* Reset bit will be cleared by hardware so poll until it is */
do
{
- ret = sgm41513_read_mask(bdi, SGM41513_REG08,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,&v);
+ ret = sgm41513_read_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,&v);
if (ret < 0)
return ret;
@@ -475,24 +290,102 @@
/* Charger power supply property routines */
-extern void typec_pwr_role_set1(void);
static void dump_sgm_regs(struct i2c_client *client);
static int sgm41513_charger_get_charge_type(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
{
printk("cy: sgm41513_charger_get_charge_type 1\n");
val->intval = bdi->charger.type;
- //set_typec_try_role(1);
- //typec_pwr_role_set1();
return 0;
}
-static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+static void set_ce_gpio(int val)
{
- u8 v=0, vbus_stat=0, chrg_stat=0, pg_stat=0;
+ if (val > 0)
+ {
+ gpio_direction_output(120, 0);
+ ce_enabled = 1;
+ }
+ else
+ {
+ gpio_direction_output(120, 1);
+ ce_enabled = 0;
+ }
+}
+
+static int sgm41513_get_real_voltage(void)
+{
+ int ret, local_ce_flag=0;
+ u8 v=0;
+ if (ce_enabled == 1)
+ {
+ ret = sgm41513_read_mask(g_bdi, SGM41513_REG08, SGM41513_REG08_CHRG_STAT_MASK, SGM41513_REG08_CHRG_STAT_SHIFT, &v);
+ if (v == 1 || v == 2)
+ {
+ local_ce_flag = 1;
+ mutex_lock(&g_bdi->bs_reg_lock);
+ g_bdi->during_voltage_query_flag = 2;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ set_ce_gpio(0);
+ msleep(100);
+ }
+ }
+ ret = get_adc1_voltage() - (local_ce_flag == 1 ? 8 : 0);
+ if (local_ce_flag)
+ {
+ set_ce_gpio(1);
+ mutex_lock(&g_bdi->bs_reg_lock);
+ g_bdi->during_voltage_query_flag = 1;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ }
+ return ret;
+}
+
+int can_cc_hardreset(void)
+{
+ if (g_bdi->dcin_5v_pulgin_flag)
+ return true;
+ return sgm41513_get_real_voltage() > CHANGE_ROLE_VOTAGE;
+}
+
+static int convert_charger_status(u8 v)
+{
+ u8 vbus_stat=0, chrg_stat=0, pg_stat=0;
int status=POWER_SUPPLY_STATUS_UNKNOWN;
+
+ vbus_stat = ((v&SGM41513_REG08_VBUS_STAT_MASK) >> SGM41513_REG08_VBUS_STAT_SHIFT);
+ chrg_stat = ((v&SGM41513_REG08_CHRG_STAT_MASK) >> SGM41513_REG08_CHRG_STAT_SHIFT);
+ pg_stat = ((v&SGM41513_REG08_PG_STAT_MASK) >> SGM41513_REG08_PG_STAT_SHIFT);
+ printk("cy: sgm41513_charger_get_status v=%d, %d %d %d\n", v, vbus_stat, chrg_stat, pg_stat);
+
+ if (vbus_stat == 0 || vbus_stat == 7 || (chrg_stat == 0 && pg_stat == 0))
+ {
+ status = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+ else if(chrg_stat == 1 || chrg_stat == 2)
+ {
+ if (ce_enabled == 1)
+ status = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+ else if(chrg_stat == 0 || ce_enabled == 0)
+ {
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+ else if(chrg_stat == 3)
+ {
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+
+ return status;
+}
+
+static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val, bool full_check)
+{
+ u8 v=0;
int ret=0;
- printk("cy: sgm41513_charger_get_status 3\n");
+ //printk("cy: sgm41513_charger_get_status 3\n");
//dump_sgm_regs(bdi->client);
//set_typec_try_role(0);
//typec_pwr_role_set1();
@@ -504,96 +397,36 @@
printk("cy: read reg 08 error\n");
return -EIO;
}
-
- vbus_stat = ((v&SGM41513_REG08_VBUS_STAT_MASK) >> SGM41513_REG08_VBUS_STAT_SHIFT);
- chrg_stat = ((v&SGM41513_REG08_CHRG_STAT_MASK) >> SGM41513_REG08_CHRG_STAT_SHIFT);
- pg_stat = ((v&SGM41513_REG08_PG_STAT_MASK) >> SGM41513_REG08_PG_STAT_SHIFT);
-
- if (vbus_stat == 0 || vbus_stat == 7 || (chrg_stat == 0 && pg_stat == 0))
+ else
{
- status = POWER_SUPPLY_STATUS_DISCHARGING;
- }
- else if(chrg_stat == 1 || chrg_stat == 2)
- {
- status = POWER_SUPPLY_STATUS_CHARGING;
- }
- else if(chrg_stat == 0)
- {
- status = POWER_SUPPLY_STATUS_NOT_CHARGING;
- }
- else if(chrg_stat == 3)
- {
- status = POWER_SUPPLY_STATUS_FULL;
+ val->intval = convert_charger_status(v);
+ if (full_check && val->intval == POWER_SUPPLY_STATUS_NOT_CHARGING && sgm41513_get_real_voltage() >= bdi->pdata->max_charge_voltage)
+ {
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ }
}
- if (!ret)
- val->intval = status;
-
- printk("cy: sgm41513_charger_get_status exit\n");
+ if (full_check)
+ printk("cy: sgm41513_charger_get_status %d exit\n", val->intval);
return ret;
}
static int sgm41513_charger_get_health(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
{
- u8 ciis_reg=0, cbis_reg=0, cfis_reg=0;
- int health=0, ret=0;
+ u8 v;
+ int ret;
- func_trace();
- //mutex_lock(&bdi->bs_reg_lock);
-
-#if 0
- if (bdi->charger_health_valid) {
- bdi->charger_health_valid = false;
- cbis_reg = bdi->cbis_curr_reg;
- ciis_reg = bdi->ciis_curr_reg;
- cfis_reg = bdi->cfis_curr_reg;
- mutex_unlock(&bdi->bs_reg_lock);
- } else {
- mutex_unlock(&bdi->bs_reg_lock);
-
- ret = sgm41513_read(bdi, SGM41513_REG_CIIS, &ciis_reg);
- if (ret < 0)
- return ret;
- ret = sgm41513_read(bdi, SGM41513_REG_CBIS, &cbis_reg);
- if (ret < 0)
- return ret;
- ret = sgm41513_read(bdi, SGM41513_REG_CFIS, &cfis_reg);
- if (ret < 0)
- return ret;
-
- printk(KERN_INFO "sgm41513_charger_get_health REG_0xa=0x%x,REG_0xc=0x%x,REG_0x10=0x%x.\n",ciis_reg,cbis_reg,cfis_reg);
-
+ ret = sgm41513_read_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_PN_MASK,
+ SGM41513_REG0B_PN_SHIFT, &v);
+ if (ret < 0 || v == 0)
+ {
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ }
+ else
+ {
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
}
- if (cbis_reg & SGM41513_REG_CBIS_OTG_FAULT_MASK) {
- /*
- * This could be over-current or over-voltage but there's
- * no way to tell which. Return 'OVERVOLTAGE' since there
- * isn't an 'OVERCURRENT' value defined that we can return
- * even if it was over-current.
- */
- health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
- }
- else if(cbis_reg & SGM41513_REG_CBIS_SAFE_TIMER_MASK) {
- health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
- }
- else if(cbis_reg & SGM41513_REG_CBIS_DCIN_PG_MASK) {
- health = POWER_SUPPLY_HEALTH_GOOD;
- }
- else if(ciis_reg & (SGM41513_REG_CIIS_INLIMIT_MASK|SGM41513_REG_CIIS_THERM_MASK)) {
- health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
- }
- else if(cfis_reg & SGM41513_REG_CFIS_THSD_MASK){
- health = POWER_SUPPLY_HEALTH_OVERHEAT; /*the chip hot error*/
- }
- else{
- health = POWER_SUPPLY_HEALTH_UNKNOWN;
- }
-
- val->intval = health;
-
-#endif
- val->intval = POWER_SUPPLY_HEALTH_GOOD;
return 0;
}
@@ -611,47 +444,6 @@
return 0;
}EXPORT_SYMBOL (sgm41513_charger_get_online);
-#if 0
-static int sgm41513_charger_get_current(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
- int curr, ret;
-
- ret = sgm41513_get_field_val(bdi, SGM41513_REG_ISC,
- SGM41513_REG_ISC_ISET_DCIN_MASK, SGM41513_REG_ISC_ISET_DCIN_SHIFT,
- sgm41513_in_ilimit_values,
- ARRAY_SIZE(sgm41513_in_ilimit_values), &curr);
- if (ret < 0)
- return ret;
-
- val->intval = curr;
- return 0;
-}
-
-static int sgm41513_charger_get_current_max(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
- int idx = ARRAY_SIZE(sgm41513_in_ilimit_values) - 1;
-
- val->intval = sgm41513_in_ilimit_values[idx];
- return 0;
-}
-
-static int sgm41513_charger_get_voltage(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
-#if 0
- int voltage, ret;
- ret = sgm41513_get_field_val(bdi, SGM41513_REG_CVC,
- SGM41513_REG_CVC_VBAT_MASK, SGM41513_REG_CVC_VBAT_SHIFT,
- sgm41513_cvc_vseta_values,
- ARRAY_SIZE(sgm41513_cvc_vseta_values), &voltage);
- if (ret < 0)
- return ret;
-
- val->intval = voltage;
-#endif
-return 0;
-}
-#endif
-
static int sgm41513_charger_get_charger_enabled(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
{
u8 charger_enabled;
@@ -702,16 +494,6 @@
}
-#if 0
-static int sgm41513_charger_set_current(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
- return sgm41513_set_field_val(bdi, SGM41513_REG_ISC,
- SGM41513_REG_ISC_ISET_DCIN_MASK, SGM41513_REG_ISC_ISET_DCIN_MASK,
- sgm41513_in_ilimit_values,
- ARRAY_SIZE(sgm41513_in_ilimit_values), val->intval);
-
-}
-#endif
static int sgm41513_charger_set_voltage(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
{
int n;
@@ -719,22 +501,127 @@
if (val->intval == 4350)
n =15;
else
- n = (val->intval - 3856) / 32;
+ n = (val->intval - 3856 + 15) / 32;
return sgm41513_write_mask(bdi, SGM41513_REG04,
SGM41513_REG04_VREG_MASK, SGM41513_REG04_VREG_SHIFT, n);
}
-static int set_ce_gpio(int val)
+static int convert_iindpm_from_current(short curr_val)
{
- if (val > 0)
- {
- gpio_direction_output(120, 0);
- ce_enabled = 1;
- }
+ if (curr_val <= 100 )
+ return 0;
+ else if (curr_val >= 3200)
+ return 0x1f;
else
+ return (curr_val - 100) / 100;
+}
+
+static int convert_ichg_from_current(short curr_val)
+{
+ int reg_val;
+ if (curr_val < 0)
+ reg_val = -1;
+ else if (curr_val <= 40)
+ reg_val = curr_val / 5;
+ else if (curr_val <= 110)
+ reg_val = 0x08 + (curr_val - 40) / 10;
+ else if (curr_val <= 270)
+ reg_val = 0x0F + (curr_val - 110) / 20;
+ else if (curr_val <= 540)
+ reg_val = 0x17 + (curr_val - 270) / 30;
+ else if (curr_val <= 1500)
+ reg_val = 0x20 + (curr_val - 540) / 60;
+ else if (curr_val <= 2940)
+ reg_val = 0x30 + (curr_val - 1500) / 120;
+ else
+ reg_val = 0x3d;
+ return reg_val;
+}
+
+static int convert_iprechg_iterm_from_current(short curr_val)
+{
+ int reg_val;
+ printk("cy: convert_iprechg_iterm_from_current1\n");
+ if (curr_val < 5)
+ reg_val = 0;
+ else if (curr_val <= 20)
+ reg_val = (curr_val - 5) / 5;
+ else if (curr_val <= 60)
+ reg_val = 0x3 + (curr_val - 20) / 10;
+ else if (curr_val <= 200)
+ reg_val = 0x7 + (curr_val - 60) / 20;
+ else
+ reg_val = 0xf;
+ printk("cy: convert_iprechg_iterm_from_current %d\n",reg_val);
+ return reg_val;
+}
+
+static struct sgm41513_charge_current_limit * get_current_temp_status(struct sgm41513_dev_info *bdi)
+{
+ int voltage, i;
+ struct sgm41513_charge_current_limit *p = NULL;
+
+ voltage = get_adc2_voltage();
+ //voltage = 678; //tmp for test
+ pr_err("%s voltage %d\n",__func__, voltage);
+ for (i=0; i<bdi->pdata->temp_current_map_size; i++)
{
- gpio_direction_output(120, 1);
- ce_enabled = 0;
+ p = &bdi->pdata->temp_current_map[i];
+ if ((p->temp_voltage_below == -1 && voltage >= p->temp_voltage_above)
+ || (voltage < p->temp_voltage_below && voltage >= p->temp_voltage_above)
+ || (p->temp_voltage_above == -1 && voltage < p->temp_voltage_below))
+ {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+static void set_charge_current(struct sgm41513_dev_info *bdi)
+{
+ int ret, i;
+ u8 last_curr = -1;
+ u8 need_curr = -1;
+ union power_supply_propval val;
+ struct sgm41513_charge_current_limit *p = NULL;
+
+ ret = sgm41513_read_mask(bdi,SGM41513_REG02,
+ SGM41513_REG02_ICHG_MASK,
+ SGM41513_REG02_ICHG_SHIFT,
+ &last_curr);
+
+ p = get_current_temp_status(bdi);
+ if (p == NULL)
+ {
+ dev_info(bdi->dev, "bad temperature range assigned\n");
+ return;
+ }
+
+ need_curr = convert_ichg_from_current(p->current_limit);
+ if (p->max_voltage != -1 && need_curr > 0)
+ {
+ val.intval = p->max_voltage;
+ sgm41513_charger_set_voltage(bdi, &val);
+ }
+
+ printk("cy: last_curr %d, need_curr %d\n",last_curr, need_curr);
+ if (need_curr != (u8)-1 && last_curr != need_curr)
+ {
+ ret = sgm41513_write_mask(bdi,SGM41513_REG02,
+ SGM41513_REG02_ICHG_MASK,
+ SGM41513_REG02_ICHG_SHIFT,
+ need_curr);
+ last_curr = need_curr;
+ }
+}
+
+static void re_schedule_charge_monitor_work(struct sgm41513_dev_info *bdi, bool re_count_down)
+{
+ if (!bdi->charge_monitor_work_running_flag || re_count_down)
+ {
+ cancel_delayed_work_sync(&bdi->charge_monitor_work);
+ schedule_delayed_work(&bdi->charge_monitor_work, HZ/2);
+ bdi->charge_monitor_work_running_flag = true;
}
}
@@ -763,18 +650,34 @@
if (enable_charge.intval == 1)
{
+ set_charge_current(bdi);
ret = sgm41513_write_mask(bdi, SGM41513_REG00,
SGM41513_REG00_EN_HIZ_MASK,
SGM41513_REG00_EN_HIZ_SHIFT, 0);
}
- printk("cy: sgm41513_charger_set_charger_config 2\n");
- ret = sgm41513_write_mask(bdi, SGM41513_REG01,
+ ret = sgm41513_write_mask(bdi, SGM41513_REG01,
SGM41513_REG01_CHG_CONFIG_MASK,
SGM41513_REG01_CHG_CONFIG_SHIFT, enable_charge.intval ); /*0:disable 1:enable*/
- set_ce_gpio(enable_charge.intval);
-
+
+ bdi->current_charging_flag = POWER_SUPPLY_STATUS_UNKNOWN; // notify query
+
+ if (bdi->battery_online_flag && enable_charge.intval != 0)
+ {
+ set_ce_gpio(1);
+ re_schedule_charge_monitor_work(bdi, true);
+ }
+ else if (enable_charge.intval == 0)
+ set_ce_gpio(0);
+ else
+ {
+ printk("battery is not online\n");
+ ret = -1;
+ }
+ //set_charge_current(bdi);
+ //power_supply_changed(&bdi->charger);
+
return ret;
}
@@ -800,7 +703,8 @@
case POWER_SUPPLY_PROP_STATUS:
printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_STATUS\n");
- ret = sgm41513_charger_get_status(bdi, val);
+ ret = sgm41513_charger_get_status(bdi, val, true);
+ bdi->last_reported_charging_flag = val->intval;
break;
case POWER_SUPPLY_PROP_HEALTH:
printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_HEALTH\n");
@@ -881,15 +785,32 @@
case POWER_SUPPLY_PROP_PD_ACTIVE:
printk("cy: POWER_SUPPLY_PROP_PD_ACTIVE %d\n", val->intval);
break;
- case POWER_SUPPLY_PROP_CHARGE_ENABLED:
- printk("cy: POWER_SUPPLY_PROP_CHARGE_ENABLED\n");
- ret = sgm41513_charger_set_charger_config(bdi, val);
- power_supply_changed(&bdi->charger);
+ case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+ printk("cy: POWER_SUPPLY_PROP_CHARGE_ENABLED val %d, dcin %d\n", val->intval, bdi->dcin_5v_pulgin_flag);
+ if (val->intval == 0 || bdi->dcin_5v_pulgin_flag)
+ ret = sgm41513_charger_set_charger_config(bdi, val);
break;
case POWER_SUPPLY_PROP_USB_OTG:
- printk("cy: POWER_SUPPLY_PROP_USB_OTG\n");
- ret = sgm41513_write_mask(bdi,SGM41513_REG01,
- SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,!!val->intval);
+ printk("cy: POWER_SUPPLY_PROP_USB_OTG val %d, dcin %d\n", val->intval, bdi->dcin_5v_pulgin_flag);
+ if (val->intval != 0 && bdi->dcin_5v_pulgin_flag)
+ {
+ ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+ SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,0);
+ gpio_direction_output(OUT_5V_GPIO, 1);
+ }
+ else if (val->intval != 0)
+ {
+ ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+ SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,1);
+ gpio_direction_output(OUT_5V_GPIO, 0);
+
+ }
+ else // val->intval == 0
+ {
+ ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+ SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,0);
+ gpio_direction_output(OUT_5V_GPIO, 0);
+ }
break;
default:
printk("cy: unkown\n");
@@ -955,69 +876,37 @@
static int sgm41513_battery_get_health(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
{
- u8 v;
- int health, ret;
-
- mutex_lock(&bdi->bs_reg_lock);
-
- if(true!=bdi->pdata->ts_flag){
- val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
- mutex_unlock(&bdi->bs_reg_lock);
- return 0;
+ struct sgm41513_charge_current_limit *p;
+ p = get_current_temp_status(bdi);
+ if (p == NULL)
+ {
+ return -1;
}
-
- if (bdi->battery_health_valid) {
- v = bdi->reg09;
- bdi->battery_health_valid = false;
- } else {
-
- ret = sgm41513_read(bdi, SGM41513_REG09, &v);
- if (ret < 0){
-
- mutex_unlock(&bdi->bs_reg_lock);
- return ret;
- }
- }
-
- if (v & SGM41513_REG09_BAT_FAULT_MASK) {
- health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
- } else {
- v &= SGM41513_REG09_NTC_FAULT_MASK;
- v >>= SGM41513_REG09_NTC_FAULT_SHIFT;
-
- switch (v) {
- case 0: /* Normal */
- health = POWER_SUPPLY_HEALTH_GOOD;
- break;
- case 2: /* warm*/
- health = POWER_SUPPLY_HEALTH_WARM;
- break;
- case 6: /* Hot */
- health = POWER_SUPPLY_HEALTH_OVERHEAT;
- break;
- case 3:/* Cool*/
- health = POWER_SUPPLY_HEALTH_COOL;
- break;
- case 5: /* Cold */
- health = POWER_SUPPLY_HEALTH_COLD;
- break;
- default:
- health = POWER_SUPPLY_HEALTH_UNKNOWN;
- }
- }
-
- val->intval = health;
- mutex_unlock(&bdi->bs_reg_lock);
+ val->intval = p->temp_grade;
return 0;
}
static int sgm41513_battery_get_online(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
{
- int ret;
-
- ret = get_adc2_voltage();
- printk("cy adc2 voltage %d\n", ret);
- val->intval = (ret <= 1700);
+
+ struct sgm41513_charge_current_limit *p;
+ p = get_current_temp_status(bdi);
+ if (p == NULL)
+ {
+ return -1;
+ }
+ if (p->temp_grade == POWER_SUPPLY_HEALTH_UNKNOWN && get_adc1_voltage() < 100 )
+ {
+ if (val != NULL)
+ val->intval = 0;
+ bdi->battery_online_flag = false;
+ }
+ else
+ {
+ if (val != NULL)
+ val->intval = 1;
+ bdi->battery_online_flag = true;
+ }
return 0;
}
@@ -1104,8 +993,8 @@
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- //#ifdef CONFIG_ZX234290_ADC
- val->intval = get_adc1_voltage() - 15;
+ //#ifdef CONFIG_ZX234290_ADC
+ val->intval = sgm41513_get_real_voltage();
ret = 0;
break;
#if 1
@@ -1211,13 +1100,25 @@
{
int ret;
printk("cy: sgm41513_boost_set_charge_enable\n");
- //set_typec_try_role(2);
ret = sgm41513_write_mask(bdi,SGM41513_REG01,
SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,!!val->intval);
return ret;
}
+static int sgm41513_boost_get_charge_enable(struct sgm41513_dev_info *bdi, union power_supply_propval *val)
+{
+ u8 v;
+ int ret;
+ ret = sgm41513_read_mask(bdi,SGM41513_REG01,
+ SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,&v);
+
+ if (ret == 0)
+ val->intval = v;
+
+ return ret;
+}
+
static int sgm41513_boost_set_current_now(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
{
return 0;
@@ -1241,6 +1142,9 @@
case POWER_SUPPLY_PROP_CURRENT_NOW:
ret = sgm41513_boost_get_current_now(bdi, val);
break;
+ case POWER_SUPPLY_PROP_BOOST_ENABLE:
+ ret = sgm41513_boost_get_charge_enable(bdi, val);
+ break;
#if 0
case POWER_SUPPLY_PROP_CURRENT_MAX:
ret = sgm41513_boost_get_current_max(bdi, val);
@@ -1385,72 +1289,6 @@
func_trace();
}
-/*
- when BAT goes under BAEdet(3.4V) or CHGRST set 1
- Group B(A1,A2,A3,A4,A5,A7) registers will reset
- call this function in init or dcin
-*/
-static int sgm41513_charger_config_groupB_Regs(struct sgm41513_dev_info *bdi)
-{
- int ret;
- return 0;//@todo cy add
-
-#if 0
- /*set VINDPM to 4.52V*/
- ret = sgm41513_write_mask(bdi,SGM41513_REG_ISC,
- SGM41513_REG_ISC_VINDPM_MASK,
- SGM41513_REG_ISC_VINDPM_SHIFT,
- 0x8);
- /*set VSETA to 4.2V*/
- ret += sgm41513_write_mask(bdi,SGM41513_REG_CVC,
- SGM41513_REG_CVC_VBAT_MASK,
- SGM41513_REG_CVC_VBAT_SHIFT,
- 0x2);
-
- /*disable the timer*/
- ret += sgm41513_write_mask(bdi,SGM41513_REG_CTC,
- SGM41513_REG_CTC_EN_TIMER_MASK,
- SGM41513_REG_CTC_EN_TIMER_SHIFT,
- 0x0);
- /*disable the 2*timer*/
- ret += sgm41513_write_mask(bdi,SGM41513_REG_CTC,
- SGM41513_REG_CTC_EN_2XTIMER_MASK,
- SGM41513_REG_CTC_EN_2XTIMER_SHIFT,
- 0x0);
- /*set CVCOMP to 20mV*/
- ret += sgm41513_write_mask(bdi,SGM41513_REG_CTC,
- SGM41513_REG_CTC_CVCOMP_MASK,
- SGM41513_REG_CTC_CVCOMP_SHIFT,
- 0x4);
-
-
- /*disable the JETTA*/
- ret += sgm41513_write_mask(bdi,SGM41513_REG_THR,
- SGM41513_REG_THR_EN_JEITA_MASK,
- SGM41513_REG_THR_EN_JEITA_SHIFT,
- 0x0);
-
- /*set the temprator cool */
- /*00:0 01:5 10:10 11:15*/
- ret += sgm41513_write_mask(bdi,SGM41513_REG_TS,
- SGM41513_REG_TS_COOL_MASK,
- SGM41513_REG_TS_COOL_SHIFT,
- 0x0);
-
- if (ret < 0){
- goto out;
- }
-
- return 0;
-
- out:
- //pm_runtime_put_sync(bdi->dev);
- dev_err(bdi->dev, "sgm41513_charger_groupB_config ERROR: %d\n", ret);
- return ret;
-
-#endif
-}
-
static int sgm41513_hw_init(struct sgm41513_dev_info *bdi)
{
u8 v;
@@ -1468,16 +1306,37 @@
//zx29_gpio_output_data(ZX29_GPIO_51, 1);
#endif
//pm_runtime_get_sync(bdi->dev);
-
+
+ set_ce_gpio(0);
+
ret = sgm41513_write_mask(bdi,SGM41513_REG0B,
SGM41513_REG0B_REGRST_MASK,
SGM41513_REG0B_REGRST_SHIFT,
0x1);
if (ret < 0){
- pr_err("cy: line %d ret %d\n", __LINE__, ret);
+ pr_err("soft rest fail! line %d ret %d\n", __LINE__, ret);
goto out;
}
- pr_err("cy: line %d ret %d\n", __LINE__, ret);
+ for (i=0;i<1000;i++)
+ {
+ udelay(100);
+ ret = sgm41513_read_mask(bdi,SGM41513_REG0B,
+ SGM41513_REG0B_REGRST_MASK,
+ SGM41513_REG0B_REGRST_SHIFT,
+ &v);
+ if (ret == 0 && v == 0)
+ break;
+ }
+
+ ret = sgm41513_write_mask(bdi,SGM41513_REG00,
+ SGM41513_REG00_IINDPM_MASK,
+ SGM41513_REG00_IINDPM_SHIFT,
+ convert_iindpm_from_current(bdi->pdata->max_input_current));
+
+ ret = sgm41513_write_mask(bdi,SGM41513_REG06,
+ SGM41513_REG06_OVP_MASK,
+ SGM41513_REG06_OVP_SHIFT,
+ 0x1);
/*
ret = sgm41513_write_mask(bdi,SGM41513_REG06,
@@ -1499,10 +1358,17 @@
ret = sgm41513_write_mask(bdi,SGM41513_REG03,
SGM41513_REG03_ITERM_MASK,
SGM41513_REG03_ITERM_SHIFT,
- 0xd);
+ convert_iprechg_iterm_from_current(bdi->pdata->terminate_charge_current));
if (ret < 0){
- pr_err("cy: line %d ret %d\n", __LINE__, ret);
- //goto out;
+ pr_err("set iterm fail, line %d ret %d\n", __LINE__, ret);
+ }
+
+ ret = sgm41513_write_mask(bdi,SGM41513_REG03,
+ SGM41513_REG03_IPRECHG_MASK,
+ SGM41513_REG03_IPRECHG_SHIFT,
+ convert_iprechg_iterm_from_current(bdi->pdata->pre_charge_current));
+ if (ret < 0){
+ pr_err("set iprechg fail, line %d ret %d\n", __LINE__, ret);
}
dump_sgm_regs(bdi->client);
@@ -1513,10 +1379,10 @@
SGM41513_REG0B_PN_MASK,
SGM41513_REG0B_PN_SHIFT,
&v);
-
+
if (ret < 0){
pr_err("cy: line %d ret %d\n", __LINE__, ret);
- goto out;
+ goto out;
}
printk(KERN_INFO "sgm41513_hw_init:sgm41513-charger version reg: 0x%x\n", v);
@@ -1525,13 +1391,8 @@
if (ret < 0){
pr_err("cy: line %d ret %d\n", __LINE__, ret);
}
- /*
- if (v != bdi->model) {
- ret = -ENODEV;
- goto out;
- }
- */
- voltage_val.intval = 4400;
+
+ voltage_val.intval = bdi->pdata->max_charge_voltage;
ret = sgm41513_charger_set_voltage(bdi,&voltage_val);
if (ret < 0){
pr_err("cy: line %d ret %d\n", __LINE__, ret);
@@ -1547,16 +1408,16 @@
pr_err("cy: line %d ret %d\n", __LINE__, ret);
goto out;
}
-
+
ret = sgm41513_write_mask(bdi,SGM41513_REG02,
SGM41513_REG02_BOOST_LIM_MASK,
SGM41513_REG02_BOOST_LIM_SHIFT,
- 0x1);
+ 0x0);
if (ret < 0){
pr_err("cy: line %d ret %d\n", __LINE__, ret);
goto out;
}
-
+
ret = sgm41513_write_mask(bdi,SGM41513_REG02,
SGM41513_REG02_ICHG_MASK,
SGM41513_REG02_ICHG_SHIFT,
@@ -1565,13 +1426,13 @@
pr_err("cy: line %d ret %d\n", __LINE__, ret);
goto out;
}
-
+
dump_sgm_regs(bdi->client);
- printk("cy: get_adc1_voltage %d\n", ret);
voltage = get_adc1_voltage();
- //*
- if (voltage < 3800) {
- set_typec_try_role(0); // try dongle
+ printk("cy: get_adc1_voltage %d\n", voltage);
+ /*
+ if (voltage < red_voltage_level) {
+ set_typec_try_role(1); // try dongle
} else {
set_typec_try_role(1);
}
@@ -1590,7 +1451,6 @@
return ret;
}
-
static irqreturn_t sgm41513_charger_irq_primary_handler(int irq, struct sgm41513_dev_info *bdi)
{
func_trace();
@@ -1603,14 +1463,149 @@
return IRQ_HANDLED;
}
+static irqreturn_t dcin_5v_irq_primary_thread(int irq, struct sgm41513_dev_info *bdi)
+{
+ int value, out_5v_value;
+ union power_supply_propval enable_charge;
+ zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_GPIO);
+ gpio_direction_input(DCIN_5V_GPIO);
+ value = gpio_get_value(DCIN_5V_GPIO);
+ bdi->dcin_5v_pulgin_flag = (value == CHG_PLUG_IN);
+
+ if (bdi->dcin_5v_pulgin_flag)
+ {
+ enable_charge.intval = 1;
+ }
+ else
+ {
+ enable_charge.intval = 0;
+ }
+
+ sgm41513_charger_set_charger_config(bdi, &enable_charge);
+
+ if (bdi->dcin_5v_pulgin_flag)
+ {
+ set_typec_try_role(2);
+ }
+ else
+ {
+ set_typec_try_role(0);
+ }
+
+ zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_EXT_INT);
+ if(value == 1)
+ {
+ zx29_gpio_set_inttype(DCIN_5V_GPIO,IRQ_TYPE_EDGE_FALLING);
+ pcu_int_clear(DCIN_5V_DT_INT);
+ }
+ else
+ {
+ zx29_gpio_set_inttype(DCIN_5V_GPIO,IRQ_TYPE_EDGE_RISING);
+ pcu_int_clear(DCIN_5V_DT_INT);
+ }
+ printk(KERN_INFO"%s,value:%d,end\n", __func__,value);
+ return IRQ_HANDLED;
+}
+
+#define MAX_PLUG_IN_OUT_CHECK_CNT 6
+
+extern int check_typec_role(void);
+void sgm41513_notify_usb_detect(int stage)
+{
+ //printk("cy: sgm41513_notify_usb_detect stage %d, usb_detect_flag %d, dwc_otg_chg_inform_status %d\n", stage, g_bdi->usb_detect_flag, g_bdi->dwc_otg_chg_inform_status);
+ mutex_lock(&g_bdi->bs_reg_lock);
+ if ((stage == 0 || stage == 4) && g_bdi->dwc_otg_chg_inform_status == 1)
+ {
+ g_bdi->dwc_otg_chg_inform_status = 2; // todo otg chg inform
+ //dwc_otg_chg_inform(0);
+ g_bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+ g_bdi->usb_detect_flag = USB_STATUS_DETECTING;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ re_schedule_charge_monitor_work(g_bdi, false);
+ return;
+ }
+ else if (stage == 0)
+ {
+ if (g_bdi->usb_detect_flag == USB_STATUS_UNKOWN || g_bdi->usb_detect_flag == USB_STATUS_DISCONNECTED)
+ {
+ g_bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+ g_bdi->usb_detect_flag = USB_STATUS_DETECTING;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ re_schedule_charge_monitor_work(g_bdi, false);
+ return;
+ }
+ }
+ else if (stage == 1)
+ {
+ //mutex_unlock(&g_bdi->bs_reg_lock);
+ //dwc_otg_chg_inform(1); //tmp add to fix not recongnize usb plugin since force usb
+ //dwc_otg_chg_inform(0);
+ //mutex_lock(&g_bdi->bs_reg_lock);
+ g_bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+ g_bdi->can_switch_role_flag = true;
+ g_bdi->usb_plug_in_out_check_cnt = 0;
+ g_bdi->power_role_switch_only = false;
+ }
+ else if (stage == 2)
+ {
+ g_bdi->usb_plug_in_out_check_cnt = 1;
+ g_bdi->usb_detect_flag = USB_STATUS_DISCONNECTING;
+ g_bdi->can_switch_role_flag = false;
+ g_bdi->discharging_flag = false;
+ g_bdi->power_role_switch_only = false;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ re_schedule_charge_monitor_work(g_bdi, true);
+ return;
+ }
+ else if (stage == 3)
+ {
+ //mutex_unlock(&g_bdi->bs_reg_lock);
+ //dwc_otg_chg_inform(1); //tmp add to fix not recongnize usb plugin since force usb
+ //dwc_otg_chg_inform(0);
+ //mutex_lock(&g_bdi->bs_reg_lock);
+ g_bdi->discharging_flag = true;
+ g_bdi->can_switch_role_flag = false;
+ g_bdi->power_role_switch_only = false;
+ g_bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+ }
+ else if (stage == 4) //dwc_otg_chg_inform_status == 0
+ {
+ g_bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+ g_bdi->power_role_switch_only = true;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ re_schedule_charge_monitor_work(g_bdi, false);
+ return;
+ }
+ else
+ {
+ printk("cy: unkown stage %d\n", stage);
+ }
+ mutex_unlock(&g_bdi->bs_reg_lock);
+}
+
+bool sgm41513_can_power_switch(void)
+{
+ bool ret = true;
+ /*
+ mutex_lock(&g_bdi->bs_reg_lock);
+ ret = g_bdi->can_switch_role_flag;
+ mutex_unlock(&g_bdi->bs_reg_lock);
+ */
+ if (g_bdi->charger.type == POWER_SUPPLY_PCAC__AC)
+ ret = false;
+ return ret;
+}
+
static irqreturn_t sgm41513_irq_handler_thread(void *data)
{
struct sgm41513_dev_info *bdi = data;
bool charger_changed_flag = false;
bool battery_changed_flag = false;
bool boost_changed_flag = false;
- int ret;
- u8 ms;
+ int ret, i, required_iindpm, last_charge_state;
+ u8 reg08, reg0a, reg0e, chrg_stat;
+ bool vbus_gd_flag, usb_in_flag, usb_host_flag, last_vbus_gd_flag, last_usb_in_flag, last_usb_host_flag;
+ bool no_cc_usb_plugin_check, no_cc_usb_plugout_check;
struct sched_param param = { .sched_priority = 2 };
param.sched_priority= 31;
func_trace();
@@ -1621,30 +1616,143 @@
down(&bdi->chgirq_sem);
//pm_runtime_get_sync(bdi->dev);
mutex_lock(&bdi->bs_reg_lock);
+ bdi->pre_reg08=bdi->reg08;
bdi->pre_reg09=bdi->reg09;
bdi->pis_pre_reg=bdi->pis_curr_reg;
bdi->cfis_pre_reg = bdi->cfis_curr_reg;
+ charger_changed_flag = false;
+ battery_changed_flag = false;
+ boost_changed_flag = false;
//printk(KERN_INFO"sgm41513_irq_handler_thread\n");
-
-#if 0
- ret = sgm41513_read(bdi, SGM41513_REG_MS, &ms);
+ ret = sgm41513_read(bdi, SGM41513_REG0A, ®0a);
if (ret < 0) {
- dev_err(bdi->dev, "Can't read MS reg: %d\n", ret);
- mutex_unlock(&bdi->bs_reg_lock);
- goto out;
- }
- //printk("sgm41513 MS reg is %d",ms);
-
- ret = sgm41513_read(bdi, SGM41513_REG_CBIS, &bdi->cbis_curr_reg);
- if (ret < 0) {
- dev_err(bdi->dev, "Can't read CBIS reg: %d\n", ret);
+ dev_err(bdi->dev, "Can't read 0a reg: %d\n", ret);
mutex_unlock(&bdi->bs_reg_lock);
goto out;
}
-
+ ret = sgm41513_read(bdi, SGM41513_REG08, ®08);
+ if (ret < 0) {
+ dev_err(bdi->dev, "Can't read 08 reg: %d\n", ret);
+ mutex_unlock(&bdi->bs_reg_lock);
+ goto out;
+ }
+
+ last_vbus_gd_flag = vbus_gd_flag = (reg0a & SGM41513_REG0A_VBUS_GD_MASK) != 0;
+ last_usb_in_flag = usb_in_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) != 0;
+ last_usb_host_flag = usb_host_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) == (0x7 << SGM41513_REG08_VBUS_STAT_SHIFT);
+
+ no_cc_usb_plugin_check = (usb_host_flag == 0 && vbus_gd_flag != 0 && !bdi->dcin_5v_pulgin_flag && bdi->usb_detect_flag == USB_STATUS_DISCONNECTED);
+ no_cc_usb_plugout_check = (usb_host_flag == 0 && vbus_gd_flag == 0 && !bdi->dcin_5v_pulgin_flag && bdi->usb_detect_flag == USB_STATUS_CONNECTED );
+
+ //*
+ printk("cy: usb_host_flag: %d, vbus_gd_flag: %d, ce_enabled %d, no_cc_usb_plugin_check %d, no_cc_usb_plugout_check %d\n",
+ usb_host_flag, vbus_gd_flag, ce_enabled,
+ no_cc_usb_plugin_check, no_cc_usb_plugout_check);
+ printk("cy: dcin state %d\n", bdi->dcin_5v_pulgin_flag);
+ //printk("cy: reg 08: %d, reg 0a: %d\n", reg08, reg0a);
+ //*/
+ if (no_cc_usb_plugin_check ||no_cc_usb_plugout_check )
+ {
+ for(i=0;i<5;i++)
+ {
+ mutex_unlock(&bdi->bs_reg_lock);
+ msleep(20);
+ mutex_lock(&bdi->bs_reg_lock);
+ if (bdi->dcin_5v_pulgin_flag)
+ break;
+ ret = sgm41513_read(bdi, SGM41513_REG08, ®08);
+ if (ret < 0) {
+ dev_err(bdi->dev, "Can't read 08 reg: %d\n", ret);
+ mutex_unlock(&bdi->bs_reg_lock);
+ goto out;
+ }
+ vbus_gd_flag = (reg0a & SGM41513_REG0A_VBUS_GD_MASK) != 0;
+ usb_in_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) != 0;
+ usb_host_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) == (0x7 << SGM41513_REG08_VBUS_STAT_SHIFT);
+ printk("cy: dcin state %d\n", bdi->dcin_5v_pulgin_flag);
+ if (vbus_gd_flag !=0 || usb_in_flag !=0 || usb_host_flag != 0)
+ {
+ if (bdi->usb_detect_flag == USB_STATUS_UNKOWN)
+ {
+ bdi->usb_detect_flag = USB_STATUS_DETECTING;
+ bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+ }
+
+ if (bdi->dwc_otg_chg_inform_status == 1)
+ {
+ bdi->dwc_otg_chg_inform_status = 2;
+ re_schedule_charge_monitor_work(bdi, false);
+ }
+ }
+ if (last_vbus_gd_flag != vbus_gd_flag || last_usb_host_flag != usb_host_flag)
+ {
+ break;
+ }
+ }
+ if (!bdi->dcin_5v_pulgin_flag && i >= 5)
+ {
+ if (no_cc_usb_plugin_check)
+ {
+ if (bdi->usb_detect_flag == USB_STATUS_DISCONNECTED)
+ {
+ bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+ //bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+ }
+ }
+ else if (no_cc_usb_plugout_check)
+ {
+ mutex_unlock(&bdi->bs_reg_lock);
+ if (bdi->usb_detect_flag == USB_STATUS_CONNECTED)
+ {
+ bdi->usb_detect_flag = USB_STATUS_DISCONNECTING;
+ bdi->usb_plug_in_out_check_cnt = 1;
+ re_schedule_charge_monitor_work(bdi, true);
+ }
+ mutex_lock(&bdi->bs_reg_lock);
+ }
+ else
+ {
+ printk("cy: usb check again %d\n", __LINE__);
+ }
+ }
+ }
+
+ bdi->reg08 = reg08;
+
+ last_charge_state = bdi->current_charging_flag;
+ if (bdi->during_voltage_query_flag != 2)
+ {
+ bdi->current_charging_flag = convert_charger_status(reg08);
+ }
+
+ if (bdi->dcin_5v_pulgin_flag && bdi->current_charging_flag == POWER_SUPPLY_STATUS_CHARGING && bdi->current_charging_flag != last_charge_state)
+ {
+ required_iindpm = convert_iindpm_from_current(bdi->pdata->max_input_current);
+ ret = sgm41513_write_mask(bdi,SGM41513_REG00,
+ SGM41513_REG00_IINDPM_MASK,
+ SGM41513_REG00_IINDPM_SHIFT,
+ required_iindpm);
+ }
+
+ ret = sgm41513_read(bdi, SGM41513_REG09, &bdi->reg09);
+ if (ret < 0) {
+ dev_err(bdi->dev, "Can't read 09 reg: %d\n", ret);
+ mutex_unlock(&bdi->bs_reg_lock);
+ goto out;
+ }
+
+ ret = sgm41513_read(bdi, SGM41513_REG0E, ®0e);
+ if (ret < 0) {
+ dev_err(bdi->dev, "Can't read 0E reg: %d\n", ret);
+ mutex_unlock(&bdi->bs_reg_lock);
+ goto out;
+ }
+
+
+#if 0
ret = sgm41513_read(bdi, SGM41513_REG_PIS, &bdi->pis_curr_reg);
if (ret < 0) {
dev_err(bdi->dev, "Can't read PIS reg: %d\n", ret);
@@ -1763,6 +1871,8 @@
bdi->battery_health_valid = true;/****?***/
bdi->battery_status_valid = true;/****?***/
+
+#endif
mutex_unlock(&bdi->bs_reg_lock);
/*
@@ -1790,12 +1900,11 @@
out:
//pm_runtime_put_sync(bdi->dev);
-
- dev_dbg(bdi->dev, "read reg:cbis_reg: 0x%02x, pis_reg: 0x%02x, ciis_reg: 0x%02x\n",
- bdi->cbis_curr_reg, bdi->pis_curr_reg, bdi->ciis_curr_reg);
+ //dev_dbg(bdi->dev, "read reg:cbis_reg: 0x%02x, pis_reg: 0x%02x, ciis_reg: 0x%02x\n",
+ // bdi->cbis_curr_reg, bdi->pis_curr_reg, bdi->ciis_curr_reg);
enable_irq(bdi->irq);
-#endif
+ //printk(KERN_INFO"cy: sgm41513_irq_handler_thread loop again, charger_changed_flag %d\n", charger_changed_flag);
}
func_trace();
return 0;
@@ -1837,7 +1946,7 @@
}
zx29_gpio_set_inttype(pdata->gpio_int,IRQ_TYPE_EDGE_FALLING/*IRQ_TYPE_EDGE_RISING*/); //INT_POSEDGE
- zx29_gpio_pd_pu_set(pdata->gpio_int, IO_CFG_PULL_DISABLE);
+ zx29_gpio_pd_pu_set(pdata->gpio_int, IO_CFG_PULL_UP/*IO_CFG_PULL_DISABLE*/);
bdi->gpio_int = pdata->gpio_int;
//pcu_int_clear(bdi->irq);
@@ -1952,76 +2061,27 @@
}
-static T_TYPE_USB_DETECT g_chg_type = 0;
void sgm41513_charge_typedet(T_TYPE_USB_DETECT chg_type)
{
int ret;
- union power_supply_propval val = {.intval = 0};
+ u8 vubs_flag;
#ifdef DBG_CHARGE
printk(KERN_INFO"charge type is %d in\n",chg_type);
#endif
func_trace();
- g_chg_type = chg_type;
+ g_bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+ g_bdi->usb_plug_in_out_check_cnt = 0;
#if 1
if(TYPE_ADAPTER == chg_type){
printk(KERN_INFO"chg type is TYPE_ADAPTER\n");
- //gpio_direction_output(120, 0);
- //ce_enabled = 1;
- val.intval = 1;
- /*set the DCIN Current = 2.4A*/
- ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
- SGM41513_REG00_IINDPM_MASK,
- SGM41513_REG00_IINDPM_SHIFT,
- 0x17);
- if (ret < 0){
- printk(KERN_INFO"write REG_00 fault\n");
- }
+ //set_typec_try_role(0);
g_bdi->charger.type = POWER_SUPPLY_PCAC__AC;
- dump_sgm_regs(g_bdi->client);
- sgm41513_charger_set_charger_config(g_bdi, &val);
}
-
- else {
- //ret = get_typec_role();
- //printk(KERN_INFO"chgage type is TYPE_PC %d\n", ret);
- gpio_direction_output(120, 1);
- ce_enabled = 0;
-
- /*set the DCIN Current = 450mA*/
- ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
- SGM41513_REG00_IINDPM_MASK,
- SGM41513_REG00_IINDPM_SHIFT,
- 0x4);
- if (ret < 0){
- printk(KERN_INFO"write REG_01 fault\n");
- }
-
- /*
- voltage = get_adc1_voltage();
- if (voltage > 3500) {
- ret = sgm41513_write_mask(bdi,SGM41513_REG00, SGM41513_REG00_EN_HIZ_MASK,
- SGM41513_REG00_EN_HIZ_SHIFT, 0x1);
- }
- */
+ else if (TYPE_COMPUTER == chg_type) {
g_bdi->charger.type = POWER_SUPPLY_PCAC__PC;
- dump_sgm_regs(g_bdi->client);
+ //set_typec_try_role(0);
}
-
- //#ifdef CONFIG_CHARGER_SGM41513_EVB
-#if 0
- /*set the DCIN Current = 2A*/
- ret = sgm41513_write_mask(g_bdi,SGM41513_REG_ISC,
- SGM41513_REG_ISC_ISET_DCIN_MASK,
- SGM41513_REG_ISC_ISET_DCIN_SHIFT,
- 0x5);
- if (ret < 0){
- printk(KERN_INFO"write REG_01 fault\n");
- }
- #endif
-
-
-
#endif
}
@@ -2207,10 +2267,11 @@
int ret = 0;
struct sgm41513_dev_info * bdi = NULL;
struct delayed_work *charge_monitor_work = NULL;
- union power_supply_propval val = {.intval = 4100};
+ union power_supply_propval val = {.intval = 0};
//static u8 last_chg_method = 0;
- u8 last_curr = -1;
- u8 need_curr = -1;
+ u8 vbus_stat = -1;
+ int next_run_wait_time = 10 * HZ;
+ bool need_change_typec_role = false;
charge_monitor_work = container_of(work, struct delayed_work, work);
if(charge_monitor_work == NULL) {
@@ -2222,44 +2283,73 @@
pr_err("Cann't get sgm \n");
return ;
}
-
- ret = sgm41513_read_mask(bdi,SGM41513_REG02,
- SGM41513_REG02_ICHG_MASK,
- SGM41513_REG02_ICHG_SHIFT,
- &last_curr);
- ret = get_adc2_voltage();
- pr_err("%s voltage %d\n",__func__, ret);
- if (ret >1284 || ret < 422){ // bellow 0 deg or above 60 deg, curr set to 0
- need_curr = 0x0;
- printk("cy: need 0\n");
- } else if (ret > 1057) { // above 0 deg and bellow 15 deg, curr set to 500mA
- need_curr = 0x1f;
- printk("cy: need 1f\n");
- } else if (ret > 623 && ret <= 1057) { // above 15 deg and bellow 45 dec, curr set to 2A
- need_curr = 0x34;
- printk("cy: need 34\n");
- } else if (ret >= 422 && ret <= 623) { // above 45 deg and bellow 60 dec, curr set to 1A, max vol set to 4.1V
- need_curr = 0x27;
- printk("cy: need 27\n");
- sgm41513_charger_set_voltage(bdi, &val);
- }
- else {
- need_curr = -1;
- printk("cy: unkown condition\n");
- }
- printk("cy: last_curr %d, need_curr %d\n",last_curr, need_curr);
- if (need_curr != -1 && last_curr != need_curr)
+ if (bdi->dwc_otg_chg_inform_status == 2)
{
- ret = sgm41513_write_mask(bdi,SGM41513_REG02,
- SGM41513_REG02_ICHG_MASK,
- SGM41513_REG02_ICHG_SHIFT,
- need_curr);
- last_curr = need_curr;
+ dwc_otg_chg_inform(0);
+ bdi->dwc_otg_chg_inform_status = 0;
}
+
+ if (ce_enabled == 1)
+ {
+ //dump_sgm_regs(bdi->client);
+ //return;
+ set_charge_current(bdi);
+ }
+
+ /*
+ printk("cy: charger_monitor_work_func ce_enabled %d, usb_plug_in_out_check_cnt %d, usb_detect_flag %d, discharging_flag %d \n",
+ ce_enabled, bdi->usb_plug_in_out_check_cnt, bdi->usb_detect_flag, bdi->discharging_flag);
+ */
+ mutex_lock(&bdi->bs_reg_lock);
+ if (bdi->usb_plug_in_out_check_cnt > 0)
+ {
+ bdi->usb_plug_in_out_check_cnt --;
+ if (bdi->usb_plug_in_out_check_cnt <=0 && g_bdi->power_role_switch_only)
+ {
+ need_change_typec_role = true;
+ g_bdi->power_role_switch_only = false;
+ }
+ else if (bdi->usb_plug_in_out_check_cnt <=0 &&!bdi->discharging_flag && (bdi->usb_detect_flag != USB_STATUS_DISCONNECTED && bdi->usb_detect_flag != USB_STATUS_CONNECTED))
+ {
+ printk("cy: usb disconnect\n");
+ bdi->usb_detect_flag = USB_STATUS_DISCONNECTED;
+ bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
+ dwc_otg_chg_inform(1);
+ bdi->dwc_otg_chg_inform_status = 1;
+ //check_typec_role();
+ need_change_typec_role = true;
+ }
+ next_run_wait_time = HZ/2;
+ }
+ mutex_unlock(&bdi->bs_reg_lock);
+ if (need_change_typec_role)
+ {
+ //check_typec_role();
+ }
+
+ if(bdi->usb_plug_in_out_check_cnt <= 0 && (!bdi->during_voltage_query_flag && ce_enabled == 0) &&
+ bdi->current_charging_flag == bdi->last_reported_charging_flag)
+ {
+ bdi->charge_monitor_work_running_flag = false;
+ return;
+ }
+ else if (bdi->current_charging_flag != bdi->last_reported_charging_flag || bdi->during_voltage_query_flag == 1)
+ {
+ sgm41513_charger_get_status(bdi, &val, false);
+ bdi->current_charging_flag = val.intval;
+ bdi->during_voltage_query_flag = 0;
+ if (bdi->current_charging_flag != bdi->last_reported_charging_flag)
+ {
+ power_supply_changed(&bdi->charger);
+ }
+ next_run_wait_time = HZ/2;
+ }
+
dump_sgm_regs(bdi->client);
OUT:
- schedule_delayed_work(&bdi->charge_monitor_work, 10*HZ);
+ bdi->charge_monitor_work_running_flag = true;
+ schedule_delayed_work(&bdi->charge_monitor_work, next_run_wait_time);
}
static int sgm41513_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -2271,15 +2361,15 @@
int ret;
int i; /*when err try 3 times*/
u8 v;
- //use for other
- //g_platform_data= client->dev.platform_data;
printk(KERN_INFO "charger probe.\n");
- //zx29_gpio_set_direction(120,GPIO_OUT);
- //zx29_gpio_output_data(120,1);
- //ret = gpio_direction_output(120, 0);
- //printk("cy: set derection %d\n", ret);
+ set_ce_gpio(0); //make sure ce status ok
+
+ gpio_direction_output(OUT_5V_GPIO, 0);
+
+ zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_GPIO);
+ gpio_direction_input(DCIN_5V_GPIO);
dump_sgm_regs(client);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -2292,6 +2382,7 @@
dev_err(dev, "Can't alloc bdi struct\n");
return -ENOMEM;
}
+ bdi->dcin_5v_pulgin_flag = (gpio_get_value(DCIN_5V_GPIO) == CHG_PLUG_IN);
bdi->pdata = pdata;
bdi->client = client;
bdi->dev = dev;
@@ -2299,23 +2390,33 @@
strncpy(bdi->model_name, id->name, sizeof(bdi->model_name)-1);
mutex_init(&bdi->bs_reg_lock);
bdi->first_time = true;
+ bdi->current_charging_flag = POWER_SUPPLY_STATUS_UNKNOWN;
+ bdi->last_reported_charging_flag = -1; //force to report once
+ bdi->during_voltage_query_flag = 0;
+ bdi->discharging_flag = false;
+ bdi->charge_monitor_work_running_flag = false;
+ bdi->battery_online_flag = false;
+ bdi->usb_detect_flag = USB_STATUS_UNKOWN;
+ bdi->dwc_otg_chg_inform_status = 1;
+ bdi->can_switch_role_flag = false;
bdi->charger_health_valid = false;
bdi->battery_health_valid = false;
bdi->battery_status_valid = false;
+ bdi->usb_plug_in_out_check_cnt = 0;
g_bdi = bdi;
i2c_set_clientdata(client, bdi);
- if (dev->of_node)
- ret = 0;//sgm41513_setup_dt(bdi);
- else
- ret = sgm41513_setup_pdata(bdi, pdata);
+ ret = sgm41513_setup_pdata(bdi, pdata);
if (ret) {
dev_err(dev, "Can't get irq info\n");
return -EINVAL;
}
+
+ sgm41513_battery_get_online(bdi, NULL);
+
#ifdef DBG_CHARGE
printk(KERN_INFO "hwinit.\n");
#endif
@@ -2336,22 +2437,6 @@
#ifdef DBG_CHARGE
printk(KERN_INFO "sgm41513_probe sgm41513_hw_init ok.\n");
#endif
-#ifdef CONFIG_CHARGER_SGM41513_EVB
- /*set the DCIN Current = 2A*/
- /*
- ret = sgm41513_write_mask(g_bdi,SGM41513_REG_ISC,
- SGM41513_REG_ISC_ISET_DCIN_MASK,
- SGM41513_REG_ISC_ISET_DCIN_SHIFT,
- 0x5);
- if (ret < 0){
- printk(KERN_INFO"write REG_01 fault\n");
- }
- */
-#endif
- ret = sgm41513_charger_config_groupB_Regs(bdi);
- if (ret < 0) {
- printk(KERN_INFO "groupB config faild.\n");
- }
sgm41513_charger_init(&bdi->charger);
@@ -2395,7 +2480,7 @@
INIT_DELAYED_WORK(&bdi->boostWorkStruct,sgm41513_boost_workstruct_callback);
INIT_DELAYED_WORK(&bdi->charge_monitor_work, charger_monitor_work_func);
- schedule_delayed_work(&bdi->charge_monitor_work,100);
+ //schedule_delayed_work(&bdi->charge_monitor_work,100);
//queue_delayed_work(bdi->boostQueue,&bdi->boostWorkStruct,20000);
#ifdef DBG_CHARGE
printk(KERN_INFO "setup_workqueue.\n");
@@ -2413,6 +2498,28 @@
sema_init(&bdi->chgirq_sem, 0);
+
+ bdi->chgin_irq= gpio_to_irq(DCIN_5V_GPIO);
+
+ ret = zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_EXT_INT);
+ if (ret < 0)
+ {
+ dev_err(dev, "init dcin_5v interrupt error.\n");
+ }
+ else
+ {
+ zx29_gpio_set_inttype(DCIN_5V_GPIO, bdi->dcin_5v_pulgin_flag ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_LEVEL_HIGH); //INT_POSEDGE
+ }
+
+ ret = request_threaded_irq(bdi->chgin_irq, NULL, dcin_5v_irq_primary_thread, IRQF_ONESHOT, "dcin-5v-chgin", bdi);
+ if (ret < 0) {
+ dev_err(dev, "Can't set up irq handler %d\n", __LINE__);
+ if (DCIN_5V_GPIO)
+ gpio_free(DCIN_5V_GPIO);
+ }
+
+ irq_set_irq_wake(bdi->chgin_irq, 1);
+
ret = sgm41513_init_state(bdi);
if(ret)
{
@@ -2465,17 +2572,16 @@
dwc_otg_chg_inform(!ret);
*/
-
- ret = sgm41513_read_mask(bdi, SGM41513_REG08,
- SGM41513_REG08_VBUS_STAT_MASK,
- SGM41513_REG08_VBUS_STAT_SHIFT,
- &v);
-
- if (ret >= 0) {
- printk("cy: vbus stat %d \n", v);
- //dwc_otg_chg_inform(!v);
+ if (bdi->dcin_5v_pulgin_flag || sgm41513_get_real_voltage() > CHANGE_ROLE_VOTAGE)
+ {
+ set_typec_try_role(1);
+ }
+ else
+ {
+ set_typec_try_role(0);
}
+ sgm41513_charger_irq_primary_handler(bdi->irq, bdi);
#ifdef DBG_CHARGE
printk(KERN_INFO "sgm41513_probe end.\n");
diff --git a/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h b/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
index 251dcaf..0ed5b5d 100644
--- a/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
+++ b/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
@@ -10,6 +10,7 @@
#define _SGM41513_CHARGER_H_
#include <linux/bitops.h>
+#include <linux/power_supply.h>
#include <mach/gpio.h>
typedef void VOID;
@@ -159,6 +160,8 @@
#define SGM41513_REG0A 0x0A
+#define SGM41513_REG0A_VBUS_GD_MASK BIT(7)
+#define SGM41513_REG0A_VBUS_GD_SHIFT 7
#define SGM41513_REG0B 0x0B /*record the version info*/
@@ -168,6 +171,9 @@
#define SGM41513_REG0B_PN_MASK (BIT(6)|BIT(5)|BIT(4)|BIT(3))
#define SGM41513_REG0B_PN_SHIFT 3
+
+#define SGM41513_REG0E 0x0E
+
#define SGM41513_REG_VERS 0x03
#define SGM41513_REG_MAX 0x10
@@ -177,6 +183,14 @@
short level; /*in percent(0..100%)*/
};
+struct sgm41513_charge_current_limit{
+ int temp_grade;
+ short temp_voltage_above; /* in mV - specify -1 for not set */
+ short temp_voltage_below; /* in mV - specify -1 for not set */
+ short current_limit; /* in mA */
+ short max_voltage; /* in mV - specify -1 for not set*/
+};
+
struct sgm41513_platform_data {
unsigned int gpio_int; /* GPIO pin that's connected to INT# */
gpio_func_id gpio_int_fun_sel;
@@ -186,6 +200,12 @@
int charging_size;
struct sgm41513_bat_calibration *discharging;
int discharging_size;
+ struct sgm41513_charge_current_limit *temp_current_map;
+ int temp_current_map_size;
+ int max_charge_voltage; /* in mV */
+ int max_input_current; /* in mA */
+ int pre_charge_current; /* in mA */
+ int terminate_charge_current; /* in mA */
bool ts_flag;
bool boost_flag;
unsigned int boost_cur_gpio1;
diff --git a/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux b/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
index 32c2702..9c58637 100755
--- a/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
+++ b/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
@@ -1360,8 +1360,7 @@
# CONFIG_W1 is not set
CONFIG_POWER_SUPPLY=y
CONFIG_POWER_SUPPLY_DEBUG=y
-CONFIG_CHARGER_AW3215=y
-#CONFIG_CHARGER_SGM41513 is not set
+CONFIG_CHARGER_SGM41513=y
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
CONFIG_WATCHDOG=y
diff --git a/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c b/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c
index 584cb2d..8caac69 100755
--- a/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c
+++ b/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c
@@ -229,11 +229,10 @@
zDrvGpio_SetDirection(GPIO120,GPIO_OUT);
zDrvGpio_SetOutputValue(GPIO120,GPIO_LOW);
-
- zDrvGpio_PullUpDown(GPIO27, 0);
- zDrvGpio_SetFunc(GPIO27,GPIO27_GPIO27);
- zDrvGpio_SetDirection(GPIO27,GPIO_OUT);
- zDrvGpio_SetOutputValue(GPIO27,GPIO_LOW);
+ // zDrvGpio_PullUpDown(GPIO27, 0);
+ // zDrvGpio_SetFunc(GPIO27,GPIO27_GPIO27);
+ // zDrvGpio_SetDirection(GPIO27,GPIO_OUT);
+ // zDrvGpio_SetOutputValue(GPIO27,GPIO_LOW);
//you.chen@20250708 temp support switch card by Analog Switch IC -- begin
//zDrvGpio_PullUpDown(GPIO49, GPIO_PULL_UP);
@@ -258,21 +257,21 @@
zDrvGpio_SetFunc(GPIO52,GPIO52_GPIO52);
zDrvGpio_SetDirection(GPIO52,GPIO_IN);
- zDrvGpio_PullUpDown(GPIO125, GPIO_PULL_DOWN);
+ zDrvGpio_PullUpDown(GPIO125, GPIO_PULL_UP);
zDrvGpio_SetFunc(GPIO125,GPIO125_GPIO125);
zDrvGpio_SetDirection(GPIO125,GPIO_IN);
- zDrvGpio_PullUpDown(GPIO36, 0);
- zDrvGpio_SetFunc(GPIO36,GPIO36_GPIO36);
- zDrvGpio_SetDirection(GPIO36, GPIO_OUT);
- if (GPIO_HIGH == zDrvGpio_GetInputValue(GPIO125))
- {
- zDrvGpio_SetOutputValue(GPIO36,GPIO_HIGH);
- }
- else
- {
- zDrvGpio_SetOutputValue(GPIO36, GPIO_LOW);
- }
+ // zDrvGpio_PullUpDown(GPIO36, 0);
+ // zDrvGpio_SetFunc(GPIO36,GPIO36_GPIO36);
+ // zDrvGpio_SetDirection(GPIO36, GPIO_OUT);
+ // if (GPIO_HIGH == zDrvGpio_GetInputValue(GPIO125))
+ // {
+ // zDrvGpio_SetOutputValue(GPIO36,GPIO_HIGH);
+ // }
+ // else
+ // {
+ // zDrvGpio_SetOutputValue(GPIO36, GPIO_LOW);
+ // }
zDrvGpio_PullUpDown(GPIO121, 0);
zDrvGpio_SetFunc(GPIO121,GPIO121_GPIO121);