aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/battery/max77693_charger.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/battery/max77693_charger.c')
-rw-r--r--drivers/battery/max77693_charger.c619
1 files changed, 488 insertions, 131 deletions
diff --git a/drivers/battery/max77693_charger.c b/drivers/battery/max77693_charger.c
index c17bbac..8609e6e 100644
--- a/drivers/battery/max77693_charger.c
+++ b/drivers/battery/max77693_charger.c
@@ -100,11 +100,26 @@
/* MAX77693_CHG_REG_CHG_CNFG_02 */
#define MAX77693_CHG_CC 0x3F
+/* MAX77693_CHG_REG_CHG_CNFG_03 */
+#define MAX77693_TO_ITH_MASK 0x06
+#define MAX77693_TO_ITH_SHIFT 0
+#define MAX77693_TO_TIME_MASK 0x38
+#define MAX77693_TO_TIME_SHIFT 3
+
/* MAX77693_CHG_REG_CHG_CNFG_04 */
#define MAX77693_CHG_MINVSYS_MASK 0xE0
#define MAX77693_CHG_MINVSYS_SHIFT 5
-#define MAX77693_CHG_PRM_MASK 0x1F
-#define MAX77693_CHG_PRM_SHIFT 0
+#define MAX77693_CHG_MINVSYS_3_6V 0x06
+#define MAX77693_CHG_CV_PRM_MASK 0x1F
+#define MAX77693_CHG_CV_PRM_SHIFT 0
+#define MAX77693_CHG_CV_PRM_4_20V 0x16
+#define MAX77693_CHG_CV_PRM_4_35V 0x1D
+#define MAX77693_CHG_CV_PRM_4_40V 0x1F
+
+/* MAX77693_CHG_REG_CHG_CNFG_06 */
+#define MAX77693_CHG_CHGPROT 0x0C
+#define MAX77693_CHG_CHGPROT_SHIFT 2
+#define MAX77693_CHG_CHGPROT_UNLOCK 0x03
/* MAX77693_CHG_REG_CHG_CNFG_09 */
#define MAX77693_CHG_CHGIN_LIM 0x7F
@@ -126,6 +141,13 @@
/* irq */
#define IRQ_DEBOUNCE_TIME 20 /* msec */
+/* charger unlock */
+#define CHG_UNLOCK_RETRY 10
+#define CHG_UNLOCK_DELAY 100
+
+/* power stabe guarantee */
+#define STABLE_POWER_DELAY 500
+
/* charger type detection */
#define DET_ERR_RETRY 5
#define DET_ERR_DELAY 200
@@ -138,8 +160,9 @@
/* soft regulation */
#define SW_REG_CURR_STEP_MA 100
-#define SW_REG_START_DELAY 1000
-#define SW_REG_STEP_DELAY 500
+#define SW_REG_CURR_MIN_MA 100
+#define SW_REG_START_DELAY 500
+#define SW_REG_STEP_DELAY 50
struct max77693_charger_data {
struct max77693_dev *max77693;
@@ -162,6 +185,9 @@ struct max77693_charger_data {
unsigned int battery_state;
unsigned int battery_present;
unsigned int cable_type;
+ unsigned int cable_sub_type;
+ unsigned int cable_pwr_type;
+ unsigned int dock_type;
unsigned int charging_current;
unsigned int vbus_state;
@@ -174,6 +200,7 @@ struct max77693_charger_data {
/* software regulation */
bool soft_reg_state;
int soft_reg_current;
+ bool soft_reg_ing;
/* unsufficient power */
bool reg_loop_deted;
@@ -216,39 +243,35 @@ static void max77693_dump_reg(struct max77693_charger_data *chg_data)
}
#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)
-static int max77693_is_topoff_state(struct max77693_charger_data *chg_data)
+static bool max77693_charger_unlock(struct max77693_charger_data *chg_data);
+static void max77693_charger_reg_init(struct max77693_charger_data *chg_data);
+
+static void check_charger_unlock_state(struct max77693_charger_data *chg_data)
{
struct i2c_client *i2c = chg_data->max77693->i2c;
- int state;
- u8 reg_data;
+ bool need_reg_init = false;
pr_debug("%s\n", __func__);
- max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_DTLS_01, &reg_data);
- reg_data = ((reg_data & MAX77693_CHG_DTLS) >> MAX77693_CHG_DTLS_SHIFT);
- pr_debug("%s: CHG_DTLS(0x%02x)\n", __func__, reg_data);
-
- if (reg_data == 0x3 || reg_data == 0x4)
- return 1;
- else
- return 0;
+ need_reg_init = max77693_charger_unlock(chg_data);
+ if (need_reg_init) {
+ pr_err("%s: charger locked state, reg init\n", __func__);
+ max77693_charger_reg_init(chg_data);
+ }
}
+#endif
-static bool check_charger_unlock_state(struct max77693_charger_data *chg_data)
+static int max77693_get_topoff_state(struct max77693_charger_data *chg_data)
{
struct i2c_client *i2c = chg_data->max77693->i2c;
u8 reg_data;
pr_debug("%s\n", __func__);
- max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_06, &reg_data);
- pr_debug("%s: chgprot = %d\n", __func__, reg_data);
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_DTLS_01, &reg_data);
+ reg_data = ((reg_data & MAX77693_CHG_DTLS) >> MAX77693_CHG_DTLS_SHIFT);
+ pr_debug("%s: CHG_DTLS(0x%02x)\n", __func__, reg_data);
- if ((reg_data&0x0C) != 0x0C) {
- pr_info("%s: NOT unlock!(%d)\n", __func__, reg_data);
- return false;
- } else
- return true;
+ return (reg_data == 0x4);
}
-#endif
static int max77693_get_battery_present(struct max77693_charger_data *chg_data)
{
@@ -348,9 +371,9 @@ static int max77693_get_charger_state(struct max77693_charger_data *chg_data)
case 0x0:
case 0x1:
case 0x2:
- case 0x3:
state = POWER_SUPPLY_STATUS_CHARGING;
break;
+ case 0x3:
case 0x4:
state = POWER_SUPPLY_STATUS_FULL;
break;
@@ -378,7 +401,7 @@ static void max77693_set_charger_state(struct max77693_charger_data *chg_data,
{
struct i2c_client *i2c = chg_data->max77693->i2c;
u8 reg_data;
- pr_debug("%s: enable=%d\n", __func__, enable);
+ pr_debug("%s: enable(%d)\n", __func__, enable);
max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_00, &reg_data);
@@ -396,7 +419,7 @@ static void max77693_set_buck(struct max77693_charger_data *chg_data,
{
struct i2c_client *i2c = chg_data->max77693->i2c;
u8 reg_data;
- pr_debug("%s: enable=%d\n", __func__, enable);
+ pr_debug("%s: enable(%d)\n", __func__, enable);
max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_00, &reg_data);
@@ -434,25 +457,22 @@ void max77693_set_input_current(struct max77693_charger_data *chg_data,
int step;
pr_debug("%s: set input current as %dmA\n", __func__, set_current);
+ mutex_lock(&chg_data->ops_lock);
#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)
- if (!check_charger_unlock_state(chg_data))
- pr_err("%s: charger NOT unlock state!!!\n", __func__);
+ check_charger_unlock_state(chg_data);
#endif
if (set_current == OFF_CURR) {
- pr_debug("%s: buck off current(%d)\n", __func__, set_current);
- max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, 0);
-
- max77693_set_buck(chg_data, DISABLE);
+ max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, set_current);
if (chg_data->soft_reg_state == true) {
pr_info("%s: exit soft regulation loop\n", __func__);
chg_data->soft_reg_state = false;
}
+ mutex_unlock(&chg_data->ops_lock);
return;
- } else
- max77693_set_buck(chg_data, ENABLE);
+ }
/* Set input current limit */
if (chg_data->soft_reg_state) {
@@ -460,8 +480,9 @@ void max77693_set_input_current(struct max77693_charger_data *chg_data,
chg_data->soft_reg_current);
in_curr = max77693_get_input_current(chg_data);
if (in_curr == chg_data->soft_reg_current) {
- pr_info("%s: same input current: %dmA\n",
+ pr_debug("%s: same input current: %dmA\n",
__func__, in_curr);
+ mutex_unlock(&chg_data->ops_lock);
return;
}
set_curr_reg = (chg_data->soft_reg_current / 20);
@@ -489,6 +510,8 @@ void max77693_set_input_current(struct max77693_charger_data *chg_data,
} while (now_curr_reg < set_curr_reg);
max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, set_curr_reg);
+
+ mutex_unlock(&chg_data->ops_lock);
}
int max77693_get_charge_current(struct max77693_charger_data *chg_data)
@@ -516,8 +539,7 @@ void max77693_set_charge_current(struct max77693_charger_data *chg_data,
pr_debug("%s: set charge current as %dmA\n", __func__, set_current);
#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)
- if (!check_charger_unlock_state(chg_data))
- pr_err("%s: charger NOT unlock state!!!\n", __func__);
+ check_charger_unlock_state(chg_data);
#endif
max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_02, &reg_data);
@@ -593,6 +615,7 @@ static int max77693_get_dock_type(struct max77693_charger_data *chg_data)
int state = POWER_SUPPLY_TYPE_BATTERY;
u8 reg_data;
int muic_cb_typ;
+ u8 dtls_00, chgin_dtls = 0;
u8 mu_st2, vbvolt = 0;
pr_debug("%s\n", __func__);
@@ -601,7 +624,19 @@ static int max77693_get_dock_type(struct max77693_charger_data *chg_data)
/* dock detect from muic */
if ((muic_cb_typ == CABLE_TYPE_CARDOCK_MUIC) ||
- (muic_cb_typ == CABLE_TYPE_DESKDOCK_MUIC)) {
+ (muic_cb_typ == CABLE_TYPE_DESKDOCK_MUIC) ||
+ (muic_cb_typ == CABLE_TYPE_SMARTDOCK_MUIC) ||
+ (muic_cb_typ == CABLE_TYPE_SMARTDOCK_TA_MUIC) ||
+ (muic_cb_typ == CABLE_TYPE_SMARTDOCK_USB_MUIC) ||
+ (muic_cb_typ == CABLE_TYPE_AUDIODOCK_MUIC)) {
+
+ chg_data->dock_type = muic_cb_typ;
+
+ /* read chgin, but not use */
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_DTLS_00, &dtls_00);
+ chgin_dtls = ((dtls_00 & MAX77693_CHGIN_DTLS) >>
+ MAX77693_CHGIN_DTLS_SHIFT);
/* check vbvolt */
max77693_read_reg(chg_data->max77693->muic,
@@ -609,8 +644,8 @@ static int max77693_get_dock_type(struct max77693_charger_data *chg_data)
vbvolt = ((mu_st2 & MAX77693_VBVOLT) >>
MAX77693_VBVOLT_SHIFT);
- pr_info("%s: dock detected(%d), vbvolt(%d)\n", __func__,
- muic_cb_typ, vbvolt);
+ pr_info("%s: dock detected(%d), vbvolt(%d), chgin(0x%02x)\n",
+ __func__, muic_cb_typ, vbvolt, chgin_dtls);
if (vbvolt == ENABLE) {
max77693_read_reg(chg_data->max77693->i2c,
@@ -627,9 +662,11 @@ static int max77693_get_dock_type(struct max77693_charger_data *chg_data)
MAX77693_CHG_REG_CHG_CNFG_00, reg_data);
state = POWER_SUPPLY_TYPE_BATTERY;
}
- } else
+ } else {
pr_debug("%s: dock not detected(%d), vbvolt(%d)\n", __func__,
muic_cb_typ, vbvolt);
+ chg_data->dock_type = 0;
+ }
return state;
}
@@ -640,16 +677,17 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data)
u8 reg_data, mu_adc, mu_adc1k, otg;
u8 dtls_00, chgin_dtls;
u8 mu_st2, chgdetrun, vbvolt, chgtyp, dxovp;
+ int muic_cb_typ;
bool wc_state;
bool retry_det, chg_det_erred;
+ bool otg_detected = false;
int retry_cnt = 0;
pr_debug("%s\n", __func__);
mutex_lock(&chg_data->ops_lock);
#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)
- if (!check_charger_unlock_state(chg_data))
- pr_err("%s: charger NOT unlock state!!!\n", __func__);
+ check_charger_unlock_state(chg_data);
#endif
/* If OTG enabled, skip detecting charger cable */
@@ -666,10 +704,28 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data)
pr_debug("%s: CHG_REG_CHG_CNFG_00(0x%02x)\n", __func__, reg_data);
otg = reg_data & MAX77693_MODE_OTG;
- if (otg || (mu_adc == 0x00 && !mu_adc1k)) {
+#ifdef CONFIG_MACH_GC1
+ /* In Factory mode using anyway Jig to switch between USB <--> UART
+ * sees a momentary 301K resistance as that of an OTG. Disabling
+ * charging INTRS now can lead to USB and MTP drivers not getting
+ * recognized in in subsequent switches.
+ * Factory Mode BOOT(on) USB
+ */
+ if (mu_adc == 0x19) {
+ pr_info("%s: jig usb cable(adc(0x%x))\n", __func__, mu_adc);
+ state = POWER_SUPPLY_TYPE_USB;
+ goto chg_det_finish;
+ }
+#endif
+
+ muic_cb_typ = max77693_muic_get_charging_type();
+ /* if type detection by otg, do not otg check */
+ if ((muic_cb_typ != CABLE_TYPE_AUDIODOCK_MUIC) &&
+ (((otg || (mu_adc == 0x00 && !mu_adc1k))))) {
pr_info("%s: otg enabled(otg(0x%x), adc(0x%x))\n",
__func__, otg, mu_adc);
state = POWER_SUPPLY_TYPE_BATTERY;
+ otg_detected = true;
goto chg_det_finish;
}
@@ -740,13 +796,23 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data)
/* check D+/D- ovp */
dxovp = ((mu_st2 & MAX77693_DXOVP) >>
MAX77693_DXOVP_SHIFT);
- if (dxovp) {
+ if ((vbvolt == 0x1) && (dxovp)) {
pr_err("%s: D+/D- ovp state\n", __func__);
+
+ /* disable CHGIN protection FETs */
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_CNFG_00,
+ &reg_data);
+ reg_data |= CHG_CNFG_00_DIS_MUIC_CTRL_MASK;
+ max77693_write_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_CNFG_00,
+ reg_data);
+
chg_det_erred = true;
- state = POWER_SUPPLY_TYPE_USB;
+ state = POWER_SUPPLY_TYPE_MAINS;
goto chg_det_finish;
} else {
- pr_err("%s: async power and chgtyp\n", __func__);
+ pr_err("%s: async power & chgtyp\n", __func__);
goto chg_det_err;
}
}
@@ -787,7 +853,6 @@ chg_det_err:
state = POWER_SUPPLY_TYPE_BATTERY;
break;
case 0x1: /* USB cabled */
- case 0x4: /* Apple 500mA charger */
state = POWER_SUPPLY_TYPE_USB;
#ifdef CONFIG_BATTERY_WPC_CHARGER
wc_state = max77693_get_wc_state(chg_data);
@@ -799,6 +864,7 @@ chg_det_err:
state = POWER_SUPPLY_TYPE_USB_CDP;
break;
case 0x3: /* Dedicated charger(up to 1.5A) */
+ case 0x4: /* Apple 500mA charger */
case 0x5: /* Apple 1A or 2A charger */
case 0x6: /* Special charger */
state = POWER_SUPPLY_TYPE_MAINS;
@@ -812,9 +878,20 @@ chg_det_finish:
if (chg_det_erred)
pr_err("%s: cable type(%d)\n", __func__, state);
- /* if cable is nothing, clear soft reg state flag */
- if (state == POWER_SUPPLY_TYPE_BATTERY)
+ /* if cable is nothing,,, */
+ if (state == POWER_SUPPLY_TYPE_BATTERY) {
+ if (!otg_detected) {
+ /* enable CHGIN protection FETs */
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_CNFG_00, &reg_data);
+ reg_data &= ~CHG_CNFG_00_DIS_MUIC_CTRL_MASK;
+ max77693_write_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_CNFG_00, reg_data);
+ }
+
+ /* clear soft reg state flag */
chg_data->soft_reg_state = false;
+ }
chg_data->cable_type = state;
@@ -888,31 +965,122 @@ static int max77693_get_battery_state(struct max77693_charger_data *chg_data)
return state;
}
+/* extended online type */
+static int max77693_get_online_type(struct max77693_charger_data *chg_data)
+{
+ int m_typ;
+ int state = 0;
+ pr_info("%s\n", __func__);
+
+ m_typ = max77693_get_cable_type(chg_data);
+
+ pr_info("%s: main(%d), sub(%d), pwr(%d)\n", __func__, m_typ,
+ chg_data->cable_sub_type,
+ chg_data->cable_pwr_type);
+
+ state = ((m_typ << ONLINE_TYPE_MAIN_SHIFT) |
+ (chg_data->cable_sub_type << ONLINE_TYPE_SUB_SHIFT) |
+ (chg_data->cable_pwr_type << ONLINE_TYPE_PWR_SHIFT));
+
+ pr_info("%s: online(0x%08x)\n", __func__, state);
+
+ return state;
+}
+
+void max77693_set_online_type(struct max77693_charger_data *chg_data, int data)
+{
+ int m_typ, s_typ, p_typ;
+ pr_info("%s: type(0x%08x)\n", __func__, data);
+
+ /* | 31-24: RSVD | 23-16: MAIN TYPE |
+ 15-8: SUB TYPE | 7-0: POWER TYPE | */
+ data &= ~(ONLINE_TYPE_RSVD_MASK);
+ m_typ = ((data & ONLINE_TYPE_MAIN_MASK) >> ONLINE_TYPE_MAIN_SHIFT);
+ chg_data->cable_sub_type = s_typ =
+ ((data & ONLINE_TYPE_SUB_MASK) >> ONLINE_TYPE_SUB_SHIFT);
+ chg_data->cable_pwr_type = p_typ =
+ ((data & ONLINE_TYPE_PWR_MASK) >> ONLINE_TYPE_PWR_SHIFT);
+ pr_info("%s: main(%d), sub(%d), pwr(%d)\n", __func__,
+ m_typ, s_typ, p_typ);
+
+ cancel_delayed_work(&chg_data->update_work);
+ wake_lock(&chg_data->update_wake_lock);
+ schedule_delayed_work(&chg_data->update_work,
+ msecs_to_jiffies(STABLE_POWER_DELAY));
+}
+
/* get cable type from muic */
void max77693_set_muic_cb_type(struct max77693_charger_data *chg_data, int data)
{
pr_info("%s: muic cable type(%d)\n", __func__, data);
+#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)
+ check_charger_unlock_state(chg_data);
+#endif
+
cancel_delayed_work(&chg_data->update_work);
wake_lock(&chg_data->update_wake_lock);
- schedule_delayed_work(&chg_data->update_work, msecs_to_jiffies(500));
+ schedule_delayed_work(&chg_data->update_work,
+ msecs_to_jiffies(STABLE_POWER_DELAY));
}
-static void max77693_charger_reg_init(struct max77693_charger_data *chg_data)
+static bool max77693_charger_unlock(struct max77693_charger_data *chg_data)
{
struct i2c_client *i2c = chg_data->max77693->i2c;
u8 reg_data;
+ u8 chgprot;
+ int retry_cnt = 0;
+ bool need_init = false;
pr_debug("%s\n", __func__);
- /* unlock charger setting protect */
- reg_data = (0x03 << 2);
- max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_06, reg_data);
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_06, &reg_data);
+ chgprot = ((reg_data & MAX77693_CHG_CHGPROT) >>
+ MAX77693_CHG_CHGPROT_SHIFT);
+
+ if (chgprot == MAX77693_CHG_CHGPROT_UNLOCK) {
+ pr_debug("%s: unlocked state, return\n", __func__);
+ need_init = false;
+ goto unlock_finish;
+ }
+
+ do {
+ max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_06,
+ (MAX77693_CHG_CHGPROT_UNLOCK <<
+ MAX77693_CHG_CHGPROT_SHIFT));
+
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_06, &reg_data);
+ chgprot = ((reg_data & MAX77693_CHG_CHGPROT) >>
+ MAX77693_CHG_CHGPROT_SHIFT);
+
+ if (chgprot != MAX77693_CHG_CHGPROT_UNLOCK) {
+ pr_err("%s: unlock err, chgprot(0x%x), retry(%d)\n",
+ __func__, chgprot, retry_cnt);
+ msleep(CHG_UNLOCK_DELAY);
+ } else {
+ pr_info("%s: unlock success, chgprot(0x%x)\n",
+ __func__, chgprot);
+ need_init = true;
+ break;
+ }
+ } while ((chgprot != MAX77693_CHG_CHGPROT_UNLOCK) &&
+ (++retry_cnt < CHG_UNLOCK_RETRY));
+
+unlock_finish:
+ return need_init;
+}
+
+static void max77693_charger_reg_init(struct max77693_charger_data *chg_data)
+{
+ struct i2c_client *i2c = chg_data->max77693->i2c;
+ u8 reg_data;
+ pr_debug("%s\n", __func__);
/*
* fast charge timer 10hrs
* restart threshold disable
* pre-qual charge enable(default)
*/
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_01, &reg_data);
reg_data = (0x04 << 0) | (0x03 << 4);
max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_01, reg_data);
@@ -920,6 +1088,7 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data)
* charge current 466mA(default)
* otg current limit 900mA
*/
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_02, &reg_data);
reg_data = (1 << 7);
max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_02, reg_data);
@@ -927,51 +1096,93 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data)
* top off current 100mA
* top off timer 0min
*/
- if (chg_data->max77693->pmic_rev == MAX77693_REV_PASS1)
- reg_data = (0x03 << 0); /* 125mA */
- else
- reg_data = (0x00 << 0); /* 100mA */
-
- reg_data |= (0x00 << 3);
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_03, &reg_data);
+ if (chg_data->max77693->pmic_rev == MAX77693_REV_PASS1) {
+ reg_data = (0x03 << 0); /* 125mA */
+ reg_data |= (0x00 << 3); /* 0min */
+ } else {
+#if defined(USE_2STEP_TERM) /* now only T0 */
+ reg_data = (0x04 << 0); /* 200mA */
+ reg_data |= (0x04 << 3); /* 40min */
+#else
+#if defined(CONFIG_MACH_GC1)
+ reg_data = (0x02 << 0); /* 150mA */
+ reg_data |= (0x00 << 3); /* 0min */
+#else /* M0, C1,,, */
+ reg_data = (0x00 << 0); /* 100mA */
+ reg_data |= (0x00 << 3); /* 0min */
+#endif
+#endif
+ }
max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_03, reg_data);
/*
* cv voltage 4.2V or 4.35V
* MINVSYS 3.6V(default)
*/
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_04, &reg_data);
+ reg_data &= (~MAX77693_CHG_MINVSYS_MASK);
+ reg_data |= (MAX77693_CHG_MINVSYS_3_6V << MAX77693_CHG_MINVSYS_SHIFT);
+ reg_data &= (~MAX77693_CHG_CV_PRM_MASK);
+#if defined(CONFIG_MACH_M0)
if ((system_rev != 3) && (system_rev >= 1))
- reg_data = (0xDD << 0);
+ reg_data |= (MAX77693_CHG_CV_PRM_4_35V << 0);
else
- reg_data = (0xD6 << 0);
+ reg_data |= (MAX77693_CHG_CV_PRM_4_20V << 0);
+#else /* C1, C2, M3, T0, ... */
+ reg_data |= (MAX77693_CHG_CV_PRM_4_35V << 0);
+#endif
/*
* For GC1 Model, MINVSYS is 3.4V.
- * For GC1 Model PRMV( Primary Charge Regn. Voltage) = 4.25V.
+ * For GC1 Model PRMV( Primary Charge Regn. Voltage) = 4.2V.
* Actual expected regulated voltage needs to be 4.2V but due to
- * internal resistance and circuit deviation we need to set the
- * benchmark a bit higher(4.25V).
+ * internal resistance and circuit deviation we might have to set the
+ * benchmark a bit higher sometimes. (4.225V now)
*/
#if defined(CONFIG_MACH_GC1)
- reg_data &= (~MAX77693_CHG_PRM_MASK);
- reg_data |= (0x18 << MAX77693_CHG_PRM_SHIFT);
+ reg_data &= (~MAX77693_CHG_CV_PRM_MASK);
+ reg_data |= (0x16 << MAX77693_CHG_CV_PRM_SHIFT);
reg_data &= (~MAX77693_CHG_MINVSYS_MASK);
reg_data |= (0x4 << MAX77693_CHG_MINVSYS_SHIFT);
#endif
-
pr_info("%s: battery cv voltage %s, (sysrev %d)\n", __func__,
- (((reg_data & MAX77693_CHG_PRM_MASK) == \
- (0x1D << MAX77693_CHG_PRM_SHIFT)) ? "4.35V" : "4.2V"),
- system_rev);
-
+ (((reg_data & MAX77693_CHG_CV_PRM_MASK) == \
+ (MAX77693_CHG_CV_PRM_4_35V << MAX77693_CHG_CV_PRM_SHIFT)) ?
+ "4.35V" : "4.2V"), system_rev);
max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_04, reg_data);
- /* VBYPSET 5V */
- reg_data = 0x50;
- max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_11, reg_data);
-
max77693_dump_reg(chg_data);
}
+static void max77693_reduce_input(struct max77693_charger_data *chg_data,
+ unsigned int curr)
+{
+ struct i2c_client *i2c = chg_data->max77693->i2c;
+ u8 reg_data;
+ pr_debug("%s: reduce %dmA\n", __func__, curr);
+
+ max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, &reg_data);
+ reg_data &= MAX77693_CHG_CHGIN_LIM;
+ chg_data->soft_reg_current = reg_data * 20;
+
+ if (chg_data->soft_reg_current < curr) {
+ pr_err("%s: recude curr(%d) is under now curr(%d)\n", __func__,
+ curr, chg_data->soft_reg_current);
+ return;
+ }
+
+ chg_data->soft_reg_current -= curr;
+ chg_data->soft_reg_current = max(chg_data->soft_reg_current,
+ SW_REG_CURR_MIN_MA);
+ pr_info("%s: %dmA to %dmA\n", __func__,
+ reg_data * 20, chg_data->soft_reg_current);
+
+ reg_data = (chg_data->soft_reg_current / 20);
+ pr_debug("%s: reg_data(0x%02x)\n", __func__, reg_data);
+ max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, reg_data);
+}
+
static void max77693_update_work(struct work_struct *work)
{
struct max77693_charger_data *chg_data = container_of(work,
@@ -1010,8 +1221,6 @@ static void max77693_update_work(struct work_struct *work)
switch (chg_data->irq - chg_data->max77693->irq_base) {
case MAX77693_CHG_IRQ_CHGIN_I:
- /* guarantee detection time */
- mdelay(100);
vbus_state = max77693_get_vbus_state(chg_data);
if (vbus_state == POWER_SUPPLY_VBUS_WEAK) {
pr_info("%s: vbus weak\n", __func__);
@@ -1039,49 +1248,91 @@ static void max77693_softreg_work(struct work_struct *work)
struct max77693_charger_data *chg_data = container_of(work,
struct max77693_charger_data,
softreg_work.work);
- struct i2c_client *i2c = chg_data->max77693->i2c;
- u8 reg_data;
- u8 int_ok, dtls_02, byp_dtls;
- pr_info("%s\n", __func__);
+ u8 int_ok;
+ u8 dtls_00, chgin_dtls;
+ u8 dtls_01, chg_dtls;
+ u8 dtls_02, byp_dtls;
+ u8 mu_st2, vbvolt;
+ u8 cnfg_09;
+ int in_curr = 0;
+ pr_debug("%s\n", __func__);
mutex_lock(&chg_data->ops_lock);
+ /* charger */
max77693_read_reg(chg_data->max77693->i2c,
- MAX77693_CHG_REG_CHG_INT_OK,
- &int_ok);
-
+ MAX77693_CHG_REG_CHG_INT_OK, &int_ok);
max77693_read_reg(chg_data->max77693->i2c,
- MAX77693_CHG_REG_CHG_DTLS_02,
- &dtls_02);
+ MAX77693_CHG_REG_CHG_DTLS_00, &dtls_00);
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_DTLS_01, &dtls_01);
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_DTLS_02, &dtls_02);
+ chgin_dtls = ((dtls_00 & MAX77693_CHGIN_DTLS) >>
+ MAX77693_CHGIN_DTLS_SHIFT);
+ chg_dtls = ((dtls_01 & MAX77693_CHG_DTLS) >>
+ MAX77693_CHG_DTLS_SHIFT);
byp_dtls = ((dtls_02 & MAX77693_BYP_DTLS) >>
MAX77693_BYP_DTLS_SHIFT);
- pr_info("%s: INT_OK(0x%02x), BYP_DTLS(0x%02x)\n",
- __func__, int_ok, byp_dtls);
- if (byp_dtls & MAX77693_BYP_DTLS3) {
- pr_info("%s: unstable power state for %dms\n", __func__,
- SW_REG_START_DELAY);
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_CNFG_09, &cnfg_09);
+ cnfg_09 &= MAX77693_CHG_CHGIN_LIM;
+ in_curr = cnfg_09 * 20;
+
+ /* muic */
+ max77693_read_reg(chg_data->max77693->muic,
+ MAX77693_MUIC_REG_STATUS2, &mu_st2);
+ vbvolt = ((mu_st2 & MAX77693_VBVOLT) >>
+ MAX77693_VBVOLT_SHIFT);
+
+ pr_info("%s: INT_OK(0x%x), CHGIN(0x%x), CHG(0x%x), "
+ "BYP(0x%x), ST2(0x%x), IN_CURR(%d)\n", __func__,
+ int_ok, chgin_dtls, chg_dtls,
+ byp_dtls, mu_st2, in_curr);
+
+ if ((in_curr > SW_REG_CURR_STEP_MA) && (chg_dtls != 0x8) &&
+ ((byp_dtls & MAX77693_BYP_DTLS3) ||
+ ((chgin_dtls != 0x3) && (vbvolt == 0x1)))) {
+ pr_info("%s: unstable power\n", __func__);
+
+ /* set soft regulation progress */
+ chg_data->soft_reg_ing = true;
+
/* enable soft regulation loop */
chg_data->soft_reg_state = true;
- max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, &reg_data);
- reg_data &= MAX77693_CHG_CHGIN_LIM;
- chg_data->soft_reg_current = reg_data * 20;
- chg_data->soft_reg_current -= SW_REG_CURR_STEP_MA;
- chg_data->soft_reg_current = max(chg_data->soft_reg_current, 0);
- pr_info("%s: %dmA to %dmA\n", __func__,
- reg_data * 20, chg_data->soft_reg_current);
+ max77693_reduce_input(chg_data, SW_REG_CURR_STEP_MA);
- reg_data = (chg_data->soft_reg_current / 20);
- pr_debug("%s: reg_data(0x%02x)\n", __func__, reg_data);
- max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, reg_data);
+ /* cancel update wq */
+ cancel_delayed_work(&chg_data->update_work);
+ /* schedule softreg wq */
wake_lock(&chg_data->softreg_wake_lock);
schedule_delayed_work(&chg_data->softreg_work,
msecs_to_jiffies(SW_REG_STEP_DELAY));
} else {
- pr_info("%s: (recover) stable power\n", __func__);
+ /* check cable detached */
+ if ((!in_curr) ||
+ ((chgin_dtls == 0x0) && (vbvolt == 0x0)) ||
+ ((byp_dtls == 0x0) && (chg_dtls == 0x8))) {
+ pr_info("%s: maybe cable is detached\n", __func__);
+
+ cancel_delayed_work(&chg_data->update_work);
+ wake_lock(&chg_data->update_wake_lock);
+ schedule_delayed_work(&chg_data->update_work,
+ msecs_to_jiffies(STABLE_POWER_DELAY));
+ }
+
+ /* for margin */
+ if (chg_data->soft_reg_ing == true) {
+ pr_info("%s: stable power, reduce 1 more step "
+ "for margin\n", __func__);
+ max77693_reduce_input(chg_data, SW_REG_CURR_STEP_MA);
+ chg_data->soft_reg_ing = false;
+ }
+
wake_unlock(&chg_data->softreg_wake_lock);
}
@@ -1096,7 +1347,8 @@ static enum power_supply_property max77693_charger_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CURRENT_MAX,
- POWER_SUPPLY_PROP_CURRENT_NOW
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL
};
static int max77693_charger_get_property(struct power_supply *psy,
@@ -1121,7 +1373,11 @@ static int max77693_charger_get_property(struct power_supply *psy,
val->intval = max77693_get_battery_present(chg_data);
break;
case POWER_SUPPLY_PROP_ONLINE:
+#if defined(EXTENDED_ONLINE_TYPE)
+ val->intval = max77693_get_online_type(chg_data);
+#else
val->intval = max77693_get_cable_type(chg_data);
+#endif
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
val->intval = max77693_get_input_current(chg_data);
@@ -1129,11 +1385,9 @@ static int max77693_charger_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = max77693_get_charge_current(chg_data);
break;
-#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC)
case POWER_SUPPLY_PROP_CHARGE_FULL:
- val->intval = max77693_is_topoff_state(chg_data);
+ val->intval = max77693_get_topoff_state(chg_data);
break;
-#endif
default:
return -EINVAL;
}
@@ -1154,7 +1408,15 @@ static int max77693_charger_set_property(struct power_supply *psy,
max77693_set_charger_state(chg_data, val->intval);
break;
case POWER_SUPPLY_PROP_ONLINE:
+#if !defined(USE_CHGIN_INTR)
max77693_set_muic_cb_type(chg_data, val->intval);
+#else
+#if defined(EXTENDED_ONLINE_TYPE)
+ max77693_set_online_type(chg_data, val->intval);
+#else
+ return -EINVAL;
+#endif
+#endif
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
max77693_set_input_current(chg_data, val->intval);
@@ -1172,7 +1434,8 @@ static int max77693_charger_set_property(struct power_supply *psy,
static irqreturn_t max77693_bypass_irq(int irq, void *data)
{
struct max77693_charger_data *chg_data = data;
- u8 int_ok, dtls_02;
+ bool need_reg_init = false;
+ u8 int_ok, dtls_02, cnfg_00;
u8 byp_dtls;
#ifdef CONFIG_USB_HOST_NOTIFY
struct host_notifier_platform_data *host_noti_pdata =
@@ -1182,6 +1445,13 @@ static irqreturn_t max77693_bypass_irq(int irq, void *data)
mutex_lock(&chg_data->irq_lock);
+ /* check and unlock */
+ need_reg_init = max77693_charger_unlock(chg_data);
+ if (need_reg_init) {
+ pr_err("%s: charger locked state, reg init\n", __func__);
+ max77693_charger_reg_init(chg_data);
+ }
+
max77693_read_reg(chg_data->max77693->i2c,
MAX77693_CHG_REG_CHG_INT_OK,
&int_ok);
@@ -1205,9 +1475,16 @@ static irqreturn_t max77693_bypass_irq(int irq, void *data)
host_state_notify(&host_noti_pdata->ndev,
NOTIFY_HOST_OVERCURRENT);
#endif
+ max77693_read_reg(chg_data->max77693->i2c,
+ MAX77693_CHG_REG_CHG_CNFG_00,
+ &cnfg_00);
+ cnfg_00 &= ~(CHG_CNFG_00_OTG_MASK
+ | CHG_CNFG_00_BOOST_MASK
+ | CHG_CNFG_00_DIS_MUIC_CTRL_MASK);
+ cnfg_00 |= CHG_CNFG_00_BUCK_MASK;
max77693_write_reg(chg_data->max77693->i2c,
MAX77693_CHG_REG_CHG_CNFG_00,
- MAX77693_MODE_DEFAULT);
+ cnfg_00);
break;
case 0x8:
pr_err("%s: chgin regulation loop is active\n", __func__);
@@ -1228,7 +1505,8 @@ static irqreturn_t max77693_bypass_irq(int irq, void *data)
cancel_delayed_work(&chg_data->update_work);
wake_lock(&chg_data->update_wake_lock);
- schedule_delayed_work(&chg_data->update_work, msecs_to_jiffies(100));
+ schedule_delayed_work(&chg_data->update_work,
+ msecs_to_jiffies(STABLE_POWER_DELAY));
mutex_unlock(&chg_data->irq_lock);
@@ -1239,13 +1517,22 @@ static irqreturn_t max77693_bypass_irq(int irq, void *data)
static irqreturn_t max77693_charger_irq(int irq, void *data)
{
struct max77693_charger_data *chg_data = data;
- u8 prev_int_ok, int_ok, dtls_00, dtls_01;
- u8 thm_dtls, chgin_dtls, chg_dtls, bat_dtls;
- u8 mu_st2;
+ bool need_reg_init = false;
+ u8 prev_int_ok, int_ok;
+ u8 dtls_00, thm_dtls, chgin_dtls;
+ u8 dtls_01, chg_dtls, bat_dtls;
+ u8 mu_st2, vbvolt;
pr_info("%s: irq(%d)\n", __func__, irq);
mutex_lock(&chg_data->irq_lock);
+ /* check and unlock */
+ need_reg_init = max77693_charger_unlock(chg_data);
+ if (need_reg_init) {
+ pr_err("%s: charger locked state, reg init\n", __func__);
+ max77693_charger_reg_init(chg_data);
+ }
+
max77693_read_reg(chg_data->max77693->i2c,
MAX77693_CHG_REG_CHG_INT_OK,
&prev_int_ok);
@@ -1283,14 +1570,36 @@ static irqreturn_t max77693_charger_irq(int irq, void *data)
/* muic */
max77693_read_reg(chg_data->max77693->muic,
MAX77693_MUIC_REG_STATUS2, &mu_st2);
+ vbvolt = ((mu_st2 & MAX77693_VBVOLT) >>
+ MAX77693_VBVOLT_SHIFT);
pr_info("%s: INT_OK(0x%x), THM(0x%x), CHGIN(0x%x), CHG(0x%x), BAT(0x%x), "
"ST2(0x%x)\n", __func__,
int_ok, thm_dtls, chgin_dtls,
chg_dtls, bat_dtls, mu_st2);
+#if defined(USE_CHGIN_INTR)
+ if (((chgin_dtls == 0x0) || (chgin_dtls == 0x1)) &&
+ (vbvolt == 0x1) && (chg_dtls != 0x8)) {
+ pr_info("%s: abnormal power state: chgin(%d), vb(%d), chg(%d)\n",
+ __func__, chgin_dtls, vbvolt, chg_dtls);
+
+ /* enable soft regulation loop */
+ chg_data->soft_reg_state = true;
+
+ /* first, reduce */
+ max77693_reduce_input(chg_data, SW_REG_CURR_STEP_MA);
+
+ /* software regulation */
+ wake_lock(&chg_data->softreg_wake_lock);
+ schedule_delayed_work(&chg_data->softreg_work,
+ msecs_to_jiffies(SW_REG_STEP_DELAY));
+ }
+#endif
+
cancel_delayed_work(&chg_data->update_work);
wake_lock(&chg_data->update_wake_lock);
- schedule_delayed_work(&chg_data->update_work, msecs_to_jiffies(500));
+ schedule_delayed_work(&chg_data->update_work,
+ msecs_to_jiffies(STABLE_POWER_DELAY));
mutex_unlock(&chg_data->irq_lock);
@@ -1301,11 +1610,19 @@ static irqreturn_t max77693_charger_irq(int irq, void *data)
static irqreturn_t wpc_charger_irq(int irq, void *data)
{
struct max77693_charger_data *chg_data = data;
+ bool need_reg_init = false;
int wc_w_state, wc_v_state, wc_v_pud_state;
pr_info("%s: irq(%d)\n", __func__, irq);
mutex_lock(&chg_data->irq_lock);
+ /* check and unlock */
+ need_reg_init = max77693_charger_unlock(chg_data);
+ if (need_reg_init) {
+ pr_err("%s: charger locked state, reg init\n", __func__);
+ max77693_charger_reg_init(chg_data);
+ }
+
wc_w_state = wc_v_state = 0;
wc_w_state = !gpio_get_value(chg_data->wc_w_gpio);
@@ -1349,7 +1666,7 @@ static irqreturn_t wpc_charger_irq(int irq, void *data)
cancel_delayed_work(&chg_data->update_work);
wake_lock(&chg_data->update_wake_lock);
schedule_delayed_work(&chg_data->update_work,
- msecs_to_jiffies(500));
+ msecs_to_jiffies(STABLE_POWER_DELAY));
}
chg_data->wc_w_state = wc_w_state;
@@ -1412,7 +1729,7 @@ static ssize_t max77693_debugfs_read_registers(struct file *filp,
if (!buf)
return -ENOMEM;
- for (i = 0xB2; i <= 0xC6; i++) {
+ for (i = 0xB0; i <= 0xC6; i++) {
max77693_read_reg(chg_data->max77693->i2c, i, &val);
len += snprintf(buf + len, PAGE_SIZE - len,
"%x=%02x", i, val);
@@ -1442,8 +1759,12 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev)
struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
int ret;
+ pr_info("%s: charger init\n", __func__);
- pr_info("%s: charger init start\n", __func__);
+ if (!pdata) {
+ pr_err("%s: no platform data\n", __func__);
+ return -ENODEV;
+ }
chg_data = kzalloc(sizeof(struct max77693_charger_data), GFP_KERNEL);
if (!chg_data)
@@ -1460,6 +1781,9 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev)
wake_lock_init(&chg_data->softreg_wake_lock, WAKE_LOCK_SUSPEND,
"charger-softreg");
+ /* unlock charger setting protect */
+ max77693_charger_unlock(chg_data);
+
chg_data->charger_pdata = pdata->charger_data;
if (!pdata->charger_data->init_data)
max77693_charger_reg_init(chg_data);
@@ -1472,6 +1796,9 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev)
chg_data->irq_charge = max77693->irq_base + MAX77693_CHG_IRQ_CHG_I;
chg_data->irq_chargin = max77693->irq_base + MAX77693_CHG_IRQ_CHGIN_I;
+ INIT_DELAYED_WORK(&chg_data->update_work, max77693_update_work);
+ INIT_DELAYED_WORK(&chg_data->softreg_work, max77693_softreg_work);
+
chg_data->charger.name = "max77693-charger",
chg_data->charger.type = POWER_SUPPLY_TYPE_BATTERY,
chg_data->charger.properties = max77693_charger_props,
@@ -1485,12 +1812,6 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev)
goto err_kfree;
}
- INIT_DELAYED_WORK_DEFERRABLE(&chg_data->update_work,
- max77693_update_work);
-
- INIT_DELAYED_WORK_DEFERRABLE(&chg_data->softreg_work,
- max77693_softreg_work);
-
ret = request_threaded_irq(chg_data->irq_bypass, NULL,
max77693_bypass_irq, 0, "bypass-irq", chg_data);
if (ret < 0)
@@ -1509,9 +1830,17 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev)
pr_err("%s: fail to request charge IRQ: %d: %d\n",
__func__, chg_data->irq_charge, ret);
+#if defined(USE_CHGIN_INTR)
+ ret = request_threaded_irq(chg_data->irq_chargin, NULL,
+ max77693_charger_irq, 0, "chargin-irq", chg_data);
+ if (ret < 0)
+ pr_err("%s: fail to request charge IRQ: %d: %d\n",
+ __func__, chg_data->irq_chargin, ret);
+#endif
+
#ifdef CONFIG_BATTERY_WPC_CHARGER
chg_data->wc_pwr_det = chg_data->charger_pdata->wc_pwr_det;
-#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1VZW) || \
+#if defined(CONFIG_MACH_M0) || \
defined(CONFIG_MACH_GRANDE) || defined(CONFIG_MACH_IRON)
if (system_rev >= 0xA)
chg_data->wc_pwr_det = true;
@@ -1520,7 +1849,7 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev)
if (system_rev >= 0x6)
chg_data->wc_pwr_det = true;
#endif
-#if defined(CONFIG_MACH_C2)
+#if defined(CONFIG_MACH_M3)
chg_data->wc_pwr_det = true;
#endif
@@ -1619,7 +1948,7 @@ wpc_init_finish:
#endif
#endif
- pr_info("%s: charger init complete\n", __func__);
+ pr_info("%s: probe complete\n", __func__);
return 0;
@@ -1657,11 +1986,14 @@ static int __devexit max77693_charger_remove(struct platform_device *pdev)
*/
#ifdef CONFIG_SLP
static u8 saved_int_mask;
+#endif
static int max77693_charger_suspend(struct device *dev)
{
struct max77693_dev *max77693 = dev_get_drvdata(dev->parent);
u8 int_mask;
+ pr_info("%s\n", __func__);
+#ifdef CONFIG_SLP
/* Save the masking value */
max77693_read_reg(max77693->i2c,
MAX77693_CHG_REG_CHG_INT_MASK,
@@ -1672,31 +2004,56 @@ static int max77693_charger_suspend(struct device *dev)
max77693_write_reg(max77693->i2c,
MAX77693_CHG_REG_CHG_INT_MASK,
int_mask);
+#else
+#if defined(USE_CHGIN_INTR)
+ /* disable chgin irq */
+ max77693_read_reg(max77693->i2c,
+ MAX77693_CHG_REG_CHG_INT_MASK,
+ &int_mask);
+ int_mask |= MAX77693_CHGIN_IM;
+ max77693_write_reg(max77693->i2c,
+ MAX77693_CHG_REG_CHG_INT_MASK,
+ int_mask);
+#endif
+#endif
return 0;
}
static int max77693_charger_resume(struct device *dev)
{
struct max77693_dev *max77693 = dev_get_drvdata(dev->parent);
+ u8 int_mask;
+ pr_info("%s\n", __func__);
+#ifdef CONFIG_SLP
/* Restore the saved masking value */
max77693_write_reg(max77693->i2c,
MAX77693_CHG_REG_CHG_INT_MASK,
saved_int_mask);
+#else
+#if defined(USE_CHGIN_INTR)
+ /* enable chgin irq */
+ max77693_read_reg(max77693->i2c,
+ MAX77693_CHG_REG_CHG_INT_MASK,
+ &int_mask);
+ int_mask &= (~MAX77693_CHGIN_IM);
+ max77693_write_reg(max77693->i2c,
+ MAX77693_CHG_REG_CHG_INT_MASK,
+ int_mask);
+#endif
+#endif
+
return 0;
}
static SIMPLE_DEV_PM_OPS(max77693_charger_pm_ops, max77693_charger_suspend,
max77693_charger_resume);
-#endif
static struct platform_driver max77693_charger_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "max77693-charger",
-#ifdef CONFIG_SLP
.pm = &max77693_charger_pm_ops,
-#endif
},
.probe = max77693_charger_probe,
.remove = __devexit_p(max77693_charger_remove),