diff --git a/drivers/power/supply/qcom/qpnp-smblite.c b/drivers/power/supply/qcom/qpnp-smblite.c index a20e61b9970d..1f705ddfdb0b 100644 --- a/drivers/power/supply/qcom/qpnp-smblite.c +++ b/drivers/power/supply/qcom/qpnp-smblite.c @@ -25,51 +25,104 @@ static struct power_supply_desc usb_psy_desc; -static struct smb_params smblite_params = { +static const struct smb_base_address smb_base[] = { + [PM2250] = { + .chg_base = 0x1000, + .dcdc_base = 0x1100, + .batif_base = 0x1200, + .usbin_base = 0x1300, + .misc_base = 0x1600, + .typec_base = 0x1500, + }, + + [PM5100] = { + .chg_base = 0x2600, + .batif_base = 0x2800, + .usbin_base = 0x2900, + .misc_base = 0x2c00, + .dcdc_base = 0x2700, + }, +}; + +static struct smb_params smblite_pm2250_params = { .fcc = { .name = "fast charge current", - .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG, .min_u = 0, .max_u = 2000000, .step_u = 100000, }, .fv = { .name = "float voltage", - .reg = CHGR_FLOAT_VOLTAGE_CFG_REG, .min_u = 3600000, .max_u = 4600000, .step_u = 20000, }, .usb_icl = { .name = "usb input current limit", - .reg = USBIN_CURRENT_LIMIT_CFG_REG, .min_u = 0, .max_u = 2000000, .step_u = 100000, }, .icl_max_stat = { .name = "dcdc icl max status", - .reg = ICL_MAX_STATUS_REG, .min_u = 0, .max_u = 2000000, .step_u = 100000, }, .icl_stat = { .name = "input current limit status", - .reg = ICL_STATUS_REG, .min_u = 0, .max_u = 2000000, .step_u = 100000, }, .aicl_5v_threshold = { .name = "AICL 5V threshold", - .reg = USBIN_LV_AICL_THRESHOLD_REG, .min_u = 4200, .max_u = 4800, .step_u = 200, }, }; +static struct smb_params smblite_pm5100_params = { + .fcc = { + .name = "fast charge current", + .min_u = 0, + .max_u = 1950000, + .get_proc = smblite_lib_get_fcc, + .set_proc = smblite_lib_set_fcc, + }, + .fv = { + .name = "float voltage", + .min_u = 3600000, + .max_u = 4790000, + .step_u = 10000, + }, + .usb_icl = { + .name = "usb input current limit", + .min_u = 0, + .max_u = 1950000, + .step_u = 100000, + }, + .icl_max_stat = { + .name = "dcdc icl max status", + .min_u = 0, + .max_u = 1950000, + .step_u = 100000, + }, + .icl_stat = { + .name = "input current limit status", + .min_u = 0, + .max_u = 1950000, + .step_u = 100000, + }, + .aicl_5v_threshold = { + .name = "AICL 5V threshold", + .min_u = 4200, + .max_u = 5100, + .step_u = 300, + }, +}; + struct smb_dt_props { int usb_icl_ua; int chg_inhibit_thr_mv; @@ -137,22 +190,37 @@ static int smblite_chg_config_init(struct smblite *chip) switch (subtype) { case PM2250: chg->wa_flags |= WEAK_ADAPTER_WA; + chg->base = smb_base[PM2250]; + chg->param = smblite_pm2250_params; + chg->name = "PM2250_charger"; + + rc = smblite_lib_read(chg, DCDC_LDO_CFG_REG(chg->base), &val); + if (rc < 0) { + pr_err("Couldn't read LDO config reg rc=%d\n", rc); + return rc; + } + + chg->ldo_mode = !!(val & LDO_MODE_BIT); + + break; + case PM5100: + chg->base = smb_base[PM5100]; + chg->param = smblite_pm5100_params; + chg->name = "PM5100_charger"; break; default: pr_err("Unsupported PMIC subtype=%d\n", subtype); return -EINVAL; } - rc = smblite_lib_read(chg, DCDC_LDO_CFG_REG, &val); - if (rc < 0) { - pr_err("Couldn't read LDO config reg rc=%d\n", rc); - return rc; - } - chg->ldo_mode = !!(val & LDO_MODE_BIT); - + /* Assign reg to smb params */ + chg->param.fcc.reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG(chg->base); + chg->param.fv.reg = CHGR_FLOAT_VOLTAGE_CFG_REG(chg->base); + chg->param.usb_icl.reg = USBIN_CURRENT_LIMIT_CFG_REG(chg->base); + chg->param.icl_max_stat.reg = ICL_MAX_STATUS_REG(chg->base); + chg->param.icl_stat.reg = ICL_STATUS_REG(chg->base); + chg->param.aicl_5v_threshold.reg = USBIN_LV_AICL_THRESHOLD_REG(chg->base); chip->chg.chg_param.smb_version = 0; - chg->param = smblite_params; - chg->name = "PM2250_charger"; return rc; } @@ -354,7 +422,6 @@ static enum power_supply_property smblite_usb_props[] = { POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX, @@ -387,9 +454,6 @@ static int smblite_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_NOW: rc = smblite_lib_get_prop_usb_voltage_now(chg, val); break; - case POWER_SUPPLY_PROP_TYPE: - val->intval = POWER_SUPPLY_TYPE_USB; - break; case POWER_SUPPLY_PROP_SCOPE: rc = smblite_lib_get_prop_scope(chg, val); break; @@ -397,7 +461,8 @@ static int smblite_usb_get_prop(struct power_supply *psy, val->intval = get_effective_result_locked(chg->usb_icl_votable); break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: - val->intval = 5000000; + val->intval = (chg->hvdcp3_detected) ? + PM5100_HVDCP3_MAX_VOLTAGE_UV : 5000000; break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: /* USB uses this to set SDP current */ @@ -714,7 +779,7 @@ static int smblite_configure_typec(struct smb_charger *chg) int rc; u8 val = 0; - rc = smblite_lib_read(chg, LEGACY_CABLE_STATUS_REG, &val); + rc = smblite_lib_read(chg, LEGACY_CABLE_STATUS_REG(chg->base), &val); if (rc < 0) { dev_err(chg->dev, "Couldn't read Legacy status rc=%d\n", rc); return rc; @@ -745,21 +810,21 @@ static int smblite_configure_typec(struct smb_charger *chg) } /* Use simple write to clear interrupts */ - rc = smblite_lib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG, 0); + rc = smblite_lib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG(chg->base), 0); if (rc < 0) { dev_err(chg->dev, "Couldn't configure Type-C interrupts rc=%d\n", rc); return rc; } - rc = smblite_lib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG, 0); + rc = smblite_lib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG(chg->base), 0); if (rc < 0) { dev_err(chg->dev, "Couldn't configure Type-C interrupts rc=%d\n", rc); return rc; } - rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG, + rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG(chg->base), EN_TRY_SNK_BIT | EN_SNK_ONLY_BIT, EN_TRY_SNK_BIT); if (rc < 0) { @@ -769,7 +834,7 @@ static int smblite_configure_typec(struct smb_charger *chg) return rc; } - rc = smblite_lib_masked_write(chg, TYPE_C_EXIT_STATE_CFG_REG, + rc = smblite_lib_masked_write(chg, TYPE_C_EXIT_STATE_CFG_REG(chg->base), SEL_SRC_UPPER_REF_BIT, SEL_SRC_UPPER_REF_BIT); if (rc < 0) dev_err(chg->dev, @@ -810,7 +875,7 @@ static int smblite_configure_iterm_thresholds_adc(struct smblite *chip) buf = (u8 *)&raw_hi_thresh; raw_hi_thresh = buf[1] | (buf[0] << 8); - rc = smblite_lib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, + rc = smblite_lib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG(chg->base), (u8 *)&raw_hi_thresh, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n", @@ -826,7 +891,7 @@ static int smblite_configure_iterm_thresholds_adc(struct smblite *chip) buf = (u8 *)&raw_lo_thresh; raw_lo_thresh = buf[1] | (buf[0] << 8); - rc = smblite_lib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG, + rc = smblite_lib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG(chg->base), (u8 *)&raw_lo_thresh, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n", @@ -859,7 +924,7 @@ static int smblite_configure_recharging(struct smblite *chip) struct smb_charger *chg = &chip->chg; /* Configure VBATT-based or automatic recharging */ - rc = smblite_lib_masked_write(chg, CHGR_RECHG_CFG_REG, RECHG_MASK, + rc = smblite_lib_masked_write(chg, CHGR_RECHG_CFG_REG(chg->base), RECHG_MASK, (chip->dt.auto_recharge_vbat_mv > 0) ? VBAT_BASED_RECHG_BIT : 0); if (rc < 0) { @@ -874,14 +939,14 @@ static int smblite_configure_recharging(struct smblite *chip) temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblite_lib_batch_write(chg, - CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2); + CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG(chg->base), (u8 *)&temp, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n", rc); return rc; } /* Program the sample count for VBAT based recharge to 3 */ - rc = smblite_lib_masked_write(chg, CHGR_RECHG_CFG_REG, + rc = smblite_lib_masked_write(chg, CHGR_RECHG_CFG_REG(chg->base), NO_OF_SAMPLE_FOR_RCHG, 3); if (rc < 0) { dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n", @@ -890,7 +955,7 @@ static int smblite_configure_recharging(struct smblite *chip) } } - rc = smblite_lib_masked_write(chg, CHGR_RECHG_CFG_REG, RECHG_MASK, + rc = smblite_lib_masked_write(chg, CHGR_RECHG_CFG_REG(chg->base), RECHG_MASK, (chip->dt.auto_recharge_soc != -EINVAL) ? SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT); if (rc < 0) { @@ -918,7 +983,7 @@ static int smblite_init_connector_type(struct smb_charger *chg) int rc, type = 0; u8 val = 0; - rc = smblite_lib_read(chg, TYPEC_U_USB_CFG_REG, &val); + rc = smblite_lib_read(chg, TYPEC_U_USB_CFG_REG(chg->base), &val); if (rc < 0) { dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n", rc); @@ -931,6 +996,8 @@ static int smblite_init_connector_type(struct smb_charger *chg) if (type) { chg->connector_type = QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB; + /* For micro USB connector, use extcon by default */ + chg->use_extcon = true; } else { chg->connector_type = QTI_POWER_SUPPLY_CONNECTOR_TYPEC; rc = smblite_configure_typec(chg); @@ -1039,7 +1106,7 @@ static int smblite_init_hw(struct smblite *chip) mask = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_RERUN_TIME_MASK; val = USBIN_AICL_PERIODIC_RERUN_EN_BIT | AICL_RERUN_TIME_12S_VAL; - rc = smblite_lib_masked_write(chg, MISC_AICL_RERUN_CFG_REG, mask, val); + rc = smblite_lib_masked_write(chg, MISC_AICL_RERUN_CFG_REG(chg->base), mask, val); if (rc < 0) { dev_err(chg->dev, "Couldn't config AICL rerun rc=%d\n", rc); return rc; @@ -1047,7 +1114,7 @@ static int smblite_init_hw(struct smblite *chip) mask = USBIN_AICL_EN_BIT | USBIN_AICL_START_AT_MAX; val = USBIN_AICL_EN_BIT; - rc = smblite_lib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, mask, + rc = smblite_lib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG(chg->base), mask, val); if (rc < 0) { dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc); @@ -1055,7 +1122,7 @@ static int smblite_init_hw(struct smblite *chip) } if (!chip->dt.disable_suspend_on_collapse) { - rc = smblite_lib_masked_write(chg, USBIN_INPUT_SUSPEND_REG, + rc = smblite_lib_masked_write(chg, USBIN_INPUT_SUSPEND_REG(chg->base), SUSPEND_ON_COLLAPSE_USBIN_BIT, SUSPEND_ON_COLLAPSE_USBIN_BIT); if (rc < 0) { @@ -1072,7 +1139,7 @@ static int smblite_init_hw(struct smblite *chip) } /* configure VBUS for software control */ - rc = smblite_lib_masked_write(chg, DCDC_OTG_CFG_REG, + rc = smblite_lib_masked_write(chg, DCDC_OTG_CFG_REG(chg->base), OTG_EN_SRC_CFG_BIT, 0); if (rc < 0) { dev_err(chg->dev, @@ -1084,7 +1151,7 @@ static int smblite_init_hw(struct smblite *chip) & BARK_WDOG_TIMEOUT_MASK; val |= BITE_WDOG_TIMEOUT_8S << BITE_WDOG_TIMEOUT_SHIFT; - rc = smblite_lib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, + rc = smblite_lib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG(chg->base), BARK_WDOG_TIMEOUT_MASK | BITE_WDOG_TIMEOUT_MASK, val); if (rc < 0) { @@ -1097,7 +1164,7 @@ static int smblite_init_hw(struct smblite *chip) | BITE_WDOG_DISABLE_CHARGING_CFG_BIT | WDOG_TIMER_EN_BIT; val = WDOG_TIMER_EN_ON_PLUGIN_BIT | BARK_WDOG_INT_EN_BIT | BITE_WDOG_DISABLE_CHARGING_CFG_BIT; - rc = smblite_lib_masked_write(chg, WD_CFG_REG, mask, val); + rc = smblite_lib_masked_write(chg, WD_CFG_REG(chg->base), mask, val); if (rc < 0) { pr_err("Couldn't configue WD config rc=%d\n", rc); return rc; @@ -1115,13 +1182,13 @@ static int smblite_init_hw(struct smblite *chip) temp = VBAT_TO_VRAW_ADC(chip->dt.chg_inhibit_thr_mv); temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblite_lib_batch_write(chg, - CHGR_INHIBIT_THRESHOLD_CFG_REG, (u8 *)&temp, 2); + CHGR_INHIBIT_THRESHOLD_CFG_REG(chg->base), (u8 *)&temp, 2); if (rc < 0) { dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n", rc); return rc; } - rc = smblite_lib_masked_write(chg, CHGR_INHIBIT_REG, + rc = smblite_lib_masked_write(chg, CHGR_INHIBIT_REG(chg->base), CHGR_INHIBIT_BIT, CHGR_INHIBIT_BIT); if (rc < 0) { dev_err(chg->dev, "Couldn't enable INHIBIT rc=%d\n", @@ -1129,7 +1196,7 @@ static int smblite_init_hw(struct smblite *chip) return rc; } } else { - rc = smblite_lib_masked_write(chg, CHGR_INHIBIT_REG, + rc = smblite_lib_masked_write(chg, CHGR_INHIBIT_REG(chg->base), CHGR_INHIBIT_BIT, 0); if (rc < 0) { dev_err(chg->dev, "Couldn't enable INHIBIT rc=%d\n", @@ -1142,7 +1209,7 @@ static int smblite_init_hw(struct smblite *chip) val = FAST_CHARGE_SAFETY_TIMER_EN_BIT | FAST_CHARGE_SAFETY_TIMER_768_MIN; rc = smblite_lib_masked_write(chg, - CHGR_FAST_CHARGE_SAFETY_TIMER_CFG_REG, mask, val); + CHGR_FAST_CHARGE_SAFETY_TIMER_CFG_REG(chg->base), mask, val); if (rc < 0) { dev_err(chg->dev, "Couldn't set CHGR_FAST_CHARGE_SAFETY_TIMER_CFG_REG rc=%d\n", rc); @@ -1210,6 +1277,7 @@ static int smblite_determine_initial_status(struct smblite *chip) smblite_batt_temp_changed_irq_handler(0, &irq_data); smblite_wdog_bark_irq_handler(0, &irq_data); smblite_typec_or_rid_detection_change_irq_handler(0, &irq_data); + smblite_usb_source_change_irq_handler(0, &irq_data); if (chg->usb_id_gpio > 0 && chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB) @@ -1300,6 +1368,11 @@ static struct smb_irq_info smblite_irqs[] = { [USBIN_GT_VT_IRQ] = { .name = "usbin-gtvt", }, + [USBIN_SRC_CHANGE_IRQ] = { + .name = "usbin-src-change", + .handler = smblite_usb_source_change_irq_handler, + .wake = true, + }, [USBIN_ICL_CHANGE_IRQ] = { .name = "usbin-icl-change", .handler = smblite_icl_change_irq_handler, @@ -1764,6 +1837,8 @@ static int smblite_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct smb_charger *chg; int rc = 0; + union power_supply_propval pval = {0, }; + const struct apsd_result *apsd; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*chip)); if (!indio_dev) @@ -1891,6 +1966,14 @@ static int smblite_probe(struct platform_device *pdev) device_init_wakeup(chg->dev, true); + rc = smblite_lib_get_prop_usb_present(chg, &pval); + if (rc < 0) + pr_err("Couldn't read usb present rc=%d\n", rc); + + apsd = smblite_lib_get_apsd_result(chg); + + pr_info("%s charger probed successfully, charger_present=%d, type=%s\n", + chg->name, pval.intval, apsd->name); return rc; disable_irq: @@ -1925,7 +2008,7 @@ static void smblite_shutdown(struct platform_device *pdev) /* configure power role for UFP */ if (chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_TYPEC) - smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG, + smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG(chg->base), TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT); } diff --git a/drivers/power/supply/qcom/smblite-lib.c b/drivers/power/supply/qcom/smblite-lib.c index 885d445ccc59..67942397792c 100644 --- a/drivers/power/supply/qcom/smblite-lib.c +++ b/drivers/power/supply/qcom/smblite-lib.c @@ -46,11 +46,18 @@ static void update_sw_icl_max(struct smb_charger *chg, int type); static int smblite_lib_get_prop_typec_mode(struct smb_charger *chg); +#define MIN_ADDRESS_RANGE 0x100 int smblite_lib_read(struct smb_charger *chg, u16 addr, u8 *val) { unsigned int value; int rc = 0; + /* Ignore address range below MIN_ADDRESS_RANGE */ + if (addr < MIN_ADDRESS_RANGE) { + pr_debug("Invalid addr = 0x%x\n", addr); + return 0; + } + rc = regmap_read(chg->regmap, addr, &value); if (rc >= 0) *val = (u8)value; @@ -61,22 +68,46 @@ int smblite_lib_read(struct smb_charger *chg, u16 addr, u8 *val) int smblite_lib_batch_read(struct smb_charger *chg, u16 addr, u8 *val, int count) { + /* Ignore address range below MIN_ADDRESS_RANGE */ + if (addr < MIN_ADDRESS_RANGE) { + pr_debug("Invalid addr = 0x%x\n", addr); + return 0; + } + return regmap_bulk_read(chg->regmap, addr, val, count); } int smblite_lib_write(struct smb_charger *chg, u16 addr, u8 val) { + /* Ignore address range below MIN_ADDRESS_RANGE */ + if (addr < MIN_ADDRESS_RANGE) { + pr_debug("Invalid addr = 0x%x\n", addr); + return 0; + } + return regmap_write(chg->regmap, addr, val); } int smblite_lib_batch_write(struct smb_charger *chg, u16 addr, u8 *val, int count) { + /* Ignore address range below MIN_ADDRESS_RANGE */ + if (addr < MIN_ADDRESS_RANGE) { + pr_debug("Invalid addr = 0x%x\n", addr); + return 0; + } + return regmap_bulk_write(chg->regmap, addr, val, count); } int smblite_lib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val) { + /* Ignore address range below MIN_ADDRESS_RANGE */ + if (addr < MIN_ADDRESS_RANGE) { + pr_debug("Invalid addr = 0x%x\n", addr); + return 0; + } + return regmap_update_bits(chg->regmap, addr, mask, val); } @@ -128,7 +159,7 @@ int smblite_lib_icl_override(struct smb_charger *chg, break; } - rc = smblite_lib_masked_write(chg, USBIN_ICL_OPTIONS_REG, + rc = smblite_lib_masked_write(chg, USBIN_ICL_OPTIONS_REG(chg->base), USBIN_MODE_CHG_BIT, usb51_mode); if (rc < 0) { smblite_lib_err(chg, "Couldn't set USBIN_ICL_OPTIONS rc=%d\n", @@ -136,7 +167,7 @@ int smblite_lib_icl_override(struct smb_charger *chg, return rc; } - rc = smblite_lib_masked_write(chg, CMD_ICL_OVERRIDE_REG, + rc = smblite_lib_masked_write(chg, CMD_ICL_OVERRIDE_REG(chg->base), ICL_OVERRIDE_BIT, icl_override); if (rc < 0) { smblite_lib_err(chg, "Couldn't override ICL rc=%d\n", rc); @@ -185,14 +216,14 @@ static void smblite_lib_notify_usb_host(struct smb_charger *chg, bool enable) if (enable) { smblite_lib_dbg(chg, PR_OTG, "enabling VBUS in OTG mode\n"); - rc = smblite_lib_masked_write(chg, DCDC_CMD_OTG_REG, + rc = smblite_lib_masked_write(chg, DCDC_CMD_OTG_REG(chg->base), OTG_EN_BIT, OTG_EN_BIT); if (rc < 0) { smblite_lib_err(chg, "Couldn't enable VBUS in OTG mode rc=%d\n", rc); return; } - rc = smblite_lib_masked_write(chg, DCDC_BST_VREG_SEL, + rc = smblite_lib_masked_write(chg, DCDC_BST_VREG_SEL(chg->base), VBOOST_MASK, VBOOST_5P00V); if (rc < 0) { smblite_lib_err(chg, @@ -202,7 +233,7 @@ static void smblite_lib_notify_usb_host(struct smb_charger *chg, bool enable) smblite_lib_notify_extcon_props(chg, EXTCON_USB_HOST); } else { smblite_lib_dbg(chg, PR_OTG, "disabling VBUS in OTG mode\n"); - rc = smblite_lib_masked_write(chg, DCDC_CMD_OTG_REG, + rc = smblite_lib_masked_write(chg, DCDC_CMD_OTG_REG(chg->base), OTG_EN_BIT, 0); if (rc < 0) { smblite_lib_err(chg, @@ -311,7 +342,7 @@ int smblite_lib_set_usb_suspend(struct smb_charger *chg, bool suspend) vote(chg->icl_irq_disable_votable, USB_SUSPEND_VOTER, true, 0); - rc = smblite_lib_masked_write(chg, USBIN_INPUT_SUSPEND_REG, + rc = smblite_lib_masked_write(chg, USBIN_INPUT_SUSPEND_REG(chg->base), USBIN_SUSPEND_BIT, suspend ? USBIN_SUSPEND_BIT : 0); if (rc < 0) @@ -347,51 +378,6 @@ static const char * const smblite_lib_qg_ext_iio_chan[] = { [SMB5_QG_TIME_TO_FULL_NOW] = "time_to_full_now", }; -int smblite_lib_read_iio_prop(struct smb_charger *chg, - enum iio_type type, int iio_chan, int *val) -{ - struct iio_channel *iio_chan_list; - int rc; - - switch (type) { - case QG: - if (IS_ERR_OR_NULL(chg->iio_chan_list_qg)) - return -ENODEV; - iio_chan_list = chg->iio_chan_list_qg[iio_chan]; - break; - case SMB_PARALLEL: - if (IS_ERR_OR_NULL(chg->iio_chan_list_smb_parallel)) - return -ENODEV; - iio_chan_list = chg->iio_chan_list_smb_parallel[iio_chan]; - break; - default: - pr_err_ratelimited("iio_type %d is not supported\n", type); - return -EINVAL; - } - - rc = iio_read_channel_processed(iio_chan_list, val); - return rc < 0 ? rc : 0; -} - -int smblite_lib_write_iio_prop(struct smb_charger *chg, - enum iio_type type, int iio_chan, int val) -{ - struct iio_channel *iio_chan_list; - - switch (type) { - case QG: - if (IS_ERR_OR_NULL(chg->iio_chan_list_qg)) - return -ENODEV; - iio_chan_list = chg->iio_chan_list_qg[iio_chan]; - break; - default: - pr_err_ratelimited("iio_type %d is not supported\n", type); - return -EINVAL; - } - - return iio_write_channel_raw(iio_chan_list, val); -} - int smblite_lib_get_prop_from_bms(struct smb_charger *chg, int channel, int *val) { int rc; @@ -405,11 +391,104 @@ int smblite_lib_get_prop_from_bms(struct smb_charger *chg, int channel, int *val return rc < 0 ? rc : 0; } -static void smblite_lib_update_usb_type(struct smb_charger *chg, +enum chg_type { + UNKNOWN, + SDP, + CDP, + DCP, + OCP, + FLOAT, + MAX_TYPES +}; + +static const struct apsd_result smblite_apsd_results[] = { + [UNKNOWN] = { + .name = "UNKNOWN", + .bit = 0, + .val = POWER_SUPPLY_TYPE_UNKNOWN + }, + [SDP] = { + .name = "SDP", + .bit = SDP_CHARGER_BIT, + .val = POWER_SUPPLY_TYPE_USB + }, + [CDP] = { + .name = "CDP", + .bit = CDP_CHARGER_BIT, + .val = POWER_SUPPLY_TYPE_USB_CDP + }, + [DCP] = { + .name = "DCP", + .bit = DCP_CHARGER_BIT, + .val = POWER_SUPPLY_TYPE_USB_DCP + }, + [OCP] = { + .name = "OCP", + .bit = OCP_CHARGER_BIT, + .val = POWER_SUPPLY_TYPE_USB_DCP + }, + [FLOAT] = { + .name = "FLOAT", + .bit = FLOAT_CHARGER_BIT, + .val = QTI_POWER_SUPPLY_TYPE_USB_FLOAT + }, +}; + +const struct apsd_result *smblite_lib_get_apsd_result(struct smb_charger *chg) +{ + int rc, i; + u8 apsd_stat; + const struct apsd_result *result = &smblite_apsd_results[UNKNOWN]; + + rc = smblite_lib_read(chg, APSD_STATUS_REG(chg->base), &apsd_stat); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc); + return result; + } + smblite_lib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", apsd_stat); + + if (!(apsd_stat & APSD_DTC_STATUS_DONE_BIT)) + return result; + + rc = smblite_lib_read(chg, APSD_RESULT_STATUS_REG(chg->base), &apsd_stat); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't read APSD_RESULT_STATUS rc=%d\n", + rc); + return result; + } + apsd_stat &= APSD_RESULT_STATUS_MASK; + + for (i = 0; i < ARRAY_SIZE(smblite_apsd_results); i++) { + if (smblite_apsd_results[i].bit == apsd_stat) + result = &smblite_apsd_results[i]; + } + + return result; +} + +static const struct apsd_result *smblite_lib_update_usb_type(struct smb_charger *chg, enum power_supply_type type) { - chg->real_charger_type = type; + const struct apsd_result *apsd_result = smblite_lib_get_apsd_result(chg); + + if (apsd_result->val == POWER_SUPPLY_TYPE_UNKNOWN) + chg->real_charger_type = type; + + /* + * Update real charger type only if its not FLOAT + * detected as SDP + */ + if (apsd_result->val != POWER_SUPPLY_TYPE_UNKNOWN && + !(apsd_result->val == QTI_POWER_SUPPLY_TYPE_USB_FLOAT && + chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) + chg->real_charger_type = apsd_result->val; + smblite_update_usb_desc(chg); + + smblite_lib_dbg(chg, PR_MISC, "APSD=%s, real_charger_type =%d\n", + apsd_result->name, chg->real_charger_type); + + return apsd_result; } static int smblite_lib_notifier_call(struct notifier_block *nb, @@ -481,6 +560,9 @@ static void smblite_lib_uusb_removal(struct smb_charger *chg) if (rc < 0) smblite_lib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); + + chg->uusb_apsd_rerun_done = false; + chg->hvdcp3_detected = false; } void smblite_lib_suspend_on_debug_battery(struct smb_charger *chg) @@ -523,6 +605,7 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) icl_options = 0; break; case USBIN_500UA: + /* USB 2.0 500mA*/ icl_options = USB51_MODE_BIT; break; default: @@ -540,7 +623,8 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) } rc = smblite_lib_masked_write(chg, - USBIN_ICL_OPTIONS_REG, USB51_MODE_BIT, icl_options); + USBIN_ICL_OPTIONS_REG(chg->base), + CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options); if (rc < 0) { smblite_lib_err(chg, "Couldn't set ICL options rc=%d\n", rc); return rc; @@ -645,6 +729,40 @@ int smblite_lib_get_icl_current(struct smb_charger *chg, int *icl_ua) return rc; } +#define FCC_STEP_1_SIZE_UA 25000 +#define FCC_STEP_2_SIZE_UA 150000 +#define FCC_STEP_1_MAX_DATA 60 +#define STEP_1_MAX_FCC_UA 1500000 + +/* + * Fast Charge Current = [DATA]x25mA, DATA = 0..60 (0-1500ma) + * or [DATA-49]x150mA, DATA = 61..63 (1650mA-1.95A) + */ +int smblite_lib_get_fcc(struct smb_chg_param *param, u8 val_raw) +{ + if (val_raw > FCC_STEP_1_MAX_DATA) + return (((val_raw - FCC_STEP_1_MAX_DATA) * FCC_STEP_2_SIZE_UA) + + STEP_1_MAX_FCC_UA); + + return (val_raw * FCC_STEP_1_SIZE_UA); +} + +int smblite_lib_set_fcc(struct smb_chg_param *param, int val_u, u8 *val_raw) +{ + if (val_u > param->max_u) + val_u = param->max_u; + else if (val_u < param->min_u) + val_u = param->min_u; + + if (val_u > (FCC_STEP_1_MAX_DATA * FCC_STEP_1_SIZE_UA)) + *val_raw = (((val_u - STEP_1_MAX_FCC_UA) / FCC_STEP_2_SIZE_UA) + + FCC_STEP_1_MAX_DATA); + else + *val_raw = (val_u / FCC_STEP_1_SIZE_UA); + + return 0; +} + /********************* * VOTABLE CALLBACKS * *********************/ @@ -667,7 +785,7 @@ static int smblite_lib_chg_disable_vote_callback(struct votable *votable, struct smb_charger *chg = data; int rc; - rc = smblite_lib_masked_write(chg, CHARGING_ENABLE_CMD_REG, + rc = smblite_lib_masked_write(chg, CHARGING_ENABLE_CMD_REG(chg->base), CHARGING_ENABLE_CMD_BIT, chg_disable ? 0 : CHARGING_ENABLE_CMD_BIT); if (rc < 0) { @@ -742,7 +860,7 @@ int smblite_lib_get_prop_batt_present(struct smb_charger *chg, int rc; u8 stat; - rc = smblite_lib_read(chg, BATIF_BASE + INT_RT_STS_OFFSET, &stat); + rc = smblite_lib_read(chg, chg->base.batif_base + INT_RT_STS_OFFSET, &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read BATIF_INT_RT_STS rc=%d\n", rc); @@ -777,7 +895,7 @@ static bool is_charging_paused(struct smb_charger *chg) int rc; u8 val; - rc = smblite_lib_read(chg, CHARGING_ENABLE_CMD_REG, &val); + rc = smblite_lib_read(chg, CHARGING_ENABLE_CMD_REG(chg->base), &val); if (rc < 0) { smblite_lib_err(chg, "Couldn't read CHARGING_PAUSE_CMD rc=%d\n", rc); @@ -839,7 +957,7 @@ int smblite_lib_get_prop_batt_status(struct smb_charger *chg, } usb_online = (bool)pval.intval; - rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat); + rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", rc); @@ -903,7 +1021,7 @@ int smblite_lib_get_prop_batt_charge_type(struct smb_charger *chg, int rc; u8 stat; - rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat); + rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", rc); @@ -936,7 +1054,7 @@ int smblite_lib_get_prop_batt_health(struct smb_charger *chg, int effective_fv_uv; u8 stat; - rc = smblite_lib_read(chg, CHARGER_VBAT_STATUS_REG, &stat); + rc = smblite_lib_read(chg, CHARGER_VBAT_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read CHARGER_VBAT_STATUS_REG rc=%d\n", rc); @@ -963,7 +1081,7 @@ int smblite_lib_get_prop_batt_health(struct smb_charger *chg, } } - rc = smblite_lib_read(chg, BATTERY_TEMP_STATUS_REG, &stat); + rc = smblite_lib_read(chg, BATTERY_TEMP_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n", rc); @@ -1009,7 +1127,7 @@ int smblite_lib_get_prop_input_current_limited(struct smb_charger *chg, return 0; } - rc = smblite_lib_read(chg, AICL_STATUS_REG, &stat); + rc = smblite_lib_read(chg, AICL_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", rc); return rc; @@ -1030,7 +1148,7 @@ int smblite_lib_get_prop_batt_iterm(struct smb_charger *chg, * and validate, hence read only the threshold corresponding to ADC * source. Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0. */ - rc = smblite_lib_read(chg, CHGR_TERM_CFG_REG, &stat); + rc = smblite_lib_read(chg, CHGR_TERM_CFG_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read CHGR_TERM_CFG_REG rc=%d\n", rc); @@ -1042,7 +1160,7 @@ int smblite_lib_get_prop_batt_iterm(struct smb_charger *chg, return 0; } - rc = smblite_lib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2); + rc = smblite_lib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG(chg->base), buf, 2); if (rc < 0) { smblite_lib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n", @@ -1067,7 +1185,7 @@ int smblite_lib_get_prop_batt_charge_done(struct smb_charger *chg, int rc; u8 stat; - rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat); + rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", rc); @@ -1167,13 +1285,39 @@ int smblite_lib_set_prop_system_temp_level(struct smb_charger *chg, return 0; } +static int smblite_lib_dp_pulse(struct smb_charger *chg) +{ + int rc; + + /* QC 3.0 increment */ + rc = smblite_lib_masked_write(chg, CMD_HVDCP_REG(chg->base), SINGLE_INCREMENT_BIT, + SINGLE_INCREMENT_BIT); + if (rc < 0) + smblite_lib_err(chg, "Couldn't write to CMD_HVDCP_REG rc=%d\n", + rc); + + return rc; +} + +int smblite_lib_force_vbus_voltage(struct smb_charger *chg, u8 val) +{ + int rc; + + rc = smblite_lib_masked_write(chg, CMD_HVDCP_REG(chg->base), val, val); + if (rc < 0) + smblite_lib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n", + rc); + + return rc; +} + int smblite_lib_set_prop_rechg_soc_thresh(struct smb_charger *chg, const int val) { int rc; u8 new_thr = DIV_ROUND_CLOSEST(val * 255, 100); - rc = smblite_lib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG, + rc = smblite_lib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG(chg->base), new_thr); if (rc < 0) { smblite_lib_err(chg, "Couldn't write to RCHG_SOC_THRESHOLD_CFG_REG rc=%d\n", @@ -1191,7 +1335,7 @@ int smblite_lib_run_aicl(struct smb_charger *chg, int type) int rc; u8 stat; - rc = smblite_lib_read(chg, POWER_PATH_STATUS_REG, &stat); + rc = smblite_lib_read(chg, POWER_PATH_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc); @@ -1205,7 +1349,7 @@ int smblite_lib_run_aicl(struct smb_charger *chg, int type) smblite_lib_dbg(chg, PR_MISC, "re-running AICL\n"); stat = (type == RERUN_AICL) ? RERUN_AICL_BIT : RESTART_AICL_BIT; - rc = smblite_lib_masked_write(chg, AICL_CMD_REG, stat, stat); + rc = smblite_lib_masked_write(chg, AICL_CMD_REG(chg->base), stat, stat); if (rc < 0) smblite_lib_err(chg, "Couldn't write to AICL_CMD_REG rc=%d\n", rc); @@ -1222,7 +1366,7 @@ int smblite_lib_get_prop_usb_present(struct smb_charger *chg, int rc; u8 stat; - rc = smblite_lib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); + rc = smblite_lib_read(chg, chg->base.usbin_base + INT_RT_STS_OFFSET, &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read USBIN_RT_STS rc=%d\n", rc); return rc; @@ -1243,7 +1387,7 @@ int smblite_lib_get_prop_usb_online(struct smb_charger *chg, return rc; } - rc = smblite_lib_read(chg, POWER_PATH_STATUS_REG, &stat); + rc = smblite_lib_read(chg, POWER_PATH_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc); @@ -1311,7 +1455,7 @@ int smblite_lib_get_prop_usb_voltage_now(struct smb_charger *chg, * OTG mode. */ if (!pval.intval) { - rc = smblite_lib_read(chg, DCDC_CMD_OTG_REG, ®); + rc = smblite_lib_read(chg, DCDC_CMD_OTG_REG(chg->base), ®); if (rc < 0) { smblite_lib_err(chg, "Couldn't read CMD_OTG rc=%d", rc); goto out; @@ -1369,7 +1513,7 @@ int smblite_lib_get_prop_typec_cc_orientation(struct smb_charger *chg, if (chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB) return 0; - rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); @@ -1401,7 +1545,7 @@ static int smblite_lib_get_prop_ufp_mode(struct smb_charger *chg) int rc; u8 stat; - rc = smblite_lib_read(chg, TYPE_C_SNK_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_SNK_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc); @@ -1434,7 +1578,7 @@ static int smblite_lib_get_prop_dfp_mode(struct smb_charger *chg) int rc; u8 stat; - rc = smblite_lib_read(chg, TYPE_C_SRC_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_SRC_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_SRC_STATUS_REG rc=%d\n", rc); @@ -1465,7 +1609,7 @@ static int smblite_lib_get_prop_typec_mode(struct smb_charger *chg) if (chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB) return QTI_POWER_SUPPLY_TYPEC_NONE; - rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_MISC_STATUS_REG rc=%d\n", rc); @@ -1502,7 +1646,7 @@ int smblite_lib_get_prop_typec_power_role(struct smb_charger *chg, return 0; } - rc = smblite_lib_read(chg, TYPE_C_MODE_CFG_REG, &ctrl); + rc = smblite_lib_read(chg, TYPE_C_MODE_CFG_REG(chg->base), &ctrl); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_MODE_CFG_REG rc=%d\n", rc); @@ -1547,9 +1691,13 @@ int smblite_lib_get_prop_input_current_settled(struct smb_charger *chg, int smblite_lib_get_prop_input_voltage_settled(struct smb_charger *chg, int *val) { - /* TODO: do we need to read the real VBUS */ - *val = 5000000; - return 0; + union power_supply_propval pval = {0, }; + int rc; + + rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); + *val = pval.intval; + + return rc; } int smblite_lib_get_prop_die_health(struct smb_charger *chg) @@ -1565,7 +1713,7 @@ int smblite_lib_get_prop_die_health(struct smb_charger *chg) if (input_present == INPUT_NOT_PRESENT) return POWER_SUPPLY_HEALTH_UNKNOWN; - rc = smblite_lib_read(chg, DIE_TEMP_STATUS_REG, &stat); + rc = smblite_lib_read(chg, DIE_TEMP_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read DIE_TEMP_STATUS_REG, rc=%d\n", rc); @@ -1724,7 +1872,7 @@ int smblite_lib_set_prop_typec_power_role(struct smb_charger *chg, return -EINVAL; } - rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG, + rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG(chg->base), TYPEC_POWER_ROLE_CMD_MASK | TYPEC_TRY_MODE_MASK, power_role); if (rc < 0) { @@ -1745,7 +1893,7 @@ int smblite_lib_set_prop_ship_mode(struct smb_charger *chg, smblite_lib_dbg(chg, PR_MISC, "Set ship mode: %d!!\n", !!val); - rc = smblite_lib_masked_write(chg, SHIP_MODE_REG, SHIP_MODE_EN_BIT, + rc = smblite_lib_masked_write(chg, SHIP_MODE_REG(chg->base), SHIP_MODE_EN_BIT, !!val ? SHIP_MODE_EN_BIT : 0); if (rc < 0) dev_err(chg->dev, "Couldn't %s ship mode, rc=%d\n", @@ -1763,10 +1911,10 @@ static int smblite_lib_update_jeita(struct smb_charger *chg, u32 *thresholds, u16 temp, base_low, base_high; - base_low = (type == JEITA_SOFT) ? CHGR_JEITA_COOL_THRESHOLD_REG - : CHGR_JEITA_COLD_THRESHOLD_REG; - base_high = (type == JEITA_SOFT) ? CHGR_JEITA_WARM_THRESHOLD_REG - : CHGR_JEITA_HOT_THRESHOLD_REG; + base_low = (type == JEITA_SOFT) ? CHGR_JEITA_COOL_THRESHOLD_REG(chg->base) + : CHGR_JEITA_COLD_THRESHOLD_REG(chg->base); + base_high = (type == JEITA_SOFT) ? CHGR_JEITA_WARM_THRESHOLD_REG(chg->base) + : CHGR_JEITA_HOT_THRESHOLD_REG(chg->base); temp = thresholds[1] & 0xFFFF; temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8); rc = smblite_lib_batch_write(chg, base_high, (u8 *)&temp, 2); @@ -1797,7 +1945,7 @@ static int smblite_lib_charge_inhibit_en(struct smb_charger *chg, bool enable) { int rc; - rc = smblite_lib_masked_write(chg, CHGR_INHIBIT_REG, + rc = smblite_lib_masked_write(chg, CHGR_INHIBIT_REG(chg->base), CHGR_INHIBIT_BIT, enable ? CHGR_INHIBIT_BIT : 0); return rc; @@ -1903,7 +2051,7 @@ int smblite_lib_get_hw_current_max(struct smb_charger *chg, bool non_compliant; u8 stat; - rc = smblite_lib_read(chg, LEGACY_CABLE_STATUS_REG, &stat); + rc = smblite_lib_read(chg, LEGACY_CABLE_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc); @@ -2000,7 +2148,7 @@ irqreturn_t smblite_chg_state_change_irq_handler(int irq, void *data) smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); - rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat); + rc = smblite_lib_read(chg, BATTERY_CHARGER_STATUS_1_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n", rc); @@ -2152,6 +2300,9 @@ static int smblite_lib_role_switch_failure(struct smb_charger *chg) int rc = 0; union power_supply_propval pval = {0, }; + if (!chg->use_extcon) + return 0; + rc = smblite_lib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblite_lib_err(chg, "Couldn't get usb presence status rc=%d\n", @@ -2248,7 +2399,6 @@ static void smblite_lib_micro_usb_plugin(struct smb_charger *chg, int rc = 0; if (vbus_rising) { - smblite_lib_notify_device_mode(chg, true); rc = typec_partner_register(chg); if (rc < 0) smblite_lib_err(chg, "Couldn't register partner rc =%d\n", @@ -2269,7 +2419,7 @@ static void smblite_lib_usb_plugin_locked(struct smb_charger *chg) struct smb_irq_data *data; struct storm_watch *wdata; - rc = smblite_lib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); + rc = smblite_lib_read(chg, chg->base.usbin_base + INT_RT_STS_OFFSET, &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc); @@ -2399,7 +2549,15 @@ static void update_sw_icl_max(struct smb_charger *chg, break; case POWER_SUPPLY_TYPE_USB_DCP: rp_ua = get_rp_based_dcp_current(chg, typec_mode); - vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); + vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); + break; + case QTI_POWER_SUPPLY_TYPE_USB_FLOAT: + /* + * limit ICL to 100mA, the USB driver will enumerate to check + * if this is a SDP and appropriately set the current + */ + vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, + USBIN_100UA); break; case POWER_SUPPLY_TYPE_UNKNOWN: default: @@ -2419,6 +2577,244 @@ static void update_sw_icl_max(struct smb_charger *chg, } } +/* triggers when HVDCP is detected */ +static void smblite_lib_handle_hvdcp_detect_done(struct smb_charger *chg, + bool rising) +{ + smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-detect-done %s\n", + rising ? "rising" : "falling"); +} + +void smblite_lib_rerun_apsd(struct smb_charger *chg) +{ + int rc; + + smblite_lib_dbg(chg, PR_MISC, "re-running APSD\n"); + + rc = smblite_lib_masked_write(chg, CMD_APSD_REG(chg->base), + APSD_RERUN_BIT, APSD_RERUN_BIT); + if (rc < 0) + smblite_lib_err(chg, "Couldn't re-run APSD rc=%d\n", rc); +} + +static int smblite_lib_request_dpdm(struct smb_charger *chg, bool enable) +{ + int rc = 0; + + /* fetch the DPDM regulator */ + if (!chg->dpdm_reg && of_get_property(chg->dev->of_node, + "dpdm-supply", NULL)) { + chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm"); + if (IS_ERR(chg->dpdm_reg)) { + rc = PTR_ERR(chg->dpdm_reg); + smblite_lib_err(chg, "Couldn't get dpdm regulator rc=%d\n", + rc); + chg->dpdm_reg = NULL; + return rc; + } + } + + mutex_lock(&chg->dpdm_lock); + if (enable) { + if (chg->dpdm_reg && !chg->dpdm_enabled) { + smblite_lib_dbg(chg, PR_MISC, "enabling DPDM regulator\n"); + rc = regulator_enable(chg->dpdm_reg); + if (rc < 0) + smblite_lib_err(chg, + "Couldn't enable dpdm regulator rc=%d\n", + rc); + else + chg->dpdm_enabled = true; + } + } else { + if (chg->dpdm_reg && chg->dpdm_enabled) { + smblite_lib_dbg(chg, PR_MISC, "disabling DPDM regulator\n"); + rc = regulator_disable(chg->dpdm_reg); + if (rc < 0) + smblite_lib_err(chg, + "Couldn't disable dpdm regulator rc=%d\n", + rc); + else + chg->dpdm_enabled = false; + } + } + mutex_unlock(&chg->dpdm_lock); + + return rc; +} + +static int smblite_lib_rerun_apsd_if_required(struct smb_charger *chg) +{ + union power_supply_propval val; + int rc; + + rc = smblite_lib_get_prop_usb_present(chg, &val); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't get usb present rc = %d\n", rc); + return rc; + } + + if (!val.intval) + return 0; + + rc = smblite_lib_request_dpdm(chg, true); + if (rc < 0) + smblite_lib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc); + + chg->uusb_apsd_rerun_done = true; + smblite_lib_rerun_apsd(chg); + + return 0; +} + +static void smblite_lib_handle_apsd_done(struct smb_charger *chg, bool rising) +{ + const struct apsd_result *apsd_result = + smblite_lib_get_apsd_result(chg); + + if (!rising) + return; + + apsd_result = smblite_lib_update_usb_type(chg, apsd_result->val); + + switch (apsd_result->bit) { + case SDP_CHARGER_BIT: + case CDP_CHARGER_BIT: + case FLOAT_CHARGER_BIT: + if (chg->use_extcon) + smblite_lib_notify_device_mode(chg, true); + break; + case OCP_CHARGER_BIT: + case DCP_CHARGER_BIT: + break; + default: + break; + } + + smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n", + apsd_result->name); +} + +#define HVDCP3_QUALIFICATION_UV (PM5100_MAX_HVDCP3_PULSES * \ + (HVDCP3_STEP_SIZE_UV / 2)) +static void smblite_lib_handle_hvdcp_check_timeout(struct smb_charger *chg, + bool rising, bool qc_charger) +{ + union power_supply_propval pval = {0, }; + int rc = 0, cnt = 0, prev_vbus; + + if (rising) { + + if (qc_charger) { + rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", + rc); + goto failure; + } + + prev_vbus = pval.intval; + + /* + * Statically increase voltage till 6V. + * ( i.e : 1V / 200mV = 5 pulses ). + */ + while (cnt++ < PM5100_MAX_HVDCP3_PULSES) { + smblite_lib_dp_pulse(chg); + /* wait for 100ms for vbus to settle. */ + msleep(100); + } + + rc = smblite_lib_get_prop_usb_voltage_now(chg, &pval); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't read voltage_now rc=%d\n", + rc); + goto failure; + } + + /* Check if voltage incremented. (i.e if QC3 )*/ + if (pval.intval >= (prev_vbus + HVDCP3_QUALIFICATION_UV)) + chg->hvdcp3_detected = true; + + smblite_lib_dbg(chg, PR_MISC, "HVDCP3 : detected=%s, prev_vbus=%d, vbus_now=%d\n", + (chg->hvdcp3_detected ? "True" : "False"), + prev_vbus, pval.intval); + } + } + +failure: + smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", __func__, + rising ? "rising" : "falling"); +} + +static void smblite_lib_handle_sdp_enumeration_done(struct smb_charger *chg, + bool rising) +{ + smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: sdp-enumeration-done %s\n", + rising ? "rising" : "falling"); +} + +static void smblite_lib_handle_slow_plugin_timeout(struct smb_charger *chg, + bool rising) +{ + smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: slow-plugin-timeout %s\n", + rising ? "rising" : "falling"); +} + +irqreturn_t smblite_usb_source_change_irq_handler(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb_charger *chg = irq_data->parent_data; + int rc = 0; + u8 stat; + + rc = smblite_lib_read(chg, APSD_STATUS_REG(chg->base), &stat); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc); + return IRQ_HANDLED; + } + smblite_lib_dbg(chg, PR_INTERRUPT, "APSD_STATUS = 0x%02x\n", stat); + + if ((chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB) + && (stat & APSD_DTC_STATUS_DONE_BIT) + && !chg->uusb_apsd_rerun_done) { + /* + * Force re-run APSD to handle slow insertion related + * charger-mis-detection. + */ + chg->uusb_apsd_rerun_done = true; + smblite_lib_rerun_apsd_if_required(chg); + return IRQ_HANDLED; + } + + smblite_lib_handle_apsd_done(chg, + (bool)(stat & APSD_DTC_STATUS_DONE_BIT)); + + smblite_lib_handle_hvdcp_detect_done(chg, + (bool)(stat & QC_CHARGER_BIT)); + + smblite_lib_handle_hvdcp_check_timeout(chg, + (bool)(stat & HVDCP_CHECK_TIMEOUT_BIT), + (bool)(stat & QC_CHARGER_BIT)); + + smblite_lib_handle_sdp_enumeration_done(chg, + (bool)(stat & ENUMERATION_DONE_BIT)); + + smblite_lib_handle_slow_plugin_timeout(chg, + (bool)(stat & SLOW_PLUGIN_TIMEOUT_BIT)); + + power_supply_changed(chg->usb_psy); + + rc = smblite_lib_read(chg, APSD_STATUS_REG(chg->base), &stat); + if (rc < 0) { + smblite_lib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc); + return IRQ_HANDLED; + } + smblite_lib_dbg(chg, PR_INTERRUPT, "APSD_STATUS = 0x%02x\n", stat); + + return IRQ_HANDLED; +} + static void typec_sink_insertion(struct smb_charger *chg) { smblite_lib_notify_usb_host(chg, true); @@ -2435,7 +2831,7 @@ static void typec_src_insertion(struct smb_charger *chg) return; } - rc = smblite_lib_read(chg, LEGACY_CABLE_STATUS_REG, &stat); + rc = smblite_lib_read(chg, LEGACY_CABLE_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_STATE_MACHINE_STATUS_REG rc=%d\n", rc); @@ -2462,7 +2858,7 @@ static int smblite_lib_force_dr_mode(struct smb_charger *chg, int mode) switch (mode) { case TYPEC_PORT_SNK: - rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG, + rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG(chg->base), TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT); if (rc < 0) { smblite_lib_err(chg, "Couldn't enable snk, rc=%d\n", @@ -2471,7 +2867,7 @@ static int smblite_lib_force_dr_mode(struct smb_charger *chg, int mode) } break; case TYPEC_PORT_SRC: - rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG, + rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG(chg->base), TYPEC_POWER_ROLE_CMD_MASK, EN_SRC_ONLY_BIT); if (rc < 0) { smblite_lib_err(chg, "Couldn't enable src, rc=%d\n", @@ -2480,7 +2876,7 @@ static int smblite_lib_force_dr_mode(struct smb_charger *chg, int mode) } break; case TYPEC_PORT_DRP: - rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG, + rc = smblite_lib_masked_write(chg, TYPE_C_MODE_CFG_REG(chg->base), TYPEC_POWER_ROLE_CMD_MASK, 0); if (rc < 0) { smblite_lib_err(chg, "Couldn't enable DRP, rc=%d\n", @@ -2646,6 +3042,7 @@ static void typec_src_removal(struct smb_charger *chg) smblite_lib_notify_device_mode(chg, false); chg->typec_legacy = false; + chg->hvdcp3_detected = false; } static void typec_mode_unattached(struct smb_charger *chg) @@ -2725,7 +3122,7 @@ irqreturn_t smblite_typec_attach_detach_irq_handler(int irq, void *data) smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); - rc = smblite_lib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_STATE_MACHINE_STATUS_REG rc=%d\n", rc); @@ -2735,7 +3132,7 @@ irqreturn_t smblite_typec_attach_detach_irq_handler(int irq, void *data) attached = !!(stat & TYPEC_ATTACH_DETACH_STATE_BIT); if (attached) { - rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read TYPE_C_MISC_STATUS_REG rc=%d\n", rc); @@ -2803,7 +3200,7 @@ irqreturn_t smblite_typec_attach_detach_irq_handler(int irq, void *data) } } - rc = smblite_lib_masked_write(chg, USB_CMD_PULLDOWN_REG, + rc = smblite_lib_masked_write(chg, USB_CMD_PULLDOWN_REG(chg->base), EN_PULLDOWN_USB_IN_BIT, attached ? 0 : EN_PULLDOWN_USB_IN_BIT); if (rc < 0) @@ -2838,7 +3235,7 @@ irqreturn_t smblite_switcher_power_ok_irq_handler(int irq, void *data) if (!(chg->wa_flags & BOOST_BACK_WA)) return IRQ_HANDLED; - rc = smblite_lib_read(chg, POWER_PATH_STATUS_REG, &stat); + rc = smblite_lib_read(chg, POWER_PATH_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc); @@ -2890,7 +3287,7 @@ irqreturn_t smblite_wdog_bark_irq_handler(int irq, void *data) smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name); - rc = smblite_lib_write(chg, BARK_BITE_WDOG_PET_REG, + rc = smblite_lib_write(chg, BARK_BITE_WDOG_PET_REG(chg->base), BARK_BITE_WDOG_PET_BIT); if (rc < 0) smblite_lib_err(chg, "Couldn't pet the dog rc=%d\n", rc); @@ -2973,7 +3370,7 @@ static void smblite_lib_pr_swap_detach_work(struct work_struct *work) int rc; u8 stat; - rc = smblite_lib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG, &stat); + rc = smblite_lib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read STATE_MACHINE_STS rc=%d\n", rc); @@ -3070,7 +3467,7 @@ static void smblite_lib_thermal_regulation_work(struct work_struct *work) goto exit; } - rc = smblite_lib_read(chg, DIE_TEMP_STATUS_REG, &stat); + rc = smblite_lib_read(chg, DIE_TEMP_STATUS_REG(chg->base), &stat); if (rc < 0) { smblite_lib_err(chg, "Couldn't read DIE_TEMP_STATUS_REG, rc=%d\n", rc); @@ -3208,7 +3605,7 @@ static void jeita_update_work(struct work_struct *work) } } else { /* Populate the jeita-soft-thresholds */ - addr = CHGR_JEITA_COOL_THRESHOLD_REG; + addr = CHGR_JEITA_COOL_THRESHOLD_REG(chg->base); rc = smblite_lib_batch_read(chg, addr, buff, 2); if (rc < 0) { pr_err("Couldn't to read 0x%4X, rc=%d\n", addr, rc); diff --git a/drivers/power/supply/qcom/smblite-lib.h b/drivers/power/supply/qcom/smblite-lib.h index 735b2a73d54a..023301631f0d 100644 --- a/drivers/power/supply/qcom/smblite-lib.h +++ b/drivers/power/supply/qcom/smblite-lib.h @@ -73,6 +73,11 @@ enum print_reason { #define TYPEC_MEDIUM_CURRENT_UA 1500000 #define TYPEC_HIGH_CURRENT_UA 3000000 #define ROLE_REVERSAL_DELAY_MS 500 +/* Max supported voltage 6V */ +#define HVDCP3_STEP_SIZE_UV 200000 +#define PM5100_MAX_HVDCP3_PULSES 5 +#define PM5100_HVDCP3_MAX_VOLTAGE_UV (PM5100_MAX_HVDCP3_PULSES * \ + HVDCP3_STEP_SIZE_UV) enum smb_mode { PARALLEL_MASTER = 0, @@ -128,6 +133,7 @@ enum smb_irq_index { USBIN_UV_IRQ, USBIN_OV_IRQ, USBIN_GT_VT_IRQ, + USBIN_SRC_CHANGE_IRQ, USBIN_ICL_CHANGE_IRQ, /* TYPEC */ TYPEC_OR_RID_DETECTION_CHANGE_IRQ, @@ -156,6 +162,12 @@ enum smb_irq_index { SMB_IRQ_MAX, }; +struct apsd_result { + const char * const name; + const u8 bit; + const int val; +}; + enum chg_term_config_src { ITERM_SRC_UNSPECIFIED, ITERM_SRC_ADC, @@ -229,6 +241,16 @@ struct smb_iio { enum pmic_type { PM2250, + PM5100, +}; + +struct smb_base_address { + u16 chg_base; + u16 batif_base; + u16 usbin_base; + u16 misc_base; + u16 dcdc_base; + u16 typec_base; }; struct smb_charger { @@ -237,6 +259,7 @@ struct smb_charger { struct regmap *regmap; struct smb_irq_info *irq_info; struct smb_params param; + struct smb_base_address base; struct smb_iio iio; struct iio_channel *iio_chans; struct iio_channel **iio_chan_list_qg; @@ -247,6 +270,7 @@ struct smb_charger { /* locks */ struct mutex typec_lock; + struct mutex dpdm_lock; /* power supplies */ struct power_supply *batt_psy; @@ -256,6 +280,9 @@ struct smb_charger { /* notifiers */ struct notifier_block nb; + /* Regulators */ + struct regulator *dpdm_reg; + /* parallel charging */ struct parallel_params pl; @@ -328,6 +355,10 @@ struct smb_charger { int usb_id_gpio; int usb_id_irq; bool typec_role_swap_failed; + bool use_extcon; + bool uusb_apsd_rerun_done; + bool dpdm_enabled; + bool hvdcp3_detected; /* workaround flag */ u32 wa_flags; @@ -379,6 +410,7 @@ irqreturn_t smblite_typec_or_rid_detection_change_irq_handler(int irq, irqreturn_t smblite_temp_change_irq_handler(int irq, void *data); irqreturn_t smblite_usbin_ov_irq_handler(int irq, void *data); irqreturn_t smblite_usb_id_irq_handler(int irq, void *data); +irqreturn_t smblite_usb_source_change_irq_handler(int irq, void *data); int smblite_lib_get_prop_batt_present(struct smb_charger *chg, union power_supply_propval *val); @@ -463,10 +495,13 @@ int smblite_lib_icl_override(struct smb_charger *chg, enum icl_override_mode mode); int smblite_lib_set_prop_usb_type(struct smb_charger *chg, const int val); +const struct apsd_result *smblite_lib_get_apsd_result(struct smb_charger *chg); void smblite_update_usb_desc(struct smb_charger *chg); int smblite_lib_init(struct smb_charger *chg); int smblite_lib_deinit(struct smb_charger *chg); int smblite_iio_get_prop(struct smb_charger *chg, int channel, int *val); int smblite_iio_set_prop(struct smb_charger *chg, int channel, int val); +int smblite_lib_get_fcc(struct smb_chg_param *param, u8 val_raw); +int smblite_lib_set_fcc(struct smb_chg_param *param, int val_u, u8 *val_raw); #endif /* __SMBLITE_LIB_H */ diff --git a/drivers/power/supply/qcom/smblite-reg.h b/drivers/power/supply/qcom/smblite-reg.h index c5bd0707d03f..14f5c80e5751 100644 --- a/drivers/power/supply/qcom/smblite-reg.h +++ b/drivers/power/supply/qcom/smblite-reg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. */ #ifndef __SMBLITE_CHARGER_REG_H @@ -8,13 +8,6 @@ #include -#define CHGR_BASE 0x1000 -#define DCDC_BASE 0x1100 -#define BATIF_BASE 0x1200 -#define USBIN_BASE 0x1300 -#define TYPEC_BASE 0X1500 -#define MISC_BASE 0x1600 - #define PERPH_TYPE_OFFSET 0x04 #define TYPE_MASK GENMASK(7, 0) #define PERPH_SUBTYPE_OFFSET 0x05 @@ -24,7 +17,7 @@ /******************************** * CHGR Peripheral Registers * ********************************/ -#define BATTERY_CHARGER_STATUS_1_REG (CHGR_BASE + 0x06) +#define BATTERY_CHARGER_STATUS_1_REG(base) (base.chg_base + 0x06) #define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0) enum { INHIBIT_CHARGE = 0, @@ -37,10 +30,10 @@ enum { DISABLE_CHARGE, }; -#define CHARGER_VBAT_STATUS_REG (CHGR_BASE + 0x08) +#define CHARGER_VBAT_STATUS_REG(base) (base.chg_base + 0x08) #define BAT_OV_BIT BIT(7) -#define BATTERY_TEMP_STATUS_REG (BATIF_BASE + 0x0C) +#define BATTERY_TEMP_STATUS_REG(base) (base.batif_base + 0x0C) #define BAT_TEMP_STATUS_TOO_HOT_AFP_BIT BIT(5) #define BAT_TEMP_STATUS_TOO_HOT_BIT BIT(4) #define BAT_TEMP_STATUS_HOT_SOFT_BIT BIT(3) @@ -48,37 +41,37 @@ enum { #define BAT_TEMP_STATUS_TOO_COLD_BIT BIT(1) #define BAT_TEMP_STATUS_TOO_COLD_AFP_BIT BIT(0) -#define CHARGING_ENABLE_CMD_REG (CHGR_BASE + 0x46) +#define CHARGING_ENABLE_CMD_REG(base) (base.chg_base + 0x46) #define CHARGING_ENABLE_CMD_BIT BIT(0) #define CHARGING_PAUSE_CMD_BIT BIT(4) -#define CHGR_FAST_CHARGE_CURRENT_CFG_REG (CHGR_BASE + 0x54) -#define CHGR_FLOAT_VOLTAGE_CFG_REG (CHGR_BASE + 0x58) +#define CHGR_FAST_CHARGE_CURRENT_CFG_REG(base) (base.chg_base + 0x54) +#define CHGR_FLOAT_VOLTAGE_CFG_REG(base) (base.chg_base + 0x58) -#define CHGR_TERM_CFG_REG (CHGR_BASE + 0x60) +#define CHGR_TERM_CFG_REG(base) (base.chg_base + 0x60) #define CHGR_ITERM_USE_ANALOG_BIT BIT(3) -#define CHGR_ADC_ITERM_UP_THD_MSB_REG (CHGR_BASE + 0x64) -#define CHGR_ADC_ITERM_UP_THD_LSB_REG (CHGR_BASE + 0x65) -#define CHGR_ADC_ITERM_LO_THD_MSB_REG (CHGR_BASE + 0x66) -#define CHGR_ADC_ITERM_LO_THD_LSB_REG (CHGR_BASE + 0x67) +#define CHGR_ADC_ITERM_UP_THD_MSB_REG(base) (base.chg_base + 0x64) +#define CHGR_ADC_ITERM_UP_THD_LSB_REG(base) (base.chg_base + 0x65) +#define CHGR_ADC_ITERM_LO_THD_MSB_REG(base) (base.chg_base + 0x66) +#define CHGR_ADC_ITERM_LO_THD_LSB_REG(base) (base.chg_base + 0x67) -#define CHGR_RECHG_CFG_REG (CHGR_BASE + 0x70) +#define CHGR_RECHG_CFG_REG(base) (base.chg_base + 0x70) #define RECHG_MASK GENMASK(7, 6) #define VBAT_BASED_RECHG_BIT BIT(7) #define SOC_BASED_RECHG_BIT GENMASK(7, 6) #define NO_OF_SAMPLE_FOR_RCHG GENMASK(1, 0) -#define CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG (CHGR_BASE + 0x72) +#define CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG(base) (base.chg_base + 0x72) -#define CHARGE_RCHG_SOC_THRESHOLD_CFG_REG (CHGR_BASE + 0x74) +#define CHARGE_RCHG_SOC_THRESHOLD_CFG_REG(base) (base.chg_base + 0x74) -#define CHGR_INHIBIT_REG (CHGR_BASE + 0x78) +#define CHGR_INHIBIT_REG(base) (base.chg_base + 0x78) #define CHGR_INHIBIT_BIT BIT(7) -#define CHGR_INHIBIT_THRESHOLD_CFG_REG (CHGR_BASE + 0x7A) +#define CHGR_INHIBIT_THRESHOLD_CFG_REG(base) (base.chg_base + 0x7A) -#define CHGR_FAST_CHARGE_SAFETY_TIMER_CFG_REG (CHGR_BASE + 0x90) +#define CHGR_FAST_CHARGE_SAFETY_TIMER_CFG_REG(base) (base.chg_base + 0x90) #define FAST_CHARGE_SAFETY_TIMER_EN_BIT BIT(3) #define FAST_CHARGE_SAFETY_TIMER_MASK GENMASK(1, 0) #define FAST_CHARGE_SAFETY_TIMER_192_MIN 0x0 @@ -89,25 +82,25 @@ enum { /******************************** * DCDC Peripheral Registers * ********************************/ -#define ICL_MAX_STATUS_REG (DCDC_BASE + 0x06) -#define ICL_STATUS_REG (DCDC_BASE + 0x09) +#define ICL_MAX_STATUS_REG(base) (base.dcdc_base + 0x06) +#define ICL_STATUS_REG(base) (base.dcdc_base + 0x09) -#define POWER_PATH_STATUS_REG (DCDC_BASE + 0x0B) +#define POWER_PATH_STATUS_REG(base) (base.dcdc_base + 0x0B) #define VALID_INPUT_POWER_SOURCE_STS_BIT BIT(7) #define USE_USBIN_BIT BIT(5) #define USBIN_SUSPEND_STS_BIT BIT(3) #define POWER_PATH_MASK GENMASK(1, 0) -#define DCDC_CMD_OTG_REG (DCDC_BASE + 0x50) +#define DCDC_CMD_OTG_REG(base) (base.dcdc_base + 0x50) #define OTG_EN_BIT BIT(0) -#define DCDC_BST_VREG_SEL (DCDC_BASE + 0x52) +#define DCDC_BST_VREG_SEL(base) (base.dcdc_base + 0x52) #define VBOOST_MASK GENMASK(1, 0) -#define DCDC_OTG_CFG_REG (DCDC_BASE + 0x56) +#define DCDC_OTG_CFG_REG(base) (base.dcdc_base + 0x56) #define OTG_EN_SRC_CFG_BIT BIT(0) -#define DCDC_LDO_CFG_REG (DCDC_BASE + 0x70) +#define DCDC_LDO_CFG_REG(base) (base.dcdc_base + 0x70) #define LDO_MODE_BIT BIT(0) /******************************** @@ -120,13 +113,13 @@ enum { #define BAT_THERM_OR_ID_MISSING_RT_STS_BIT BIT(1) #define BAT_TEMP_RT_STS_BIT BIT(0) -#define SHIP_MODE_REG (BATIF_BASE + 0x52) +#define SHIP_MODE_REG(base) (base.batif_base + 0x52) #define SHIP_MODE_EN_BIT BIT(0) -#define CHGR_JEITA_HOT_THRESHOLD_REG (BATIF_BASE + 0x84) -#define CHGR_JEITA_WARM_THRESHOLD_REG (BATIF_BASE + 0x86) -#define CHGR_JEITA_COOL_THRESHOLD_REG (BATIF_BASE + 0x88) -#define CHGR_JEITA_COLD_THRESHOLD_REG (BATIF_BASE + 0x8A) +#define CHGR_JEITA_HOT_THRESHOLD_REG(base) (base.batif_base + 0x84) +#define CHGR_JEITA_WARM_THRESHOLD_REG(base) (base.batif_base + 0x86) +#define CHGR_JEITA_COOL_THRESHOLD_REG(base) (base.batif_base + 0x88) +#define CHGR_JEITA_COLD_THRESHOLD_REG(base) (base.batif_base + 0x8A) /******************************** @@ -141,34 +134,67 @@ enum { #define USBIN_COLLAPSE_RT_STS_BIT BIT(1) #define USBIN_PLUGIN_RT_STS_BIT BIT(0) -#define USBIN_ICL_OPTIONS_REG (USBIN_BASE + 0x50) +#define USBIN_ICL_OPTIONS_REG(base) (base.usbin_base + 0x50) #define USBIN_MODE_CHG_BIT BIT(2) -#define USB51_MODE_BIT BIT(1) +#define USB51_MODE_BIT BIT(1) +#define CFG_USB3P0_SEL_BIT BIT(0) -#define CMD_ICL_OVERRIDE_REG (USBIN_BASE + 0x51) +#define CMD_ICL_OVERRIDE_REG(base) (base.usbin_base + 0x51) #define ICL_OVERRIDE_BIT BIT(0) -#define USBIN_CURRENT_LIMIT_CFG_REG (USBIN_BASE + 0x52) +#define USBIN_CURRENT_LIMIT_CFG_REG(base) (base.usbin_base + 0x52) -#define USBIN_INPUT_SUSPEND_REG (USBIN_BASE + 0x54) +#define USBIN_INPUT_SUSPEND_REG(base) (base.usbin_base + 0x54) #define SUSPEND_ON_COLLAPSE_USBIN_BIT BIT(7) #define USBIN_SUSPEND_BIT BIT(0) -#define USBIN_AICL_OPTIONS_CFG_REG (USBIN_BASE + 0x60) +#define USBIN_AICL_OPTIONS_CFG_REG(base) (base.usbin_base + 0x60) #define USBIN_AICL_EN_BIT BIT(7) #define USBIN_AICL_START_AT_MAX BIT(4) #define USBIN_AICL_STEP_TIMING_SEL_MASK GENMASK(3, 2) #define USBIN_IN_COLLAPSE_GF_SEL_MASK GENMASK(1, 0) -#define USBIN_LV_AICL_THRESHOLD_REG (USBIN_BASE + 0x63) +#define USBIN_LV_AICL_THRESHOLD_REG(base) (base.usbin_base + 0x63) -#define USB_CMD_PULLDOWN_REG (USBIN_BASE + 0x70) +#define USB_CMD_PULLDOWN_REG(base) (base.usbin_base + 0x70) #define EN_PULLDOWN_USB_IN_BIT BIT(0) +#define APSD_STATUS_REG(base) (base.usbin_base + 0x0a) +#define HVDCP_CHECK_TIMEOUT_BIT BIT(6) +#define SLOW_PLUGIN_TIMEOUT_BIT BIT(5) +#define ENUMERATION_DONE_BIT BIT(4) +#define VADP_CHANGE_DONE_AFTER_AUTH_BIT BIT(3) +#define QC_AUTH_DONE_STATUS_BIT BIT(2) +#define QC_CHARGER_BIT BIT(1) +#define APSD_DTC_STATUS_DONE_BIT BIT(0) + +#define APSD_RESULT_STATUS_REG(base) (base.usbin_base + 0x0b) +#define APSD_RESULT_STATUS_MASK GENMASK(6, 0) +#define QC_3P0_BIT BIT(6) +#define FLOAT_CHARGER_BIT BIT(4) +#define DCP_CHARGER_BIT BIT(3) +#define CDP_CHARGER_BIT BIT(2) +#define OCP_CHARGER_BIT BIT(1) +#define SDP_CHARGER_BIT BIT(0) + +#define CMD_APSD_REG(base) (base.usbin_base + 0x45) +#define APSD_RERUN_BIT BIT(0) + +#define USBIN_APSD_EN_REG(base) (base.usbin_base + 0x44) +#define BC1P2_SRC_DETECT_BIT BIT(7) + +#define CMD_HVDCP_REG(base) (base.usbin_base + 0x4a) +#define SINGLE_INCREMENT_BIT BIT(5) +#define SINGLE_DECREMENT_BIT BIT(4) +#define FORCE_12V_BIT BIT(3) +#define FORCE_9V_BIT BIT(2) +#define FORCE_5V_BIT BIT(1) +#define IDLE_BIT BIT(0) + /******************************** * TYPEC Peripheral Registers * ********************************/ -#define TYPE_C_SNK_STATUS_REG (TYPEC_BASE + 0x06) +#define TYPE_C_SNK_STATUS_REG(base) (base.typec_base + 0x06) #define DETECTED_SRC_TYPE_MASK GENMASK(6, 0) #define SNK_DAM_500MA_BIT BIT(6) #define SNK_DAM_1500MA_BIT BIT(5) @@ -178,7 +204,7 @@ enum { #define SNK_RP_3P0_BIT BIT(1) #define SNK_RP_SHORT_BIT BIT(0) -#define TYPE_C_SRC_STATUS_REG (TYPEC_BASE + 0x08) +#define TYPE_C_SRC_STATUS_REG(base) (base.typec_base + 0x08) #define DETECTED_SNK_TYPE_MASK GENMASK(4, 0) #define SRC_HIGH_BATT_BIT BIT(5) #define SRC_DEBUG_ACCESS_BIT BIT(4) @@ -186,27 +212,27 @@ enum { #define SRC_RA_OPEN_BIT BIT(1) #define AUDIO_ACCESS_RA_RA_BIT BIT(0) -#define TYPE_C_STATE_MACHINE_STATUS_REG (TYPEC_BASE + 0x09) +#define TYPE_C_STATE_MACHINE_STATUS_REG(base) (base.typec_base + 0x09) #define TYPEC_ATTACH_DETACH_STATE_BIT BIT(5) -#define TYPE_C_MISC_STATUS_REG (TYPEC_BASE + 0x0B) +#define TYPE_C_MISC_STATUS_REG(base) (base.typec_base + 0x0B) #define SNK_SRC_MODE_BIT BIT(6) #define TYPEC_VBUS_ERROR_STATUS_BIT BIT(4) #define TYPEC_TCCDEBOUNCE_DONE_STATUS_BIT BIT(3) #define CC_ORIENTATION_BIT BIT(1) #define CC_ATTACHED_BIT BIT(0) -#define LEGACY_CABLE_STATUS_REG (TYPEC_BASE + 0x0D) +#define LEGACY_CABLE_STATUS_REG(base) (base.typec_base + 0x0D) #define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(1) #define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(0) -#define TYPEC_U_USB_STATUS_REG (TYPEC_BASE + 0x0F) +#define TYPEC_U_USB_STATUS_REG(base) (base.typec_base + 0x0F) #define U_USB_GROUND_NOVBUS_BIT BIT(6) #define U_USB_GROUND_BIT BIT(4) #define U_USB_FLOAT1_BIT BIT(2) #define U_USB_FLOAT2_BIT BIT(0) -#define TYPE_C_MODE_CFG_REG (TYPEC_BASE + 0x44) +#define TYPE_C_MODE_CFG_REG(base) (base.typec_base + 0x44) #define TYPEC_TRY_MODE_MASK GENMASK(4, 3) #define EN_TRY_SNK_BIT BIT(4) #define EN_TRY_SRC_BIT BIT(3) @@ -215,15 +241,15 @@ enum { #define EN_SNK_ONLY_BIT BIT(1) #define TYPEC_DISABLE_CMD_BIT BIT(0) -#define DEBUG_ACCESS_SRC_CFG_REG (TYPEC_BASE + 0x4C) +#define DEBUG_ACCESS_SRC_CFG_REG(base) (base.typec_base + 0x4C) #define EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT BIT(0) -#define TYPE_C_EXIT_STATE_CFG_REG (TYPEC_BASE + 0x50) +#define TYPE_C_EXIT_STATE_CFG_REG(base) (base.typec_base + 0x50) #define BYPASS_VSAFE0V_DURING_ROLE_SWAP_BIT BIT(3) #define SEL_SRC_UPPER_REF_BIT BIT(2) #define EXIT_SNK_BASED_ON_CC_BIT BIT(0) -#define TYPE_C_CURRSRC_CFG_REG (TYPEC_BASE + 0x52) +#define TYPE_C_CURRSRC_CFG_REG(base) (base.typec_base + 0x52) #define TYPEC_SRC_RP_SEL_MASK GENMASK(1, 0) enum { TYPEC_SRC_RP_STD, @@ -233,7 +259,7 @@ enum { TYPEC_SRC_RP_MAX_ELEMENTS }; -#define TYPE_C_INTERRUPT_EN_CFG_1_REG (TYPEC_BASE + 0x5E) +#define TYPE_C_INTERRUPT_EN_CFG_1_REG(base) (base.typec_base + 0x5E) #define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(7) #define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT BIT(6) #define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(5) @@ -243,7 +269,7 @@ enum { #define TYPEC_VBUS_DEASSERT_INT_EN_BIT BIT(1) #define TYPEC_VBUS_ASSERT_INT_EN_BIT BIT(0) -#define TYPE_C_INTERRUPT_EN_CFG_2_REG (TYPEC_BASE + 0x60) +#define TYPE_C_INTERRUPT_EN_CFG_2_REG(base) (base.typec_base + 0x60) #define TYPEC_SRC_BATT_HPWR_INT_EN_BIT BIT(6) #define MICRO_USB_STATE_CHANGE_INT_EN_BIT BIT(5) #define TYPEC_STATE_MACHINE_CHANGE_INT_EN_BIT BIT(4) @@ -252,13 +278,13 @@ enum { #define TYPEC_VBUS_ERROR_INT_EN_BIT BIT(1) #define TYPEC_DEBOUNCE_DONE_INT_EN_BIT BIT(0) -#define TYPEC_U_USB_CFG_REG (TYPEC_BASE + 0x70) +#define TYPEC_U_USB_CFG_REG(base) (base.typec_base + 0x70) #define EN_MICRO_USB_MODE_BIT BIT(0) /******************************** * MISC Peripheral Registers * ********************************/ -#define TEMP_RANGE_STATUS_REG (MISC_BASE + 0x08) +#define TEMP_RANGE_STATUS_REG(base) (base.misc_base + 0x08) #define THERM_REG_ACTIVE_BIT BIT(6) #define TLIM_BIT BIT(5) #define TEMP_RANGE_MASK GENMASK(4, 1) @@ -268,37 +294,37 @@ enum { #define TEMP_BELOW_RANGE_BIT BIT(1) #define THERMREG_DISABLED_BIT BIT(0) -#define DIE_TEMP_STATUS_REG (MISC_BASE + 0x09) +#define DIE_TEMP_STATUS_REG(base) (base.misc_base + 0x09) #define DIE_TEMP_MASK GENMASK(3, 0) #define DIE_TEMP_SHDN_BIT BIT(3) #define DIE_TEMP_RST_BIT BIT(2) #define DIE_TEMP_UB_BIT BIT(1) #define DIE_TEMP_LB_BIT BIT(0) -#define AICL_STATUS_REG (MISC_BASE + 0x06) +#define AICL_STATUS_REG(base) (base.misc_base + 0x06) #define SOFT_ILIMIT_BIT BIT(6) #define AICL_DONE_BIT BIT(0) -#define AICL_CMD_REG (MISC_BASE + 0x50) +#define AICL_CMD_REG(base) (base.misc_base + 0x50) #define RESTART_AICL_BIT BIT(1) #define RERUN_AICL_BIT BIT(0) -#define MISC_SMB_EN_CMD_REG (MISC_BASE + 0x4C) +#define MISC_SMB_EN_CMD_REG(base) (base.misc_base + 0x4C) #define SMB_EN_OVERRIDE_VALUE_BIT BIT(0) #define SMB_EN_OVERRIDE_BIT BIT(1) -#define MISC_AICL_RERUN_CFG_REG (MISC_BASE + 0x54) +#define MISC_AICL_RERUN_CFG_REG(base) (base.misc_base + 0x54) #define USBIN_AICL_PERIODIC_RERUN_EN_BIT BIT(5) #define USBIN_AICL_RERUN_TIME_MASK GENMASK(1, 0) #define AICL_RERUN_TIME_12S_VAL 0x01 -#define WD_CFG_REG (MISC_BASE + 0x58) +#define WD_CFG_REG(base) (base.misc_base + 0x58) #define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7) #define BARK_WDOG_INT_EN_BIT BIT(4) #define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1) #define WDOG_TIMER_EN_BIT BIT(0) -#define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x59) +#define SNARL_BARK_BITE_WD_CFG_REG(base) (base.misc_base + 0x59) #define SNARL_WDOG_TIMEOUT_MASK GENMASK(2, 0) #define SNARL_WDOG_TMOUT_62P5MS 0x0 #define SNARL_WDOG_TMOUT_1S 0x4 @@ -310,7 +336,7 @@ enum { #define BITE_WDOG_TIMEOUT_SHIFT 6 #define MIN_WD_BARK_TIME 16 -#define BARK_BITE_WDOG_PET_REG (MISC_BASE + 0x5A) +#define BARK_BITE_WDOG_PET_REG(base) (base.misc_base + 0x5A) #define BARK_BITE_WDOG_PET_BIT BIT(0) #endif /* __SMBLITE_CHARGER_REG_H */