power: qpnp-smbcharger: Become the owner of usb_psy
The USB power_supply object should be maintained by the charger driver. Since it is now removed from the USB controller driver, create and register it here. Many of the calls to set/get_property can be simplified since there are equivalent state variables we have access to. PROP_OTG can be removed entirely since that is now handled by emitting an EXTCON_USB_HOST notification. Signed-off-by: Jack Pham <jackp@codeaurora.org>
This commit is contained in:
parent
ee53d51499
commit
f0a4dfdccc
1 changed files with 126 additions and 121 deletions
|
@ -198,6 +198,8 @@ struct smbchg_chip {
|
|||
u32 wa_flags;
|
||||
int usb_icl_delta;
|
||||
bool typec_dfp;
|
||||
unsigned int usb_current_max;
|
||||
unsigned int usb_health;
|
||||
|
||||
/* jeita and temperature */
|
||||
bool batt_hot;
|
||||
|
@ -236,6 +238,7 @@ struct smbchg_chip {
|
|||
bool enable_aicl_wake;
|
||||
|
||||
/* psy */
|
||||
struct power_supply_desc usb_psy_d;
|
||||
struct power_supply *usb_psy;
|
||||
struct power_supply_desc batt_psy_d;
|
||||
struct power_supply *batt_psy;
|
||||
|
@ -1109,7 +1112,6 @@ static void update_typec_status(struct smbchg_chip *chip)
|
|||
{
|
||||
union power_supply_propval type = {0, };
|
||||
union power_supply_propval capability = {0, };
|
||||
int rc;
|
||||
|
||||
get_property_from_typec(chip, POWER_SUPPLY_PROP_TYPE, &type);
|
||||
if (type.intval != POWER_SUPPLY_TYPE_UNKNOWN) {
|
||||
|
@ -1117,17 +1119,8 @@ static void update_typec_status(struct smbchg_chip *chip)
|
|||
POWER_SUPPLY_PROP_CURRENT_CAPABILITY,
|
||||
&capability);
|
||||
chip->typec_current_ma = capability.intval;
|
||||
|
||||
if (!chip->skip_usb_notification) {
|
||||
rc = power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
|
||||
&capability);
|
||||
if (rc)
|
||||
pr_err("typec failed to set current max rc=%d\n",
|
||||
rc);
|
||||
pr_smb(PR_TYPEC, "SMB Type-C mode = %d, current=%d\n",
|
||||
type.intval, capability.intval);
|
||||
}
|
||||
pr_smb(PR_TYPEC, "SMB Type-C mode = %d, current=%d\n",
|
||||
type.intval, capability.intval);
|
||||
} else {
|
||||
pr_smb(PR_TYPEC,
|
||||
"typec detection not completed continuing with USB update\n");
|
||||
|
@ -1493,7 +1486,6 @@ static void smbchg_usb_update_online_work(struct work_struct *work)
|
|||
usb_set_online_work);
|
||||
bool user_enabled = !get_client_vote(chip->usb_suspend_votable,
|
||||
USER_EN_VOTER);
|
||||
union power_supply_propval ret;
|
||||
int online;
|
||||
|
||||
online = user_enabled && chip->usb_present && !chip->very_weak_charger;
|
||||
|
@ -1501,10 +1493,8 @@ static void smbchg_usb_update_online_work(struct work_struct *work)
|
|||
mutex_lock(&chip->usb_set_online_lock);
|
||||
if (chip->usb_online != online) {
|
||||
pr_smb(PR_MISC, "setting usb psy online = %d\n", online);
|
||||
ret.intval = online;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_ONLINE, &ret);
|
||||
chip->usb_online = online;
|
||||
power_supply_changed(chip->usb_psy);
|
||||
}
|
||||
mutex_unlock(&chip->usb_set_online_lock);
|
||||
}
|
||||
|
@ -3587,10 +3577,12 @@ static void smbchg_external_power_changed(struct power_supply *psy)
|
|||
vote(chip->usb_suspend_votable, POWER_SUPPLY_EN_VOTER,
|
||||
!prop.intval, 0);
|
||||
|
||||
rc = power_supply_get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
|
||||
if (rc == 0)
|
||||
current_limit = prop.intval / 1000;
|
||||
current_limit = chip->usb_current_max / 1000;
|
||||
|
||||
/* Override if type-c charger used */
|
||||
if (chip->typec_current_ma > 500 &&
|
||||
current_limit < chip->typec_current_ma)
|
||||
current_limit = chip->typec_current_ma;
|
||||
|
||||
read_usb_type(chip, &usb_type_name, &usb_supply_type);
|
||||
|
||||
|
@ -4290,7 +4282,6 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip,
|
|||
enum power_supply_type type)
|
||||
{
|
||||
int rc, current_limit_ma;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
/*
|
||||
* if the type is not unknown, set the type before changing ICL vote
|
||||
|
@ -4309,8 +4300,6 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip,
|
|||
current_limit_ma = chip->typec_current_ma;
|
||||
else if (type == POWER_SUPPLY_TYPE_USB)
|
||||
current_limit_ma = DEFAULT_SDP_MA;
|
||||
else if (type == POWER_SUPPLY_TYPE_USB)
|
||||
current_limit_ma = DEFAULT_SDP_MA;
|
||||
else if (type == POWER_SUPPLY_TYPE_USB_CDP)
|
||||
current_limit_ma = DEFAULT_CDP_MA;
|
||||
else if (type == POWER_SUPPLY_TYPE_USB_HVDCP)
|
||||
|
@ -4329,16 +4318,13 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!chip->skip_usb_notification) {
|
||||
pval.intval = type;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_TYPE, &pval);
|
||||
}
|
||||
|
||||
/* otherwise if it is unknown, set type after the vote */
|
||||
if (type == POWER_SUPPLY_TYPE_UNKNOWN)
|
||||
chip->usb_supply_type = type;
|
||||
|
||||
if (!chip->skip_usb_notification)
|
||||
power_supply_changed(chip->usb_psy);
|
||||
|
||||
/* set the correct buck switching frequency */
|
||||
rc = smbchg_set_optimal_charging_mode(chip, type);
|
||||
if (rc < 0)
|
||||
|
@ -4528,25 +4514,13 @@ static void handle_usb_removal(struct smbchg_chip *chip)
|
|||
if (chip->typec_psy)
|
||||
chip->typec_current_ma = 0;
|
||||
smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
|
||||
if (!chip->skip_usb_notification) {
|
||||
pr_smb(PR_MISC, "setting usb psy present = %d\n",
|
||||
chip->usb_present);
|
||||
pval.intval = chip->usb_present;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &pval);
|
||||
}
|
||||
extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
|
||||
set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DPR_DMR);
|
||||
schedule_work(&chip->usb_set_online_work);
|
||||
|
||||
pr_smb(PR_MISC, "setting usb psy health UNKNOWN\n");
|
||||
pval.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
|
||||
rc = power_supply_set_property(chip->usb_psy, POWER_SUPPLY_PROP_HEALTH,
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
pr_smb(PR_STATUS,
|
||||
"usb psy does not allow updating prop %d rc = %d\n",
|
||||
POWER_SUPPLY_HEALTH_UNKNOWN, rc);
|
||||
chip->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN;
|
||||
power_supply_changed(chip->usb_psy);
|
||||
|
||||
if (parallel_psy && chip->parallel_charger_detected) {
|
||||
pval.intval = false;
|
||||
|
@ -4619,13 +4593,6 @@ static void handle_usb_insertion(struct smbchg_chip *chip)
|
|||
if (chip->typec_psy)
|
||||
update_typec_status(chip);
|
||||
smbchg_change_usb_supply_type(chip, usb_supply_type);
|
||||
if (!chip->skip_usb_notification) {
|
||||
pr_smb(PR_MISC, "setting usb psy present = %d\n",
|
||||
chip->usb_present);
|
||||
pval.intval = chip->usb_present;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &pval);
|
||||
}
|
||||
|
||||
/* Only notify USB if it's not a charger */
|
||||
if (usb_supply_type == POWER_SUPPLY_TYPE_USB ||
|
||||
|
@ -4643,16 +4610,10 @@ static void handle_usb_insertion(struct smbchg_chip *chip)
|
|||
pr_smb(PR_MISC, "setting usb psy health %s\n",
|
||||
chip->very_weak_charger
|
||||
? "UNSPEC_FAILURE" : "GOOD");
|
||||
pval.intval = chip->very_weak_charger
|
||||
chip->usb_health = chip->very_weak_charger
|
||||
? POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
|
||||
: POWER_SUPPLY_HEALTH_GOOD;
|
||||
rc = power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
pr_smb(PR_STATUS,
|
||||
"usb psy does not allow updating prop %d rc = %d\n",
|
||||
POWER_SUPPLY_HEALTH_GOOD, rc);
|
||||
power_supply_changed(chip->usb_psy);
|
||||
}
|
||||
schedule_work(&chip->usb_set_online_work);
|
||||
|
||||
|
@ -4777,7 +4738,6 @@ static void increment_aicl_count(struct smbchg_chip *chip)
|
|||
u8 reg;
|
||||
long elapsed_seconds;
|
||||
unsigned long now_seconds;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
pr_smb(PR_INTERRUPT, "aicl count c:%d dgltch:%d first:%ld\n",
|
||||
chip->aicl_irq_count, chip->aicl_deglitch_short,
|
||||
|
@ -4859,13 +4819,8 @@ static void increment_aicl_count(struct smbchg_chip *chip)
|
|||
if (bad_charger) {
|
||||
pr_smb(PR_MISC,
|
||||
"setting usb psy health UNSPEC_FAILURE\n");
|
||||
pval.intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
rc = power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
&pval);
|
||||
if (rc)
|
||||
pr_err("Couldn't set health on usb psy rc:%d\n",
|
||||
rc);
|
||||
chip->usb_health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
power_supply_changed(chip->usb_psy);
|
||||
schedule_work(&chip->usb_set_online_work);
|
||||
}
|
||||
}
|
||||
|
@ -5514,17 +5469,8 @@ static int smbchg_dp_dm(struct smbchg_chip *chip, int val)
|
|||
static void update_typec_capability_status(struct smbchg_chip *chip,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pr_smb(PR_TYPEC, "typec capability = %dma\n", val->intval);
|
||||
|
||||
if (!chip->skip_usb_notification) {
|
||||
rc = power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, val);
|
||||
if (rc)
|
||||
pr_err("typec failed to set current max rc=%d\n", rc);
|
||||
}
|
||||
|
||||
pr_debug("changing ICL from %dma to %dma\n", chip->typec_current_ma,
|
||||
val->intval);
|
||||
chip->typec_current_ma = val->intval;
|
||||
|
@ -5540,8 +5486,6 @@ static void update_typec_otg_status(struct smbchg_chip *chip, int mode,
|
|||
if (mode == POWER_SUPPLY_TYPE_DFP) {
|
||||
chip->typec_dfp = true;
|
||||
pval.intval = 1;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_USB_OTG, &pval);
|
||||
extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST,
|
||||
chip->typec_dfp);
|
||||
/* update FG */
|
||||
|
@ -5550,8 +5494,6 @@ static void update_typec_otg_status(struct smbchg_chip *chip, int mode,
|
|||
} else if (force || chip->typec_dfp) {
|
||||
chip->typec_dfp = false;
|
||||
pval.intval = 0;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_USB_OTG, &pval);
|
||||
extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST,
|
||||
chip->typec_dfp);
|
||||
/* update FG */
|
||||
|
@ -5560,6 +5502,82 @@ static void update_typec_otg_status(struct smbchg_chip *chip, int mode,
|
|||
}
|
||||
}
|
||||
|
||||
static int smbchg_usb_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct smbchg_chip *chip = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
val->intval = chip->usb_current_max;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = chip->usb_present;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = chip->usb_online;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TYPE:
|
||||
val->intval = chip->usb_supply_type;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
val->intval = chip->usb_health;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smbchg_usb_set_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct smbchg_chip *chip = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
chip->usb_current_max = val->intval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
chip->usb_online = val->intval;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
power_supply_changed(psy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
smbchg_usb_is_writeable(struct power_supply *psy, enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char *smbchg_usb_supplicants[] = {
|
||||
"battery",
|
||||
"bms",
|
||||
};
|
||||
|
||||
static enum power_supply_property smbchg_usb_properties[] = {
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_TYPE,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
};
|
||||
|
||||
#define CHARGE_OUTPUT_VTG_RATIO 840
|
||||
static int smbchg_get_iusb(struct smbchg_chip *chip)
|
||||
{
|
||||
|
@ -6158,7 +6176,6 @@ static irqreturn_t usbin_ov_handler(int irq, void *_chip)
|
|||
int rc;
|
||||
u8 reg;
|
||||
bool usb_present;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1);
|
||||
if (rc < 0) {
|
||||
|
@ -6169,17 +6186,9 @@ static irqreturn_t usbin_ov_handler(int irq, void *_chip)
|
|||
/* OV condition is detected. Notify it to USB psy */
|
||||
if (reg & USBIN_OV_BIT) {
|
||||
chip->usb_ov_det = true;
|
||||
if (chip->usb_psy) {
|
||||
pr_smb(PR_MISC, "setting usb psy health OV\n");
|
||||
pval.intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||
rc = power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
&pval);
|
||||
if (rc)
|
||||
pr_smb(PR_STATUS,
|
||||
"usb psy does not allow updating prop %d rc = %d\n",
|
||||
POWER_SUPPLY_HEALTH_OVERVOLTAGE, rc);
|
||||
}
|
||||
pr_smb(PR_MISC, "setting usb psy health OV\n");
|
||||
chip->usb_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||
power_supply_changed(chip->usb_psy);
|
||||
} else {
|
||||
chip->usb_ov_det = false;
|
||||
/* If USB is present, then handle the USB insertion */
|
||||
|
@ -6270,11 +6279,8 @@ static irqreturn_t usbin_uv_handler(int irq, void *_chip)
|
|||
rc);
|
||||
}
|
||||
pr_smb(PR_MISC, "setting usb psy health UNSPEC_FAILURE\n");
|
||||
pval.intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
rc = power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_HEALTH, &pval);
|
||||
if (rc)
|
||||
pr_err("Couldn't set health on usb psy rc:%d\n", rc);
|
||||
chip->usb_health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
power_supply_changed(chip->usb_psy);
|
||||
schedule_work(&chip->usb_set_online_work);
|
||||
}
|
||||
|
||||
|
@ -6428,18 +6434,12 @@ static irqreturn_t usbid_change_handler(int irq, void *_chip)
|
|||
{
|
||||
struct smbchg_chip *chip = _chip;
|
||||
bool otg_present;
|
||||
union power_supply_propval pval = {0, };
|
||||
|
||||
pr_smb(PR_INTERRUPT, "triggered\n");
|
||||
|
||||
otg_present = is_otg_present(chip);
|
||||
if (chip->usb_psy) {
|
||||
pr_smb(PR_MISC, "setting usb psy OTG = %d\n",
|
||||
otg_present ? 1 : 0);
|
||||
pval.intval = otg_present ? 1 : 0;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_USB_OTG, &pval);
|
||||
}
|
||||
pr_smb(PR_MISC, "setting usb psy OTG = %d\n",
|
||||
otg_present ? 1 : 0);
|
||||
|
||||
extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST, otg_present);
|
||||
|
||||
|
@ -7858,19 +7858,13 @@ static int smbchg_probe(struct platform_device *pdev)
|
|||
{
|
||||
int rc;
|
||||
struct smbchg_chip *chip;
|
||||
struct power_supply *usb_psy, *typec_psy = NULL;
|
||||
struct power_supply *typec_psy = NULL;
|
||||
struct qpnp_vadc_chip *vadc_dev, *vchg_vadc_dev;
|
||||
const char *typec_psy_name;
|
||||
union power_supply_propval pval = {0, };
|
||||
struct power_supply_config usb_psy_cfg = {};
|
||||
struct power_supply_config batt_psy_cfg = {};
|
||||
struct power_supply_config dc_psy_cfg = {};
|
||||
|
||||
usb_psy = power_supply_get_by_name("usb");
|
||||
if (!usb_psy) {
|
||||
pr_smb(PR_STATUS, "USB supply not found, deferring probe\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(pdev->dev.of_node, "qcom,external-typec")) {
|
||||
/* read the type power supply name */
|
||||
rc = of_property_read_string(pdev->dev.of_node,
|
||||
|
@ -8002,7 +7996,6 @@ static int smbchg_probe(struct platform_device *pdev)
|
|||
chip->pdev = pdev;
|
||||
chip->dev = &pdev->dev;
|
||||
|
||||
chip->usb_psy = usb_psy;
|
||||
chip->typec_psy = typec_psy;
|
||||
chip->fake_battery_soc = -EINVAL;
|
||||
chip->usb_online = -EINVAL;
|
||||
|
@ -8055,6 +8048,26 @@ static int smbchg_probe(struct platform_device *pdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
chip->usb_psy_d.name = "usb";
|
||||
chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB;
|
||||
chip->usb_psy_d.get_property = smbchg_usb_get_property;
|
||||
chip->usb_psy_d.set_property = smbchg_usb_set_property;
|
||||
chip->usb_psy_d.properties = smbchg_usb_properties;
|
||||
chip->usb_psy_d.num_properties = ARRAY_SIZE(smbchg_usb_properties);
|
||||
chip->usb_psy_d.property_is_writeable = smbchg_usb_is_writeable;
|
||||
|
||||
usb_psy_cfg.drv_data = chip;
|
||||
usb_psy_cfg.supplied_to = smbchg_usb_supplicants;
|
||||
usb_psy_cfg.num_supplicants = ARRAY_SIZE(smbchg_usb_supplicants);
|
||||
|
||||
chip->usb_psy = devm_power_supply_register(chip->dev,
|
||||
&chip->usb_psy_d, &usb_psy_cfg);
|
||||
if (IS_ERR(chip->usb_psy)) {
|
||||
dev_err(&pdev->dev, "Unable to register usb_psy rc = %ld\n",
|
||||
PTR_ERR(chip->usb_psy));
|
||||
return PTR_ERR(chip->usb_psy);
|
||||
}
|
||||
|
||||
rc = smbchg_hw_init(chip);
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
|
@ -8142,14 +8155,6 @@ static int smbchg_probe(struct platform_device *pdev)
|
|||
goto unregister_led_class;
|
||||
}
|
||||
|
||||
if (!chip->skip_usb_notification) {
|
||||
pr_smb(PR_MISC, "setting usb psy present = %d\n",
|
||||
chip->usb_present);
|
||||
pval.intval = chip->usb_present;
|
||||
power_supply_set_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &pval);
|
||||
}
|
||||
|
||||
rerun_hvdcp_det_if_necessary(chip);
|
||||
|
||||
dump_regs(chip);
|
||||
|
|
Loading…
Add table
Reference in a new issue