Commit ef82f1ad authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-4.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging driver fixes from Greg KH:
 "Here are a number of staging driver fixes for 4.12-rc2

  Most of them are typec driver fixes found by reviewers and users of
  the code. There are also some removals of files no longer needed in
  the tree due to the ion driver rewrite in 4.12-rc1, as well as some
  wifi driver fixes. And to round it out, a MAINTAINERS file update.

  All have been in linux-next with no reported issues"

* tag 'staging-4.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (22 commits)
  MAINTAINERS: greybus-dev list is members-only
  staging: fsl-dpaa2/eth: add ETHERNET dependency
  staging: typec: fusb302: refactor resume retry mechanism
  staging: typec: fusb302: reset i2c_busy state in error
  staging: rtl8723bs: remove re-positioned call to kfree in os_dep/ioctl_cfg80211.c
  staging: rtl8192e: GetTs Fix invalid TID 7 warning.
  staging: rtl8192e: rtl92e_get_eeprom_size Fix read size of EPROM_CMD.
  staging: rtl8192e: fix 2 byte alignment of register BSSIDR.
  staging: rtl8192e: rtl92e_fill_tx_desc fix write to mapped out memory.
  staging: vc04_services: Fix bulk cache maintenance
  staging: ccree: remove extraneous spin_unlock_bh() in error handler
  staging: typec: Fix sparse warnings about incorrect types
  staging: typec: fusb302: do not free gpio from managed resource
  staging: typec: tcpm: Fix Port Power Role field in PS_RDY messages
  staging: typec: tcpm: Respond to Discover Identity commands
  staging: typec: tcpm: Set correct flags in PD request messages
  staging: typec: tcpm: Drop duplicate PD messages
  staging: typec: fusb302: Fix chip->vbus_present init value
  staging: typec: fusb302: Fix module autoload
  staging: typec: tcpci: declare private structure as static
  ...
parents 32026293 66ea5974
Hi6220 SoC ION
===================================================================
Required properties:
- compatible : "hisilicon,hi6220-ion"
- list of the ION heaps
- heap name : maybe heap_sys_user@0
- heap id : id should be unique in the system.
- heap base : base ddr address of the heap,0 means that
it is dynamic.
- heap size : memory size and 0 means it is dynamic.
- heap type : the heap type of the heap, please also
see the define in ion.h(drivers/staging/android/uapi/ion.h)
-------------------------------------------------------------------
Example:
hi6220-ion {
compatible = "hisilicon,hi6220-ion";
heap_sys_user@0 {
heap-name = "sys_user";
heap-id = <0x0>;
heap-base = <0x0>;
heap-size = <0x0>;
heap-type = "ion_system";
};
heap_sys_contig@0 {
heap-name = "sys_contig";
heap-id = <0x1>;
heap-base = <0x0>;
heap-size = <0x0>;
heap-type = "ion_system_contig";
};
};
......@@ -846,7 +846,6 @@ M: Laura Abbott <labbott@redhat.com>
M: Sumit Semwal <sumit.semwal@linaro.org>
L: devel@driverdev.osuosl.org
S: Supported
F: Documentation/devicetree/bindings/staging/ion/
F: drivers/staging/android/ion
F: drivers/staging/android/uapi/ion.h
F: drivers/staging/android/uapi/ion_test.h
......@@ -3116,6 +3115,14 @@ F: drivers/net/ieee802154/cc2520.c
F: include/linux/spi/cc2520.h
F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
CCREE ARM TRUSTZONE CRYPTOCELL 700 REE DRIVER
M: Gilad Ben-Yossef <gilad@benyossef.com>
L: linux-crypto@vger.kernel.org
L: driverdev-devel@linuxdriverproject.org
S: Supported
F: drivers/staging/ccree/
W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
CEC FRAMEWORK
M: Hans Verkuil <hans.verkuil@cisco.com>
L: linux-media@vger.kernel.org
......@@ -5695,7 +5702,7 @@ M: Alex Elder <elder@kernel.org>
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Maintained
F: drivers/staging/greybus/
L: greybus-dev@lists.linaro.org
L: greybus-dev@lists.linaro.org (moderated for non-subscribers)
GREYBUS AUDIO PROTOCOLS DRIVERS
M: Vaibhav Agarwal <vaibhav.sr@gmail.com>
......
Ion Memory Manager
Ion is a memory manager that allows for sharing of buffers via dma-buf.
Ion allows for different types of allocation via an abstraction called
a 'heap'. A heap represents a specific type of memory. Each heap has
a different type. There can be multiple instances of the same heap
type.
Specific heap instances are tied to heap IDs. Heap IDs are not to be specified
in the devicetree.
Required properties for Ion
- compatible: "linux,ion" PLUS a compatible property for the device
All child nodes of a linux,ion node are interpreted as heaps
required properties for heaps
- compatible: compatible string for a heap type PLUS a compatible property
for the specific instance of the heap. Current heap types
-- linux,ion-heap-system
-- linux,ion-heap-system-contig
-- linux,ion-heap-carveout
-- linux,ion-heap-chunk
-- linux,ion-heap-dma
-- linux,ion-heap-custom
Optional properties
- memory-region: A phandle to a memory region. Required for DMA heap type
(see reserved-memory.txt for details on the reservation)
Example:
ion {
compatbile = "hisilicon,ion", "linux,ion";
ion-system-heap {
compatbile = "hisilicon,system-heap", "linux,ion-heap-system"
};
ion-camera-region {
compatible = "hisilicon,camera-heap", "linux,ion-heap-dma"
memory-region = <&camera_region>;
};
ion-fb-region {
compatbile = "hisilicon,fb-heap", "linux,ion-heap-dma"
memory-region = <&fb_region>;
};
}
......@@ -376,7 +376,6 @@ int send_request(
rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev);
if (rc != 0) {
SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc);
spin_unlock_bh(&req_mgr_h->hw_lock);
return rc;
}
#endif
......
......@@ -12,6 +12,7 @@ config FSL_DPAA2
config FSL_DPAA2_ETH
tristate "Freescale DPAA2 Ethernet"
depends on FSL_DPAA2 && FSL_MC_DPIO
depends on NETDEVICES && ETHERNET
---help---
Ethernet driver for Freescale DPAA2 SoCs, using the
Freescale MC bus driver
......@@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
switch (variable) {
case HW_VAR_BSSID:
rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]);
rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
/* BSSIDR 2 byte alignment */
rtl92e_writew(dev, BSSIDR, *(u16 *)val);
rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2));
break;
case HW_VAR_MEDIA_STATUS:
......@@ -624,7 +625,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev)
struct r8192_priv *priv = rtllib_priv(dev);
RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
curCR = rtl92e_readl(dev, EPROM_CMD);
curCR = rtl92e_readw(dev, EPROM_CMD);
RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
curCR);
priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
......@@ -961,8 +962,8 @@ static void _rtl92e_net_update(struct net_device *dev)
rtl92e_config_rate(dev, &rate_config);
priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
priv->basic_rate = rate_config &= 0x15f;
rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]);
rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid);
rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2));
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
rtl92e_writew(dev, ATIMWND, 2);
......@@ -1182,8 +1183,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
struct cb_desc *cb_desc, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
dma_addr_t mapping;
struct tx_fwinfo_8190pci *pTxFwInfo;
pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
......@@ -1194,8 +1194,6 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT,
pTxFwInfo->TxRate, cb_desc);
if (pci_dma_mapping_error(priv->pdev, mapping))
netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
if (cb_desc->bAMPDUEnable) {
pTxFwInfo->AllowAggregation = 1;
pTxFwInfo->RxMF = cb_desc->ampdu_factor;
......@@ -1230,6 +1228,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
}
memset((u8 *)pdesc, 0, 12);
mapping = pci_map_single(priv->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(priv->pdev, mapping)) {
netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
return;
}
pdesc->LINIP = 0;
pdesc->CmdInit = 1;
pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
......
......@@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
pTsCommonInfo->TClasNum = TCLAS_Num;
}
static bool IsACValid(unsigned int tid)
{
return tid < 7;
}
bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
{
......@@ -328,12 +323,6 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
if (ieee->current_network.qos_data.supported == 0) {
UP = 0;
} else {
if (!IsACValid(TID)) {
netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
__func__, TID);
return false;
}
switch (TID) {
case 0:
case 3:
......@@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
case 7:
UP = 7;
break;
default:
netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
__func__, TID);
return false;
}
}
......
......@@ -3531,7 +3531,6 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev)
pwdev_priv->power_mgmt = true;
else
pwdev_priv->power_mgmt = false;
kfree((u8 *)wdev);
return ret;
......
......@@ -264,22 +264,36 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { }
#define FUSB302_RESUME_RETRY 10
#define FUSB302_RESUME_RETRY_SLEEP 50
static int fusb302_i2c_write(struct fusb302_chip *chip,
u8 address, u8 data)
static bool fusb302_is_suspended(struct fusb302_chip *chip)
{
int retry_cnt;
int ret = 0;
atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
retry_cnt + 1, FUSB302_RESUME_RETRY);
dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n",
retry_cnt + 1, FUSB302_RESUME_RETRY);
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
return false;
}
}
return true;
}
static int fusb302_i2c_write(struct fusb302_chip *chip,
u8 address, u8 data)
{
int ret = 0;
atomic_set(&chip->i2c_busy, 1);
if (fusb302_is_suspended(chip)) {
atomic_set(&chip->i2c_busy, 0);
return -ETIMEDOUT;
}
ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data);
if (ret < 0)
fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d",
......@@ -292,21 +306,17 @@ static int fusb302_i2c_write(struct fusb302_chip *chip,
static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
u8 length, const u8 *data)
{
int retry_cnt;
int ret = 0;
if (length <= 0)
return ret;
atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
retry_cnt + 1, FUSB302_RESUME_RETRY);
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
}
if (fusb302_is_suspended(chip)) {
atomic_set(&chip->i2c_busy, 0);
return -ETIMEDOUT;
}
ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address,
length, data);
if (ret < 0)
......@@ -320,19 +330,15 @@ static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
static int fusb302_i2c_read(struct fusb302_chip *chip,
u8 address, u8 *data)
{
int retry_cnt;
int ret = 0;
atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
retry_cnt + 1, FUSB302_RESUME_RETRY);
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
}
if (fusb302_is_suspended(chip)) {
atomic_set(&chip->i2c_busy, 0);
return -ETIMEDOUT;
}
ret = i2c_smbus_read_byte_data(chip->i2c_client, address);
*data = (u8)ret;
if (ret < 0)
......@@ -345,33 +351,31 @@ static int fusb302_i2c_read(struct fusb302_chip *chip,
static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address,
u8 length, u8 *data)
{
int retry_cnt;
int ret = 0;
if (length <= 0)
return ret;
atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
retry_cnt + 1, FUSB302_RESUME_RETRY);
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
}
if (fusb302_is_suspended(chip)) {
atomic_set(&chip->i2c_busy, 0);
return -ETIMEDOUT;
}
ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address,
length, data);
if (ret < 0) {
fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d",
address, length, ret);
return ret;
goto done;
}
if (ret != length) {
fusb302_log(chip, "only read %d/%d bytes from 0x%02x",
ret, length, address);
return -EIO;
ret = -EIO;
}
done:
atomic_set(&chip->i2c_busy, 0);
return ret;
......@@ -489,7 +493,7 @@ static int tcpm_init(struct tcpc_dev *dev)
ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data);
if (ret < 0)
return ret;
chip->vbus_present = !!(FUSB_REG_STATUS0 & FUSB_REG_STATUS0_VBUSOK);
chip->vbus_present = !!(data & FUSB_REG_STATUS0_VBUSOK);
ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data);
if (ret < 0)
return ret;
......@@ -1025,7 +1029,7 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip,
buf[pos++] = FUSB302_TKN_SYNC1;
buf[pos++] = FUSB302_TKN_SYNC2;
len = pd_header_cnt(msg->header) * 4;
len = pd_header_cnt_le(msg->header) * 4;
/* plug 2 for header */
len += 2;
if (len > 0x1F) {
......@@ -1481,7 +1485,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
(u8 *)&msg->header);
if (ret < 0)
return ret;
len = pd_header_cnt(msg->header) * 4;
len = pd_header_cnt_le(msg->header) * 4;
/* add 4 to length to include the CRC */
if (len > PD_MAX_PAYLOAD * 4) {
fusb302_log(chip, "PD message too long %d", len);
......@@ -1663,14 +1667,12 @@ static int init_gpio(struct fusb302_chip *chip)
if (ret < 0) {
fusb302_log(chip,
"cannot set GPIO Int_N to input, ret=%d", ret);
gpio_free(chip->gpio_int_n);
return ret;
}
ret = gpio_to_irq(chip->gpio_int_n);
if (ret < 0) {
fusb302_log(chip,
"cannot request IRQ for GPIO Int_N, ret=%d", ret);
gpio_free(chip->gpio_int_n);
return ret;
}
chip->gpio_int_n_irq = ret;
......@@ -1787,11 +1789,13 @@ static const struct of_device_id fusb302_dt_match[] = {
{.compatible = "fcs,fusb302"},
{},
};
MODULE_DEVICE_TABLE(of, fusb302_dt_match);
static const struct i2c_device_id fusb302_i2c_device_id[] = {
{"typec_fusb302", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, fusb302_i2c_device_id);
static const struct dev_pm_ops fusb302_pm_ops = {
.suspend = fusb302_pm_suspend,
......
......@@ -92,6 +92,16 @@ static inline unsigned int pd_header_type_le(__le16 header)
return pd_header_type(le16_to_cpu(header));
}
static inline unsigned int pd_header_msgid(u16 header)
{
return (header >> PD_HEADER_ID_SHIFT) & PD_HEADER_ID_MASK;
}
static inline unsigned int pd_header_msgid_le(__le16 header)
{
return pd_header_msgid(le16_to_cpu(header));
}
#define PD_MAX_PAYLOAD 7
struct pd_message {
......
......@@ -22,6 +22,9 @@
* VDM object is minimum of VDM header + 6 additional data objects.
*/
#define VDO_MAX_OBJECTS 6
#define VDO_MAX_SIZE (VDO_MAX_OBJECTS + 1)
/*
* VDM header
* ----------
......@@ -34,7 +37,6 @@
* <5> :: reserved (SVDM), command type (UVDM)
* <4:0> :: command
*/
#define VDO_MAX_SIZE 7
#define VDO(vid, type, custom) \
(((vid) << 16) | \
((type) << 15) | \
......
......@@ -425,7 +425,7 @@ static const struct regmap_config tcpci_regmap_config = {
.max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */
};
const struct tcpc_config tcpci_tcpc_config = {
static const struct tcpc_config tcpci_tcpc_config = {
.type = TYPEC_PORT_DFP,
.default_role = TYPEC_SINK,
};
......
......@@ -238,6 +238,7 @@ struct tcpm_port {
unsigned int hard_reset_count;
bool pd_capable;
bool explicit_contract;
unsigned int rx_msgid;
/* Partner capabilities/requests */
u32 sink_request;
......@@ -251,6 +252,8 @@ struct tcpm_port {
unsigned int nr_src_pdo;
u32 snk_pdo[PDO_MAX_OBJECTS];
unsigned int nr_snk_pdo;
u32 snk_vdo[VDO_MAX_OBJECTS];
unsigned int nr_snk_vdo;
unsigned int max_snk_mv;
unsigned int max_snk_ma;
......@@ -997,6 +1000,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
struct pd_mode_data *modep;
int rlen = 0;
u16 svid;
int i;
tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d",
p0, cmd_type, cmd, cnt);
......@@ -1007,6 +1011,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
case CMDT_INIT:
switch (cmd) {
case CMD_DISCOVER_IDENT:
/* 6.4.4.3.1: Only respond as UFP (device) */
if (port->data_role == TYPEC_DEVICE &&
port->nr_snk_vdo) {
for (i = 0; i < port->nr_snk_vdo; i++)
response[i + 1]
= cpu_to_le32(port->snk_vdo[i]);
rlen = port->nr_snk_vdo + 1;
}
break;
case CMD_DISCOVER_SVID:
break;
......@@ -1415,6 +1427,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
case SOFT_RESET_SEND:
port->message_id = 0;
port->rx_msgid = -1;
if (port->pwr_role == TYPEC_SOURCE)
next_state = SRC_SEND_CAPABILITIES;
else
......@@ -1503,6 +1516,22 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
port->attached);
if (port->attached) {
enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
unsigned int msgid = pd_header_msgid_le(msg->header);
/*
* USB PD standard, 6.6.1.2:
* "... if MessageID value in a received Message is the
* same as the stored value, the receiver shall return a
* GoodCRC Message with that MessageID value and drop
* the Message (this is a retry of an already received
* Message). Note: this shall not apply to the Soft_Reset
* Message which always has a MessageID value of zero."
*/
if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET)
goto done;
port->rx_msgid = msgid;
/*
* If both ends believe to be DFP/host, we have a data role
* mismatch.
......@@ -1520,6 +1549,7 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
}
}
done:
mutex_unlock(&port->lock);
kfree(event);
}
......@@ -1719,8 +1749,7 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
}
ma = min(ma, port->max_snk_ma);
/* XXX: Any other flags need to be set? */
flags = 0;
flags = RDO_USB_COMM | RDO_NO_SUSPEND;
/* Set mismatch bit if offered power is less than operating power */
mw = ma * mv / 1000;
......@@ -1957,6 +1986,12 @@ static void tcpm_reset_port(struct tcpm_port *port)
port->attached = false;
port->pd_capable = false;
/*
* First Rx ID should be 0; set this to a sentinel of -1 so that
* we can check tcpm_pd_rx_handler() if we had seen it before.
*/
port->rx_msgid = -1;
port->tcpc->set_pd_rx(port->tcpc, false);
tcpm_init_vbus(port); /* also disables charging */
tcpm_init_vconn(port);
......@@ -2170,6 +2205,7 @@ static void run_state_machine(struct tcpm_port *port)
port->pwr_opmode = TYPEC_PWR_MODE_USB;
port->caps_count = 0;
port->message_id = 0;
port->rx_msgid = -1;
port->explicit_contract = false;
tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
break;
......@@ -2329,6 +2365,7 @@ static void run_state_machine(struct tcpm_port *port)
typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB);
port->pwr_opmode = TYPEC_PWR_MODE_USB;
port->message_id = 0;
port->rx_msgid = -1;
port->explicit_contract = false;
tcpm_set_state(port, SNK_DISCOVERY, 0);
break;
......@@ -2496,6 +2533,7 @@ static void run_state_machine(struct tcpm_port *port)
/* Soft_Reset states */
case SOFT_RESET:
port->message_id = 0;
port->rx_msgid = -1;
tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
if (port->pwr_role == TYPEC_SOURCE)
tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
......@@ -2504,6 +2542,7 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SOFT_RESET_SEND:
port->message_id = 0;
port->rx_msgid = -1;
if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
tcpm_set_state_cond(port, hard_reset_state(port), 0);
else
......@@ -2568,6 +2607,14 @@ static void run_state_machine(struct tcpm_port *port)
break;
case PR_SWAP_SRC_SNK_SOURCE_OFF:
tcpm_set_cc(port, TYPEC_CC_RD);
/*
* USB-PD standard, 6.2.1.4, Port Power Role:
* "During the Power Role Swap Sequence, for the initial Source
* Port, the Port Power Role field shall be set to Sink in the
* PS_RDY Message indicating that the initial Source’s power
* supply is turned off"
*/
tcpm_set_pwr_role(port, TYPEC_SINK);
if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
tcpm_set_state(port, ERROR_RECOVERY, 0);
break;
......@@ -2575,7 +2622,6 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
case PR_SWAP_SRC_SNK_SINK_ON:
tcpm_set_pwr_role(port, TYPEC_SINK);
tcpm_swap_complete(port, 0);
tcpm_set_state(port, SNK_STARTUP, 0);
break;
......@@ -2587,8 +2633,15 @@ static void run_state_machine(struct tcpm_port *port)
case PR_SWAP_SNK_SRC_SOURCE_ON:
tcpm_set_cc(port, tcpm_rp_cc(port));
tcpm_set_vbus(port, true);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
/*
* USB PD standard, 6.2.1.4:
* "Subsequent Messages initiated by the Policy Engine,
* such as the PS_RDY Message sent to indicate that Vbus
* is ready, will have the Port Power Role field set to
* Source."
*/
tcpm_set_pwr_role(port, TYPEC_SOURCE);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
tcpm_swap_complete(port, 0);
tcpm_set_state(port, SRC_STARTUP, 0);
break;
......@@ -3292,6 +3345,20 @@ static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo,