summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2017-05-30 15:54:55 -0700
committerHemant Kumar <hemantk@codeaurora.org>2017-06-01 13:51:13 -0700
commit6577867741e343ba3df76112245c28385685f8cf (patch)
treea5d9461f155bdd692d8ae761aeb8597887d921b8
parent840d1a232cfd67867a61a31ccc5d81c5c2192474 (diff)
usb: pd: policy_engine: Handle spec revision properly
As per USB PD 3.0 specification the 2-bit Specification Revision field of a GoodCRC Message does not carry any meaning and Shall be considered as don't care by the recipient of the Message. Hence set spec revision to USBPD_REV_20 for GoodCRC message. PD protocol message header defaults to USBPD_REV_20 which gets updated USBPD_REV_30 if PD 3.0 source capabale of programmable power supply. Change-Id: I5209bb00c437f3c959d093a972f1ac75233cbcf9 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
-rw-r--r--drivers/usb/pd/policy_engine.c34
-rw-r--r--drivers/usb/pd/qpnp-pdphy.c13
-rw-r--r--drivers/usb/pd/usbpd.h7
3 files changed, 16 insertions, 38 deletions
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 7bfadccf0e47..d46e21bd2c68 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -187,6 +187,8 @@ static void *usbpd_ipc_log;
#define PD_MAX_MSG_ID 7
+#define PD_MAX_DATA_OBJ 7
+
#define PD_MSG_HDR(type, dr, pr, id, cnt, rev) \
(((type) & 0xF) | ((dr) << 5) | (rev << 6) | \
((pr) << 8) | ((id) << 9) | ((cnt) << 12))
@@ -308,7 +310,7 @@ struct usbpd {
struct list_head rx_q;
spinlock_t rx_lock;
- u32 received_pdos[7];
+ u32 received_pdos[PD_MAX_DATA_OBJ];
u16 src_cap_id;
u8 selected_pdo;
u8 requested_pdo;
@@ -547,6 +549,7 @@ static int pd_select_pdo(struct usbpd *pd, int pdo_pos, int uv, int ua)
static int pd_eval_src_caps(struct usbpd *pd)
{
+ int obj_cnt;
union power_supply_propval val;
u32 first_pdo = pd->received_pdos[0];
@@ -563,6 +566,13 @@ static int pd_eval_src_caps(struct usbpd *pd)
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED, &val);
+ for (obj_cnt = 1; obj_cnt < PD_MAX_DATA_OBJ; obj_cnt++) {
+ if ((PD_SRC_PDO_TYPE(pd->received_pdos[obj_cnt]) ==
+ PD_SRC_PDO_TYPE_AUGMENTED) &&
+ !PD_APDO_PPS(pd->received_pdos[obj_cnt]))
+ pd->spec_rev = USBPD_REV_30;
+ }
+
/* Select the first PDO (vSafe5V) immediately. */
pd_select_pdo(pd, 1, 0, 0);
@@ -653,12 +663,6 @@ static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type,
return;
}
- /* if spec rev differs (i.e. is older), update PHY */
- if (PD_MSG_HDR_REV(header) < pd->spec_rev) {
- pd->spec_rev = PD_MSG_HDR_REV(header);
- pd_phy_update_spec_rev(pd->spec_rev);
- }
-
rx_msg = kzalloc(sizeof(*rx_msg), GFP_KERNEL);
if (!rx_msg)
return;
@@ -701,7 +705,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
.shutdown_cb = phy_shutdown,
.frame_filter_val = FRAME_FILTER_EN_SOP |
FRAME_FILTER_EN_HARD_RESET,
- .spec_rev = USBPD_REV_20,
};
union power_supply_propval val = {0};
unsigned long flags;
@@ -748,8 +751,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val);
- /* support only PD 2.0 as a source */
- pd->spec_rev = USBPD_REV_20;
pd_reset_protocol(pd);
if (!pd->in_pr_swap) {
@@ -760,7 +761,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
phy_params.data_role = pd->current_dr;
phy_params.power_role = pd->current_pr;
- phy_params.spec_rev = pd->spec_rev;
ret = pd_phy_open(&phy_params);
if (ret) {
@@ -772,8 +772,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
}
pd->pd_phy_opened = true;
- } else {
- pd_phy_update_spec_rev(pd->spec_rev);
}
pd->current_state = PE_SRC_SEND_CAPABILITIES;
@@ -909,11 +907,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
if (!val.intval)
break;
- /*
- * support up to PD 3.0 as a sink; if source is 2.0,
- * phy_msg_received() will handle the downgrade.
- */
- pd->spec_rev = USBPD_REV_30;
pd_reset_protocol(pd);
if (!pd->in_pr_swap) {
@@ -924,7 +917,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
phy_params.data_role = pd->current_dr;
phy_params.power_role = pd->current_pr;
- phy_params.spec_rev = pd->spec_rev;
ret = pd_phy_open(&phy_params);
if (ret) {
@@ -936,8 +928,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
}
pd->pd_phy_opened = true;
- } else {
- pd_phy_update_spec_rev(pd->spec_rev);
}
pd->current_voltage = pd->requested_voltage = 5000000;
@@ -3314,6 +3304,8 @@ struct usbpd *usbpd_create(struct device *parent)
pd->dual_role->drv_data = pd;
}
+ /* default support as PD 2.0 source or sink */
+ pd->spec_rev = USBPD_REV_20;
pd->current_pr = PR_NONE;
pd->current_dr = DR_NONE;
list_add_tail(&pd->instance, &_usbpd);
diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c
index 588af94db6cd..fa3b71d6ce08 100644
--- a/drivers/usb/pd/qpnp-pdphy.c
+++ b/drivers/usb/pd/qpnp-pdphy.c
@@ -334,15 +334,6 @@ int pd_phy_update_roles(enum data_role dr, enum power_role pr)
}
EXPORT_SYMBOL(pd_phy_update_roles);
-int pd_phy_update_spec_rev(enum pd_spec_rev rev)
-{
- struct usb_pdphy *pdphy = __pdphy;
-
- return pdphy_masked_write(pdphy, USB_PDPHY_MSG_CONFIG,
- MSG_CONFIG_SPEC_REV_MASK, rev);
-}
-EXPORT_SYMBOL(pd_phy_update_spec_rev);
-
int pd_phy_open(struct pd_phy_params *params)
{
int ret;
@@ -377,7 +368,9 @@ int pd_phy_open(struct pd_phy_params *params)
if (ret)
return ret;
- ret = pd_phy_update_spec_rev(params->spec_rev);
+ /* PD 2.0 phy */
+ ret = pdphy_masked_write(pdphy, USB_PDPHY_MSG_CONFIG,
+ MSG_CONFIG_SPEC_REV_MASK, USBPD_REV_20);
if (ret)
return ret;
diff --git a/drivers/usb/pd/usbpd.h b/drivers/usb/pd/usbpd.h
index b2663add7f3c..108701739f89 100644
--- a/drivers/usb/pd/usbpd.h
+++ b/drivers/usb/pd/usbpd.h
@@ -68,7 +68,6 @@ struct pd_phy_params {
enum data_role data_role;
enum power_role power_role;
u8 frame_filter_val;
- u8 spec_rev;
};
#if IS_ENABLED(CONFIG_QPNP_USB_PDPHY)
@@ -77,7 +76,6 @@ int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms);
int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
enum pd_msg_type type, unsigned int timeout_ms);
int pd_phy_update_roles(enum data_role dr, enum power_role pr);
-int pd_phy_update_spec_rev(enum pd_spec_rev rev);
void pd_phy_close(void);
#else
static inline int pd_phy_open(struct pd_phy_params *params)
@@ -101,11 +99,6 @@ static inline int pd_phy_update_roles(enum data_role dr, enum power_role pr)
return -ENODEV;
}
-static inline int pd_phy_update_spec_rev(enum pd_spec_rev rev)
-{
- return -ENODEV;
-}
-
static inline void pd_phy_close(void)
{
}