mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-06 03:45:24 -04:00
usb: pd: Add PDO Selection
The PDO selection should be done by either the Kernel or User Space. Setup a callback that selects the PDO based on what the Voltage Max is set to when the function is called. refer to https://gerrit.mot.com/1403781 Based on Gerrit https://gerrit.mot.com/#/c/1301690/ Change-Id: I54a14b47e79637c681cc24c78a75a1206ecd903e Signed-off-by: mahj8 <mahj8@lenovo.com> Reviewed-on: https://gerrit.mot.com/1770248 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao <liaohs@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
a0ecbc9a1b
commit
667b71ea21
2 changed files with 108 additions and 0 deletions
|
|
@ -891,6 +891,32 @@ static int pd_select_pdo(struct usbpd *pd, int pdo_pos, int uv, int ua)
|
|||
|
||||
pd->requested_current = curr;
|
||||
pd->requested_pdo = pdo_pos;
|
||||
usbpd_warn(&pd->dev, "select_pdo: PDO:%d, %d uV, %d uA\n",
|
||||
pdo_pos, uv, ua);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pd_get_pdo(struct usbpd *pd, int pdo_pos, int *uv_max, int *uv_min, int *ua)
|
||||
{
|
||||
u8 type;
|
||||
u32 pdo = pd->received_pdos[pdo_pos - 1];
|
||||
|
||||
if (0 == pdo)
|
||||
return -ENOTSUPP;
|
||||
|
||||
type = PD_SRC_PDO_TYPE(pdo);
|
||||
if (type == PD_SRC_PDO_TYPE_FIXED) {
|
||||
*ua = PD_SRC_PDO_FIXED_MAX_CURR(pdo) * 10;
|
||||
*uv_max = *uv_min = PD_SRC_PDO_FIXED_VOLTAGE(pdo) * 50 * 1000;
|
||||
} else if (type == PD_SRC_PDO_TYPE_AUGMENTED) {
|
||||
*uv_max = PD_APDO_MAX_VOLT(pdo) * 100000;
|
||||
*uv_min = PD_APDO_MIN_VOLT(pdo) * 100000;
|
||||
*ua = PD_APDO_MAX_CURR(pdo) * 50000;
|
||||
} else {
|
||||
usbpd_err(&pd->dev, "Only Fixed or Programmable PDOs supported\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4228,6 +4254,83 @@ static ssize_t pdo_n_show(struct device *dev, struct device_attribute *attr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int usbpd_select_pdo_match(struct usbpd *pd)
|
||||
{
|
||||
int uv_diff = 0, max_uv_diff = 0, pdo = 0;
|
||||
int pdo_max_uv = 0, pdo_min_uv = 0, pdo_ua = 0;
|
||||
int uv_in, i;
|
||||
int ret;
|
||||
union power_supply_propval val;
|
||||
|
||||
if (!pd)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pd->swap_lock);
|
||||
|
||||
/* Only allowed if we are already in explicit sink contract */
|
||||
if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) {
|
||||
usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n");
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check the Max Input Voltage from USBPSY */
|
||||
power_supply_get_property(pd->usb_psy,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
|
||||
uv_in = val.intval;
|
||||
/* start with 5 V */
|
||||
max_uv_diff = 5000000;
|
||||
for (i = 1; i < 8; i++) {
|
||||
if (!pd_get_pdo(pd, i, &pdo_max_uv, &pdo_min_uv, &pdo_ua)) {
|
||||
if (pdo_max_uv <= uv_in) {
|
||||
uv_diff = uv_in - pdo_max_uv;
|
||||
if (uv_diff < max_uv_diff) {
|
||||
max_uv_diff = uv_diff;
|
||||
pdo = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pdo < 1 || pdo > 7) {
|
||||
usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pd_get_pdo(pd, pdo, &pdo_max_uv, &pdo_min_uv, &pdo_ua);
|
||||
ret = pd_select_pdo(pd, pdo, pdo_max_uv, pdo_ua);
|
||||
if (ret)
|
||||
goto out;
|
||||
else
|
||||
ret = pdo_max_uv;
|
||||
|
||||
reinit_completion(&pd->is_ready);
|
||||
pd->send_request = true;
|
||||
kick_sm(pd, 0);
|
||||
|
||||
/* wait for operation to complete */
|
||||
if (!wait_for_completion_timeout(&pd->is_ready,
|
||||
msecs_to_jiffies(1000))) {
|
||||
usbpd_err(&pd->dev, "select_pdo: request timed out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* determine if request was accepted/rejected */
|
||||
if (pd->selected_pdo != pd->requested_pdo ||
|
||||
pd->current_voltage != pd->requested_voltage) {
|
||||
usbpd_err(&pd->dev, "select_pdo: request rejected\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
pd->send_request = false;
|
||||
mutex_unlock(&pd->swap_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(usbpd_select_pdo_match);
|
||||
|
||||
static ssize_t select_pdo_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -99,6 +99,11 @@ int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
|
|||
enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
|
||||
const u32 *vdos, int num_vdos);
|
||||
|
||||
/*
|
||||
* Look for best match for PDO selection in Source Mode.
|
||||
*/
|
||||
int usbpd_select_pdo_match(struct usbpd *pd);
|
||||
|
||||
/*
|
||||
* Get current status of CC pin orientation.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue