diff --git a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_class.c b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_class.c index 7c17e62d294a..43db0af356da 100644 --- a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_class.c +++ b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_class.c @@ -221,6 +221,16 @@ int charger_dev_get_real_charger_type(struct charger_device *chg_dev, int *charg } EXPORT_SYMBOL(charger_dev_get_real_charger_type); +int charger_dev_get_qc3p_power(struct charger_device *chg_dev, int *qc3p_power) +{ + if (chg_dev != NULL && chg_dev->ops != NULL && + chg_dev->ops->get_qc3p_power) + return chg_dev->ops->get_qc3p_power(chg_dev, qc3p_power); + + return -ENOTSUPP; +} +EXPORT_SYMBOL(charger_dev_get_qc3p_power); + int charger_dev_notify(struct charger_device *chg_dev) { return srcu_notifier_call_chain( diff --git a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.c b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.c index 37f63a16f1fb..9a245c2674e3 100644 --- a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.c +++ b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.c @@ -1980,15 +1980,53 @@ int mmi_discrete_get_charging_enabled(struct mmi_discrete_charger *chip, bool *v { int rc = 0; - mmi_dbg(chip, "mmi_discrete_get_charging_enabled val:%d\n",*val); - rc = charger_dev_is_enabled_charging(chip->master_chg_dev, val); if (rc) mmi_err(chip, "Couldn't get charging status rc=%d\n", rc); + mmi_dbg(chip, "mmi_discrete_get_charging_enabled val:%d\n",*val); + return rc; } +int mmi_discrete_get_qc3p_power(struct mmi_discrete_charger *chip, int *val) +{ + int rc = 0; + + rc = charger_dev_get_qc3p_power(chip->master_chg_dev, val); + if (rc) + mmi_err(chip, "Couldn't get qc3p power rc=%d\n", rc); + + mmi_dbg(chip, "mmi_discrete_get_qc3p_power val:%d\n",*val); + + return rc; +} + +int mmi_discrete_get_pulse_cnt(struct mmi_discrete_charger *chip, int *count) +{ + int rc = 0; + + rc = charger_dev_get_pulse_cnt(chip->master_chg_dev, count); + if (rc) + mmi_err(chip, "Couldn't get pulse cnt rc=%d\n", rc); + + mmi_dbg(chip, "mmi_discrete_get_pulse_cnt count:%d\n",*count); + + return rc; +} + +int mmi_discrete_set_dp_dm(struct mmi_discrete_charger *chip, int val) +{ + int rc = 0; + + rc = charger_dev_set_dp_dm(chip->master_chg_dev, val); + if (rc) + mmi_err(chip, "Couldn't set dp dm rc=%d\n", rc); + + mmi_dbg(chip, "mmi_discrete_set_dp_dm val:%d\n",val); + + return rc; +} int mmi_discrete_config_input_current_settled(struct mmi_discrete_charger *chip, int val) { diff --git a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.h b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.h index 7f8b4410da7f..8843f777fa1f 100644 --- a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.h +++ b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_core.h @@ -138,5 +138,8 @@ int mmi_discrete_config_charging_enabled(struct mmi_discrete_charger *chip, int int mmi_discrete_get_charging_enabled(struct mmi_discrete_charger *chip, bool *val); int mmi_discrete_config_input_current_settled(struct mmi_discrete_charger *chip, int val); int mmi_discrete_config_termination_enabled(struct mmi_discrete_charger *chip, int val); +int mmi_discrete_get_qc3p_power(struct mmi_discrete_charger *chip, int *val); +int mmi_discrete_get_pulse_cnt(struct mmi_discrete_charger *chip, int *count); +int mmi_discrete_set_dp_dm(struct mmi_discrete_charger *chip, int val); #endif diff --git a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.c b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.c index d6a50fcf1644..2a01d25a1bdd 100644 --- a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.c +++ b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.c @@ -10,6 +10,7 @@ * GNU General Public License for more details. */ +#include #include "mmi_discrete_charger_iio.h" static int mmi_discrete_iio_write_raw(struct iio_dev *indio_dev, @@ -38,6 +39,12 @@ static int mmi_discrete_iio_write_raw(struct iio_dev *indio_dev, case PSY_IIO_USB_TERMINATION_ENABLED: rc = mmi_discrete_config_termination_enabled(chip, val1); break; + case PSY_IIO_DP_DM: + if (chip->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 + || chip->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3P5) { + rc = mmi_discrete_set_dp_dm(chip, val1); + } + break; default: pr_err("Unsupported mmi_discrete IIO chan %d\n", chan->channel); rc = -EINVAL; @@ -71,6 +78,12 @@ static int mmi_discrete_iio_read_raw(struct iio_dev *indio_dev, rc = mmi_discrete_get_charging_enabled(chip, &val_bool); *val1 = val_bool?1:0; break; + case PSY_IIO_MMI_QC3P_POWER: + rc = mmi_discrete_get_qc3p_power(chip, val1); + break; + case PSY_IIO_DP_DM: + rc = mmi_discrete_get_pulse_cnt(chip, val1); + break; default: pr_err("Unsupported mmi_discrete IIO chan %d\n", chan->channel); rc = -EINVAL; diff --git a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.h b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.h index cd3bbff31193..23be390fd48e 100644 --- a/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.h +++ b/drivers/power/mmi_discrete_charger/mmi_discrete_charger_iio.h @@ -35,6 +35,10 @@ struct mmi_discrete_iio_channels { .info_mask = _mask, \ }, +#define MMI_DISCRETE_CHAN_COUNT(_name, _num) \ + MMI_DISCRETE_IIO_CHAN(_name, _num,IIO_COUNT, \ + BIT(IIO_CHAN_INFO_PROCESSED)) + #define MMI_DISCRETE_CHAN_INDEX(_name, _num) \ MMI_DISCRETE_IIO_CHAN(_name, _num, IIO_INDEX, \ BIT(IIO_CHAN_INFO_PROCESSED)) @@ -48,6 +52,8 @@ static const struct mmi_discrete_iio_channels mmi_discrete_iio_psy_channels[] = MMI_DISCRETE_CHAN_INDEX("charging_enabled", PSY_IIO_USB_CHARGING_ENABLED) MMI_DISCRETE_CHAN_INDEX("input_current_settled", PSY_IIO_INPUT_CURRENT_SETTLED) MMI_DISCRETE_CHAN_INDEX("termination_enabled", PSY_IIO_USB_TERMINATION_ENABLED) + MMI_DISCRETE_CHAN_COUNT("battery_dp_dm", PSY_IIO_DP_DM) + MMI_DISCRETE_CHAN_INDEX("usb_qc3p_power", PSY_IIO_MMI_QC3P_POWER) }; int mmi_discrete_init_iio_psy(struct mmi_discrete_charger *chip, diff --git a/drivers/power/mmi_discrete_turbo_charger/Android.mk b/drivers/power/mmi_discrete_turbo_charger/Android.mk index 291d04365929..6adb332ea3f2 100644 --- a/drivers/power/mmi_discrete_turbo_charger/Android.mk +++ b/drivers/power/mmi_discrete_turbo_charger/Android.mk @@ -5,6 +5,10 @@ include $(CLEAR_VARS) LOCAL_MODULE := mmi_discrete_turbo_charger.ko LOCAL_MODULE_TAGS := optional +ifeq ($(MMI_QC3P_WT6670_DETECTED),true) + KERNEL_CFLAGS += CONFIG_MMI_QC3P_WT6670_DETECTED=y +endif + ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true) LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/ else diff --git a/drivers/power/mmi_discrete_turbo_charger/Kbuild b/drivers/power/mmi_discrete_turbo_charger/Kbuild index f649757ea3a4..6137c8800e6b 100644 --- a/drivers/power/mmi_discrete_turbo_charger/Kbuild +++ b/drivers/power/mmi_discrete_turbo_charger/Kbuild @@ -3,6 +3,10 @@ EXTRA_CFLAGS += -Wall EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include \ -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/power/mmi_discrete_turbo_charger +ifneq ($(filter m y,$(CONFIG_MMI_QC3P_WT6670_DETECTED)),) + EXTRA_CFLAGS += -DCONFIG_MMI_QC3P_WT6670_DETECTED +endif + obj-m += mmi_discrete_turbo_charger.o mmi_discrete_turbo_charger-objs += mmi_charger_class.o mmi_discrete_turbo_charger-objs += mmi_charger_core.o diff --git a/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.c b/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.c index 7cbc47eb66ce..ee0bdda8f28c 100644 --- a/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.c +++ b/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.c @@ -751,7 +751,9 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) struct mmi_charger_manager *chip = container_of(nb, struct mmi_charger_manager, psy_nb); +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED return NOTIFY_OK; +#endif if (!chip->usb_psy) { mmi_chrg_err(chip, "usb psy is NULL, direct return\n"); diff --git a/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.h b/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.h index 02542b8ae593..38d4c368af9c 100644 --- a/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.h +++ b/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core.h @@ -79,7 +79,11 @@ enum print_reason { enum mmi_qc3p_power { QTI_POWER_SUPPLY_QC3P_NONE, +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED QTI_POWER_SUPPLY_QC3P_18W = 0x8, +#else + QTI_POWER_SUPPLY_QC3P_18W, +#endif QTI_POWER_SUPPLY_QC3P_27W, QTI_POWER_SUPPLY_QC3P_45W, }; diff --git a/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core_iio.h b/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core_iio.h index a08c8bb70916..58f1b21085fc 100644 --- a/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core_iio.h +++ b/drivers/power/mmi_discrete_turbo_charger/mmi_charger_core_iio.h @@ -49,7 +49,6 @@ enum mmi_charger_ext_iio_channels { CP_INPUT_VOLTAGE_NOW, CP_STATUS1, CP_CLEAR_ERROR, - SMB5_QC3P_START_DETECT, /*mmi-smb5charger-iio*/ MMI_CP_ENABLE_STATUS, MMI_USB_TERMINATION_ENABLED, @@ -64,10 +63,15 @@ static const char * const mmi_charger_ext_iio_chan_name[] = { [SMB5_USB_PD_ACTIVE] = "pd_active", [MMI_USB_TERMINATION_ENABLED] = "termination_enabled", /*qc3p*/ +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED [SMB5_USB_REAL_TYPE] = "wt6670_usb_real_type", [SMB5_DP_DM] = "wt6670_battery_dp_dm", [SMB5_QC3P_POWER] = "wt6670_usb_qc3p_power", - [SMB5_QC3P_START_DETECT] = "wt6670_start_detection", +#else + [SMB5_USB_REAL_TYPE] = "usb_real_type", + [SMB5_DP_DM] = "battery_dp_dm", + [SMB5_QC3P_POWER] = "usb_qc3p_power", +#endif /*cp*/ [CP_ENABLE] = "bq2597x_cp_enabled", [CP_INPUT_CURRENT_NOW] = "bq2597x_input_current_now", diff --git a/drivers/power/mmi_discrete_turbo_charger/mmi_qc3p.c b/drivers/power/mmi_discrete_turbo_charger/mmi_qc3p.c index c0289d5c7809..9f9d7e7553f1 100644 --- a/drivers/power/mmi_discrete_turbo_charger/mmi_qc3p.c +++ b/drivers/power/mmi_discrete_turbo_charger/mmi_qc3p.c @@ -42,17 +42,6 @@ #include #include -bool mmi_qc3p_start_detection(struct mmi_charger_manager *chg) -{ - int ret, iio_val; - - ret = mmi_charger_read_iio_chan(chg, SMB5_QC3P_START_DETECT, &iio_val); - if (ret < 0) { - mmi_chrg_err(chg, "Couldn't operate qc3p detection rc=%d\n", ret); - return false; - } - return true; -} bool mmi_qc3p_power_active(struct mmi_charger_manager *chg) { @@ -63,9 +52,13 @@ bool mmi_qc3p_power_active(struct mmi_charger_manager *chg) mmi_chrg_err(chg, "Couldn't read charger type rc=%d\n", ret); return false; } +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED if (iio_val != QTI_POWER_SUPPLY_QC3P_27W && iio_val != QTI_POWER_SUPPLY_QC3P_45W) return false; - +#else + if (iio_val != POWER_SUPPLY_TYPE_USB_HVDCP_3P5) + return false; +#endif ret = mmi_charger_read_iio_chan(chg, SMB5_QC3P_POWER, &iio_val); if (ret < 0) { mmi_chrg_err(chg, "Couldn't read qc3p power rc=%d\n", ret); @@ -81,6 +74,7 @@ bool mmi_qc3p_power_active(struct mmi_charger_manager *chg) return false; } +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED int mmi_qc3p_set_vbus_voltage(struct mmi_charger_manager *chg, int target_mv) { int rc = -EINVAL; @@ -132,4 +126,71 @@ int mmi_qc3p_set_vbus_voltage(struct mmi_charger_manager *chg, int target_mv) } mmi_chrg_info(chg, "result_vbus= %d\n",curr_vbus_mv); return curr_vbus_mv; -} \ No newline at end of file +} + +#else + +enum { + MMI_POWER_SUPPLY_DP_DM_UNKNOWN = 0, + MMI_POWER_SUPPLY_DP_DM_DP_PULSE = 1, + MMI_POWER_SUPPLY_DP_DM_DM_PULSE = 2, +}; + +#define QC3P_PULSE_COUNT_MAX ((11000 - 5000) / 20 + 10) +int mmi_qc3p_set_vbus_voltage(struct mmi_charger_manager *chg, int target_mv) +{ + int rc = -EINVAL; + union power_supply_propval val = {0, }; + int pulse_cnt, curr_vbus_mv, step, i; + + rc = mmi_charger_read_iio_chan(chg, SMB5_DP_DM, &val.intval); + if (rc < 0) { + mmi_chrg_err(chg, "Couldn't read dpdm pulse count rc=%d\n", rc); + return -EINVAL; + } else { + mmi_chrg_info(chg, "DP DM pulse count = %d\n", val.intval); + pulse_cnt = val.intval; + } + + rc = mmi_get_vbus(chg->chrg_list[CP_MASTER], + &curr_vbus_mv); + if (rc) { + mmi_chrg_err(chg, "Unable to read USB voltage: %d\n", rc); + return -EINVAL; + } + + if(target_mv < curr_vbus_mv) { + step = (curr_vbus_mv - target_mv) / 20; + val.intval = MMI_POWER_SUPPLY_DP_DM_DM_PULSE; + if (pulse_cnt <= step) + step = pulse_cnt; + } else { + step = (target_mv - curr_vbus_mv) / 20; + val.intval = MMI_POWER_SUPPLY_DP_DM_DP_PULSE; + if (step + pulse_cnt > QC3P_PULSE_COUNT_MAX) + step = QC3P_PULSE_COUNT_MAX - pulse_cnt; + } + + mmi_chrg_info(chg, "curr_vbus= %d, target_vbus = %d, step = %d\n",curr_vbus_mv, target_mv, step); + for (i = 0; i < step; i++) { + rc = mmi_charger_write_iio_chan(chg, SMB5_DP_DM, val.intval); + if (rc < 0) { + mmi_chrg_err(chg, "Couldn't set dpdm pulse rc=%d\n", rc); + break; + } + + if (i < step - 1) + udelay(5000); + } + + rc = mmi_get_vbus(chg->chrg_list[CP_MASTER], + &curr_vbus_mv); + if (rc) { + mmi_chrg_err(chg, "Unable to read VBUS: %d\n", rc); + return -EINVAL; + } + mmi_chrg_info(chg, "result_vbus= %d\n",curr_vbus_mv); + return curr_vbus_mv; +} +#endif + diff --git a/drivers/power/sgm4154x_chg_mmi/Android.mk b/drivers/power/sgm4154x_chg_mmi/Android.mk index c50411b9ae39..20c0fd04a51c 100644 --- a/drivers/power/sgm4154x_chg_mmi/Android.mk +++ b/drivers/power/sgm4154x_chg_mmi/Android.mk @@ -9,6 +9,10 @@ ifeq ($(MMI_QC3P_TURBO_CHARGER),true) KERNEL_CFLAGS += CONFIG_MMI_QC3P_TURBO_CHARGER=y endif +ifeq ($(MMI_QC3P_WT6670_DETECTED),true) + KERNEL_CFLAGS += CONFIG_MMI_QC3P_WT6670_DETECTED=y +endif + LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) LOCAL_ADDITIONAL_DEPENDENCIES := $(KERNEL_MODULES_OUT)/mmi_discrete_charger_class.ko diff --git a/drivers/power/sgm4154x_chg_mmi/Kbuild b/drivers/power/sgm4154x_chg_mmi/Kbuild index 9328f2d11429..f722b5abb160 100644 --- a/drivers/power/sgm4154x_chg_mmi/Kbuild +++ b/drivers/power/sgm4154x_chg_mmi/Kbuild @@ -7,6 +7,10 @@ ifneq ($(filter m y,$(CONFIG_MMI_QC3P_TURBO_CHARGER)),) EXTRA_CFLAGS += -DCONFIG_MMI_QC3P_TURBO_CHARGER endif +ifneq ($(filter m y,$(CONFIG_MMI_QC3P_WT6670_DETECTED)),) + EXTRA_CFLAGS += -DCONFIG_MMI_QC3P_WT6670_DETECTED +endif + obj-m += sgm4154x_charger.o KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../mmi_discrete_charger/$(GKI_OBJ_MODULE_DIR)/Module.symvers diff --git a/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.c b/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.c index 681f0ae558a5..158a20f5bbba 100644 --- a/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.c +++ b/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.c @@ -24,10 +24,6 @@ #include #include -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER -static bool g_qc3p_detected = false; -#endif - static struct power_supply_desc sgm4154x_power_supply_desc; /* SGM4154x REG06 BOOST_LIM[5:4], uV */ @@ -322,7 +318,7 @@ static int sgm4154x_get_usb_voltage_now(struct sgm4154x_device *sgm, int *val) return 0; } -#ifndef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifndef CONFIG_MMI_QC3P_WT6670_DETECTED static int sgm4154x_adjust_qc20_hvdcp_5v(struct sgm4154x_device *sgm) { int ret; @@ -673,7 +669,6 @@ static int sgm4154x_get_icl(struct charger_device *chg_dev, u32 *uA) return 0; } -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER static int sgm4154x_is_enabled_charging(struct charger_device *chg_dev, bool *en) { struct sgm4154x_device *sgm = dev_get_drvdata(&chg_dev->dev); @@ -690,7 +685,6 @@ static int sgm4154x_is_enabled_charging(struct charger_device *chg_dev, bool *en return 0; } -#endif /*mahj:for build static int sgm4154x_set_watchdog_timer(struct sgm4154x_device *sgm, int time) @@ -1396,7 +1390,13 @@ OUT: schedule_delayed_work(&sgm->charge_monitor_work, 10*HZ); } -#ifndef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifndef CONFIG_MMI_QC3P_WT6670_DETECTED +#define QC3P_AUTHEN_LOW_THR_MV 5500000 +#define QC3P_AUTHEN_HIGH_THR_MV 6500000 +#define QC3P_AUTHEN_NONE_THR_MV 9000000 +#define QC3P_AUTHEN_45W_THR_MV 8000000 +#define QC3P_AUTHEN_27W_THR_MV 7000000 +#define QC3P_AUTHEN_18W_THR_MV 6000000 static int sgm4154x_detected_qc30_hvdcp(struct sgm4154x_device *sgm, int *charger_type) { int ret = 0; @@ -1440,14 +1440,125 @@ static int sgm4154x_detected_qc30_hvdcp(struct sgm4154x_device *sgm, int *charge dev_err(sgm->dev, "%s qc30 step down vbus error\n", __func__); } +#ifndef CONFIG_MMI_QC3P_TURBO_CHARGER sgm4154x_get_usb_voltage_now(sgm, &vbus_voltage); dev_info(sgm->dev, "%s vbus voltage now = %d after detected qc30\n", __func__,vbus_voltage); +#endif + + return ret; +} + +static int sgm4154x_detected_qc3p_hvdcp(struct sgm4154x_device *sgm, int *charger_type) +{ + int ret = 0; + int dp_val, dm_val; + int i=0, vbus_voltage; + + mdelay(100);//need tunning + + sgm4154x_get_usb_voltage_now(sgm, &vbus_voltage); + + if (vbus_voltage < QC3P_AUTHEN_LOW_THR_MV + || vbus_voltage > QC3P_AUTHEN_HIGH_THR_MV) { + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_NONE; + /*do qc3p rerun*/ + if (!sgm->mmi_qc3p_rerun_done) { + sgm->mmi_qc3p_rerun_done = true; + dp_val = 0x0<<3; + ret = regmap_update_bits(sgm->regmap, SGM4154x_CHRG_CTRL_d, + SGM4154x_DP_VSEL_MASK, dp_val); //dp HIZ + if (ret) + return ret; + + dm_val = 0x0<<1; + ret = regmap_update_bits(sgm->regmap, SGM4154x_CHRG_CTRL_d, + SGM4154x_DM_VSEL_MASK, dm_val); //dm HIZ + if (ret) + return ret; + + msleep(30);//need tunning + + schedule_work(&sgm->rerun_apsd_work); + } + + return 0; + } + + for (i = 0;i < 3; i++) { + ret = sgm4154x_qc30_step_up_vbus(sgm); + if (ret) + dev_err(sgm->dev, "%s qc3p step up vbus error\n", __func__); + + ret = sgm4154x_qc30_step_down_vbus(sgm); + if (ret) + dev_err(sgm->dev, "%s qc3p step down vbus error\n", __func__); + + } + + mdelay(30);//need tuning + + sgm4154x_get_usb_voltage_now(sgm, &vbus_voltage); + + for (i = 0; i < 2; i++) { + ret = sgm4154x_qc30_step_up_vbus(sgm); + if (ret) + dev_err(sgm->dev, "%s qc3p step up vbus error\n", __func__); + } + + for (i = 0; i < 2; i++) { + ret = sgm4154x_qc30_step_down_vbus(sgm); + if (ret) + dev_err(sgm->dev, "%s qc3p step down vbus error\n", __func__); + } + + msleep(30); + + dev_info(sgm->dev, "%s vbus voltage now = %d after detected qc3p\n", __func__,vbus_voltage); + + if (vbus_voltage > QC3P_AUTHEN_NONE_THR_MV) + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_NONE; + else if (vbus_voltage > QC3P_AUTHEN_45W_THR_MV) + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_45W; + else if (vbus_voltage > QC3P_AUTHEN_27W_THR_MV) + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_27W; + else if (vbus_voltage > QC3P_AUTHEN_18W_THR_MV) + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_18W; + else + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_NONE; + + if (sgm->mmi_qc3p_power != MMI_POWER_SUPPLY_QC3P_NONE) { + *charger_type = POWER_SUPPLY_TYPE_USB_HVDCP_3P5; + dev_info(sgm->dev, "%s detected qc3p, qc3p power = %d\n", + __func__,sgm->mmi_qc3p_power); + } else { + dev_err(sgm->dev, "qc3p power is invalid, rerun qc3p detect\n"); + //do rerun qc3p + if (!sgm->mmi_qc3p_rerun_done) { + sgm->mmi_qc3p_rerun_done = true; + dp_val = 0x0<<3; + ret = regmap_update_bits(sgm->regmap, SGM4154x_CHRG_CTRL_d, + SGM4154x_DP_VSEL_MASK, dp_val); //dp HIZ + if (ret) + return ret; + + dm_val = 0x0<<1; + ret = regmap_update_bits(sgm->regmap, SGM4154x_CHRG_CTRL_d, + SGM4154x_DM_VSEL_MASK, dm_val); //dm HIZ + if (ret) + return ret; + + msleep(30);//need tunning + + schedule_work(&sgm->rerun_apsd_work); + } + + } return ret; } #endif -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED bool is_chan_valid(struct sgm4154x_device *chip, enum mmi_qc3p_ext_iio_channels chan) { @@ -1590,7 +1701,7 @@ static int mmi_hvdcp_detect_kthread(void *param) sgm->mmi_is_qc3_authen = true; sgm4154x_set_input_curr_lim(sgm, MMI_HVDCP_DETECT_ICL_LIMIT); -#ifndef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifndef CONFIG_MMI_QC3P_WT6670_DETECTED //do qc2.0 detected ret = sgm4154x_detected_qc20_hvdcp(sgm, &charger_type); if (ret) { @@ -1605,7 +1716,19 @@ static int mmi_hvdcp_detect_kthread(void *param) ret = sgm4154x_detected_qc30_hvdcp(sgm, &charger_type); if (ret) { dev_err(sgm->dev, "Cann't detected qc30 hvdcp\n"); + goto out; } + +#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER + //do qc3p detected + if (charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3) { + ret = sgm4154x_detected_qc3p_hvdcp(sgm, &charger_type); + if (ret) { + dev_err(sgm->dev, "Cann't detected qc3p hvdcp\n"); + goto out; + } + } +#endif #else sgm4154x_enable_termination(sgm->chg_dev, true); qc3p_start_detection(sgm); @@ -1626,7 +1749,6 @@ static int mmi_hvdcp_detect_kthread(void *param) dev_err(sgm->dev, "QC3P 27W have been detected !\n"); charger_type = POWER_SUPPLY_TYPE_USB_HVDCP_3P5; qc3p_update_policy(sgm); - g_qc3p_detected = true; break; default: dev_info(sgm->dev, "No HDVCP detected\n"); @@ -1670,16 +1792,18 @@ static void sgm4154x_vbus_remove(struct sgm4154x_device * sgm) #ifdef CONFIG_MMI_QC3P_TURBO_CHARGER sgm4154x_enable_termination(sgm->chg_dev, true); - g_qc3p_detected = false; +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED qc3p_update_policy(sgm); #endif - +#endif cancel_delayed_work_sync(&sgm->charge_monitor_work); sgm->pulse_cnt = 0; + sgm->mmi_qc3p_rerun_done = false; sgm->typec_apsd_rerun_done = false; sgm->chg_dev->noti.apsd_done = false; sgm->chg_dev->noti.hvdcp_done = false; sgm->real_charger_type = POWER_SUPPLY_TYPE_UNKNOWN; + sgm->mmi_qc3p_power = MMI_POWER_SUPPLY_QC3P_NONE; sgm4154x_request_dpdm(sgm, false); charger_dev_notify(sgm->chg_dev); } @@ -1713,10 +1837,7 @@ static void sgm4154x_vbus_plugin(struct sgm4154x_device * sgm) case SGM4154x_USB_DCP: pr_err("SGM4154x charger type: DCP\n"); sgm->real_charger_type = POWER_SUPPLY_TYPE_USB_DCP; -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER - if(g_qc3p_detected == false) -#endif - mmi_start_hvdcp_detect(sgm); + mmi_start_hvdcp_detect(sgm); break; case SGM4154x_UNKNOWN: @@ -2459,6 +2580,15 @@ static int sgm4154x_set_boost_current_limit(struct charger_device *chg_dev, u32 return rc; } +static int sgm4154x_get_qc3p_power(struct charger_device *chg_dev, int *qc3p_power) +{ + struct sgm4154x_device *sgm = dev_get_drvdata(&chg_dev->dev); + + *qc3p_power = sgm->mmi_qc3p_power; + + return 0; +} + static int sgm4154x_get_pulse_cnt(struct charger_device *chg_dev, int *count) { struct sgm4154x_device *sgm = dev_get_drvdata(&chg_dev->dev); @@ -2544,10 +2674,9 @@ static struct charger_ops sgm4154x_chg_ops = { .is_charge_halted = sgm4154x_is_charging_halted, .dump_registers = sgm4154x_dump_registers, -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER .is_enabled_charging = sgm4154x_is_enabled_charging, -#endif .enable_termination = sgm4154x_enable_termination, + .get_qc3p_power = sgm4154x_get_qc3p_power, }; static int sgm4154x_probe(struct i2c_client *client, @@ -2675,7 +2804,7 @@ static int sgm4154x_probe(struct i2c_client *client, enable_irq_wake(client->irq); } -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED ret = mmi_init_iio_psy(sgm, dev); if (ret) { dev_err(dev, diff --git a/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h b/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h index 3c7c574db97b..e9dd69b366c6 100644 --- a/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h +++ b/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h @@ -233,6 +233,13 @@ enum { MMI_POWER_SUPPLY_DP_DM_DM_PULSE = 2, }; +enum mmi_qc3p_power { + MMI_POWER_SUPPLY_QC3P_NONE, + MMI_POWER_SUPPLY_QC3P_18W, + MMI_POWER_SUPPLY_QC3P_27W, + MMI_POWER_SUPPLY_QC3P_45W, +}; + struct sgm4154x_iio { struct iio_channel *usbin_v_chan; }; @@ -347,13 +354,17 @@ struct sgm4154x_device { u32 input_current_cache; int pulse_cnt; + /*mmi qc3p*/ + bool mmi_qc3p_rerun_done; + int mmi_qc3p_power; + struct sgm4154x_iio iio; -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED struct iio_channel **ext_iio_chans; #endif }; -#ifdef CONFIG_MMI_QC3P_TURBO_CHARGER +#ifdef CONFIG_MMI_QC3P_WT6670_DETECTED enum WT_charger_type{ WT_CHG_TYPE_BEGIN = 0, WT_CHG_TYPE_FC, diff --git a/include/linux/mmi_discrete_charger_class.h b/include/linux/mmi_discrete_charger_class.h index f09d3fd88261..982bc4cc7cb0 100644 --- a/include/linux/mmi_discrete_charger_class.h +++ b/include/linux/mmi_discrete_charger_class.h @@ -47,6 +47,7 @@ struct charger_ops { int (*get_pulse_cnt)(struct charger_device *dev, int *count); int (*get_real_charger_type)(struct charger_device *dev, int *charger_type); + int (*get_qc3p_power)(struct charger_device *dev, int *qc3p_power); /* enable/disable charger */ int (*enable_charging)(struct charger_device *dev, bool en); @@ -137,6 +138,8 @@ extern int charger_dev_set_dp_dm(struct charger_device *chg_dev, int val); extern int charger_dev_get_real_charger_type(struct charger_device *chg_dev, int *charger_type); +extern int charger_dev_get_qc3p_power(struct charger_device *chg_dev, int *qc3p_power); + extern int register_charger_device_notifier( struct charger_device *charger_dev, struct notifier_block *nb);