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> ...@@ -846,7 +846,6 @@ M: Laura Abbott <labbott@redhat.com>
M: Sumit Semwal <sumit.semwal@linaro.org> M: Sumit Semwal <sumit.semwal@linaro.org>
L: devel@driverdev.osuosl.org L: devel@driverdev.osuosl.org
S: Supported S: Supported
F: Documentation/devicetree/bindings/staging/ion/
F: drivers/staging/android/ion F: drivers/staging/android/ion
F: drivers/staging/android/uapi/ion.h F: drivers/staging/android/uapi/ion.h
F: drivers/staging/android/uapi/ion_test.h F: drivers/staging/android/uapi/ion_test.h
...@@ -3116,6 +3115,14 @@ F: drivers/net/ieee802154/cc2520.c ...@@ -3116,6 +3115,14 @@ F: drivers/net/ieee802154/cc2520.c
F: include/linux/spi/cc2520.h F: include/linux/spi/cc2520.h
F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt 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 CEC FRAMEWORK
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hans.verkuil@cisco.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
...@@ -5695,7 +5702,7 @@ M: Alex Elder <elder@kernel.org> ...@@ -5695,7 +5702,7 @@ M: Alex Elder <elder@kernel.org>
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Maintained S: Maintained
F: drivers/staging/greybus/ F: drivers/staging/greybus/
L: greybus-dev@lists.linaro.org L: greybus-dev@lists.linaro.org (moderated for non-subscribers)
GREYBUS AUDIO PROTOCOLS DRIVERS GREYBUS AUDIO PROTOCOLS DRIVERS
M: Vaibhav Agarwal <vaibhav.sr@gmail.com> 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( ...@@ -376,7 +376,6 @@ int send_request(
rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev); rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev);
if (rc != 0) { if (rc != 0) {
SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc); SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc);
spin_unlock_bh(&req_mgr_h->hw_lock);
return rc; return rc;
} }
#endif #endif
......
...@@ -12,6 +12,7 @@ config FSL_DPAA2 ...@@ -12,6 +12,7 @@ config FSL_DPAA2
config FSL_DPAA2_ETH config FSL_DPAA2_ETH
tristate "Freescale DPAA2 Ethernet" tristate "Freescale DPAA2 Ethernet"
depends on FSL_DPAA2 && FSL_MC_DPIO depends on FSL_DPAA2 && FSL_MC_DPIO
depends on NETDEVICES && ETHERNET
---help--- ---help---
Ethernet driver for Freescale DPAA2 SoCs, using the Ethernet driver for Freescale DPAA2 SoCs, using the
Freescale MC bus driver Freescale MC bus driver
...@@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) ...@@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
switch (variable) { switch (variable) {
case HW_VAR_BSSID: case HW_VAR_BSSID:
rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]); /* BSSIDR 2 byte alignment */
rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]); rtl92e_writew(dev, BSSIDR, *(u16 *)val);
rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2));
break; break;
case HW_VAR_MEDIA_STATUS: case HW_VAR_MEDIA_STATUS:
...@@ -624,7 +625,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev) ...@@ -624,7 +625,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev)
struct r8192_priv *priv = rtllib_priv(dev); struct r8192_priv *priv = rtllib_priv(dev);
RT_TRACE(COMP_INIT, "===========>%s()\n", __func__); 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, RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
curCR); curCR);
priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 : priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
...@@ -961,8 +962,8 @@ static void _rtl92e_net_update(struct net_device *dev) ...@@ -961,8 +962,8 @@ static void _rtl92e_net_update(struct net_device *dev)
rtl92e_config_rate(dev, &rate_config); rtl92e_config_rate(dev, &rate_config);
priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
priv->basic_rate = rate_config &= 0x15f; priv->basic_rate = rate_config &= 0x15f;
rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]); rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid);
rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]); rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2));
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
rtl92e_writew(dev, ATIMWND, 2); rtl92e_writew(dev, ATIMWND, 2);
...@@ -1182,8 +1183,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, ...@@ -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 cb_desc *cb_desc, struct sk_buff *skb)
{ {
struct r8192_priv *priv = rtllib_priv(dev); struct r8192_priv *priv = rtllib_priv(dev);
dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, dma_addr_t mapping;
PCI_DMA_TODEVICE);
struct tx_fwinfo_8190pci *pTxFwInfo; struct tx_fwinfo_8190pci *pTxFwInfo;
pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data; pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
...@@ -1194,8 +1194,6 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, ...@@ -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->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT,
pTxFwInfo->TxRate, cb_desc); 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) { if (cb_desc->bAMPDUEnable) {
pTxFwInfo->AllowAggregation = 1; pTxFwInfo->AllowAggregation = 1;
pTxFwInfo->RxMF = cb_desc->ampdu_factor; pTxFwInfo->RxMF = cb_desc->ampdu_factor;
...@@ -1230,6 +1228,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, ...@@ -1230,6 +1228,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
} }
memset((u8 *)pdesc, 0, 12); 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->LINIP = 0;
pdesc->CmdInit = 1; pdesc->CmdInit = 1;
pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8; pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
......
...@@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr, ...@@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
pTsCommonInfo->TClasNum = TCLAS_Num; pTsCommonInfo->TClasNum = TCLAS_Num;
} }
static bool IsACValid(unsigned int tid)
{
return tid < 7;
}
bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs) 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, ...@@ -328,12 +323,6 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
if (ieee->current_network.qos_data.supported == 0) { if (ieee->current_network.qos_data.supported == 0) {
UP = 0; UP = 0;
} else { } else {
if (!IsACValid(TID)) {
netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
__func__, TID);
return false;
}
switch (TID) { switch (TID) {
case 0: case 0:
case 3: case 3:
...@@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, ...@@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
case 7: case 7:
UP = 7; UP = 7;
break; 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) ...@@ -3531,7 +3531,6 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev)
pwdev_priv->power_mgmt = true; pwdev_priv->power_mgmt = true;
else else
pwdev_priv->power_mgmt = false; pwdev_priv->power_mgmt = false;
kfree((u8 *)wdev);
return ret; return ret;
......
...@@ -264,22 +264,36 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { } ...@@ -264,22 +264,36 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { }
#define FUSB302_RESUME_RETRY 10 #define FUSB302_RESUME_RETRY 10
#define FUSB302_RESUME_RETRY_SLEEP 50 #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 retry_cnt;
int ret = 0;
atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) { if (atomic_read(&chip->pm_suspend)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n",
retry_cnt + 1, FUSB302_RESUME_RETRY); retry_cnt + 1, FUSB302_RESUME_RETRY);
msleep(FUSB302_RESUME_RETRY_SLEEP); msleep(FUSB302_RESUME_RETRY_SLEEP);
} else { } 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); ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data);
if (ret < 0) if (ret < 0)
fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d", 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, ...@@ -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, static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
u8 length, const u8 *data) u8 length, const u8 *data)
{ {
int retry_cnt;
int ret = 0; int ret = 0;
if (length <= 0) if (length <= 0)
return ret; return ret;
atomic_set(&chip->i2c_busy, 1); atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) { if (fusb302_is_suspended(chip)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", atomic_set(&chip->i2c_busy, 0);
retry_cnt + 1, FUSB302_RESUME_RETRY); return -ETIMEDOUT;
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
}
} }
ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address, ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address,
length, data); length, data);
if (ret < 0) if (ret < 0)
...@@ -320,19 +330,15 @@ static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address, ...@@ -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, static int fusb302_i2c_read(struct fusb302_chip *chip,
u8 address, u8 *data) u8 address, u8 *data)
{ {
int retry_cnt;
int ret = 0; int ret = 0;
atomic_set(&chip->i2c_busy, 1); atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) { if (fusb302_is_suspended(chip)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", atomic_set(&chip->i2c_busy, 0);
retry_cnt + 1, FUSB302_RESUME_RETRY); return -ETIMEDOUT;
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
}
} }
ret = i2c_smbus_read_byte_data(chip->i2c_client, address); ret = i2c_smbus_read_byte_data(chip->i2c_client, address);
*data = (u8)ret; *data = (u8)ret;
if (ret < 0) if (ret < 0)
...@@ -345,33 +351,31 @@ static int fusb302_i2c_read(struct fusb302_chip *chip, ...@@ -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, static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address,
u8 length, u8 *data) u8 length, u8 *data)
{ {
int retry_cnt;
int ret = 0; int ret = 0;
if (length <= 0) if (length <= 0)
return ret; return ret;
atomic_set(&chip->i2c_busy, 1); atomic_set(&chip->i2c_busy, 1);
for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
if (atomic_read(&chip->pm_suspend)) { if (fusb302_is_suspended(chip)) {
pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", atomic_set(&chip->i2c_busy, 0);
retry_cnt + 1, FUSB302_RESUME_RETRY); return -ETIMEDOUT;
msleep(FUSB302_RESUME_RETRY_SLEEP);
} else {
break;
}
} }
ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address, ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address,
length, data); length, data);
if (ret < 0) { if (ret < 0) {
fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d", fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d",
address, length, ret); address, length, ret);
return ret; goto done;
} }
if (ret != length) { if (ret != length) {
fusb302_log(chip, "only read %d/%d bytes from 0x%02x", fusb302_log(chip, "only read %d/%d bytes from 0x%02x",
ret, length, address); ret, length, address);
return -EIO; ret = -EIO;
} }
done:
atomic_set(&chip->i2c_busy, 0); atomic_set(&chip->i2c_busy, 0);
return ret; return ret;
...@@ -489,7 +493,7 @@ static int tcpm_init(struct tcpc_dev *dev) ...@@ -489,7 +493,7 @@ static int tcpm_init(struct tcpc_dev *dev)
ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data); ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data);
if (ret < 0) if (ret < 0)
return ret; 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); ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1025,7 +1029,7 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip, ...@@ -1025,7 +1029,7 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip,
buf[pos++] = FUSB302_TKN_SYNC1; buf[pos++] = FUSB302_TKN_SYNC1;
buf[pos++] = FUSB302_TKN_SYNC2; buf[pos++] = FUSB302_TKN_SYNC2;
len = pd_header_cnt(msg->header) * 4; len = pd_header_cnt_le(msg->header) * 4;
/* plug 2 for header */ /* plug 2 for header */
len += 2; len += 2;
if (len > 0x1F) { if (len > 0x1F) {
...@@ -1481,7 +1485,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip, ...@@ -1481,7 +1485,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
(u8 *)&msg->header); (u8 *)&msg->header);
if (ret < 0) if (ret < 0)
return ret; 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 */ /* add 4 to length to include the CRC */
if (len > PD_MAX_PAYLOAD * 4) { if (len > PD_MAX_PAYLOAD * 4) {
fusb302_log(chip, "PD message too long %d", len); fusb302_log(chip, "PD message too long %d", len);
...@@ -1663,14 +1667,12 @@ static int init_gpio(struct fusb302_chip *chip) ...@@ -1663,14 +1667,12 @@ static int init_gpio(struct fusb302_chip *chip)
if (ret < 0) { if (ret < 0) {
fusb302_log(chip, fusb302_log(chip,
"cannot set GPIO Int_N to input, ret=%d", ret); "cannot set GPIO Int_N to input, ret=%d", ret);
gpio_free(chip->gpio_int_n);
return ret; return ret;
} }
ret = gpio_to_irq(chip->gpio_int_n); ret = gpio_to_irq(chip->gpio_int_n);
if (ret < 0) { if (ret < 0) {
fusb302_log(chip, fusb302_log(chip,
"cannot request IRQ for GPIO Int_N, ret=%d", ret); "cannot request IRQ for GPIO Int_N, ret=%d", ret);
gpio_free(chip->gpio_int_n);
return ret; return ret;
} }
chip->gpio_int_n_irq = ret; chip->gpio_int_n_irq = ret;
...@@ -1787,11 +1789,13 @@ static const struct of_device_id fusb302_dt_match[] = { ...@@ -1787,11 +1789,13 @@ static const struct of_device_id fusb302_dt_match[] = {
{.compatible = "fcs,fusb302"}, {.compatible = "fcs,fusb302"},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, fusb302_dt_match);
static const struct i2c_device_id fusb302_i2c_device_id[] = { static const struct i2c_device_id fusb302_i2c_device_id[] = {
{"typec_fusb302", 0}, {"typec_fusb302", 0},
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, fusb302_i2c_device_id);
static const struct dev_pm_ops fusb302_pm_ops = { static const struct dev_pm_ops fusb302_pm_ops = {
.suspend = fusb302_pm_suspend, .suspend = fusb302_pm_suspend,
......
...@@ -92,6 +92,16 @@ static inline unsigned int pd_header_type_le(__le16 header) ...@@ -92,6 +92,16 @@ static inline unsigned int pd_header_type_le(__le16 header)
return pd_header_type(le16_to_cpu(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 #define PD_MAX_PAYLOAD 7
struct pd_message { struct pd_message {
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
* VDM object is minimum of VDM header + 6 additional data objects. * 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 * VDM header
* ---------- * ----------
...@@ -34,7 +37,6 @@ ...@@ -34,7 +37,6 @@
* <5> :: reserved (SVDM), command type (UVDM) * <5> :: reserved (SVDM), command type (UVDM)
* <4:0> :: command * <4:0> :: command
*/ */
#define VDO_MAX_SIZE 7
#define VDO(vid, type, custom) \ #define VDO(vid, type, custom) \
(((vid) << 16) | \ (((vid) << 16) | \
((type) << 15) | \ ((type) << 15) | \
......
...@@ -425,7 +425,7 @@ static const struct regmap_config tcpci_regmap_config = { ...@@ -425,7 +425,7 @@ static const struct regmap_config tcpci_regmap_config = {
.max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */ .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, .type = TYPEC_PORT_DFP,
.default_role = TYPEC_SINK, .default_role = TYPEC_SINK,
}; };
......
...@@ -238,6 +238,7 @@ struct tcpm_port { ...@@ -238,6 +238,7 @@ struct tcpm_port {
unsigned int hard_reset_count; unsigned int hard_reset_count;
bool pd_capable; bool pd_capable;
bool explicit_contract; bool explicit_contract;
unsigned int rx_msgid;
/* Partner capabilities/requests */ /* Partner capabilities/requests */
u32 sink_request; u32 sink_request;
...@@ -251,6 +252,8 @@ struct tcpm_port { ...@@ -251,6 +252,8 @@ struct tcpm_port {
unsigned int nr_src_pdo; unsigned int nr_src_pdo;
u32 snk_pdo[PDO_MAX_OBJECTS]; u32 snk_pdo[PDO_MAX_OBJECTS];
unsigned int nr_snk_pdo; 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_mv;
unsigned int max_snk_ma; unsigned int max_snk_ma;
...@@ -997,6 +1000,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, ...@@ -997,6 +1000,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
struct pd_mode_data *modep; struct pd_mode_data *modep;
int rlen = 0; int rlen = 0;
u16 svid; u16 svid;
int i;
tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d", tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d",
p0, cmd_type, cmd, cnt); p0, cmd_type, cmd, cnt);
...@@ -1007,6 +1011,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, ...@@ -1007,6 +1011,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
case CMDT_INIT: case CMDT_INIT:
switch (cmd) { switch (cmd) {
case CMD_DISCOVER_IDENT: 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; break;
case CMD_DISCOVER_SVID: case CMD_DISCOVER_SVID:
break; break;
...@@ -1415,6 +1427,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, ...@@ -1415,6 +1427,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break; break;
case SOFT_RESET_SEND: case SOFT_RESET_SEND:
port->message_id = 0; port->message_id = 0;
port->rx_msgid = -1;
if (port->pwr_role == TYPEC_SOURCE) if (port->pwr_role == TYPEC_SOURCE)
next_state = SRC_SEND_CAPABILITIES; next_state = SRC_SEND_CAPABILITIES;
else else
...@@ -1503,6 +1516,22 @@ static void tcpm_pd_rx_handler(struct work_struct *work) ...@@ -1503,6 +1516,22 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
port->attached); port->attached);
if (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 * If both ends believe to be DFP/host, we have a data role
* mismatch. * mismatch.
...@@ -1520,6 +1549,7 @@ static void tcpm_pd_rx_handler(struct work_struct *work) ...@@ -1520,6 +1549,7 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
} }
} }
done:
mutex_unlock(&port->lock); mutex_unlock(&port->lock);
kfree(event); kfree(event);
} }
...@@ -1719,8 +1749,7 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) ...@@ -1719,8 +1749,7 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
} }
ma = min(ma, port->max_snk_ma); ma = min(ma, port->max_snk_ma);
/* XXX: Any other flags need to be set? */ flags = RDO_USB_COMM | RDO_NO_SUSPEND;
flags = 0;
/* Set mismatch bit if offered power is less than operating power */ /* Set mismatch bit if offered power is less than operating power */
mw = ma * mv / 1000; mw = ma * mv / 1000;
...@@ -1957,6 +1986,12 @@ static void tcpm_reset_port(struct tcpm_port *port) ...@@ -1957,6 +1986,12 @@ static void tcpm_reset_port(struct tcpm_port *port)
port->attached = false; port->attached = false;
port->pd_capable = 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); port->tcpc->set_pd_rx(port->tcpc, false);
tcpm_init_vbus(port); /* also disables charging */ tcpm_init_vbus(port); /* also disables charging */
tcpm_init_vconn(port); tcpm_init_vconn(port);
...@@ -2170,6 +2205,7 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2170,6 +2205,7 @@ static void run_state_machine(struct tcpm_port *port)
port->pwr_opmode = TYPEC_PWR_MODE_USB; port->pwr_opmode = TYPEC_PWR_MODE_USB;
port->caps_count = 0; port->caps_count = 0;
port->message_id = 0; port->message_id = 0;
port->rx_msgid = -1;
port->explicit_contract = false; port->explicit_contract = false;
tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
break; break;
...@@ -2329,6 +2365,7 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2329,6 +2365,7 @@ static void run_state_machine(struct tcpm_port *port)
typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB); typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB);
port->pwr_opmode = TYPEC_PWR_MODE_USB; port->pwr_opmode = TYPEC_PWR_MODE_USB;
port->message_id = 0; port->message_id = 0;
port->rx_msgid = -1;
port->explicit_contract = false; port->explicit_contract = false;
tcpm_set_state(port, SNK_DISCOVERY, 0); tcpm_set_state(port, SNK_DISCOVERY, 0);
break; break;
...@@ -2496,6 +2533,7 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2496,6 +2533,7 @@ static void run_state_machine(struct tcpm_port *port)
/* Soft_Reset states */ /* Soft_Reset states */
case SOFT_RESET: case SOFT_RESET:
port->message_id = 0; port->message_id = 0;
port->rx_msgid = -1;
tcpm_pd_send_control(port, PD_CTRL_ACCEPT); tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
if (port->pwr_role == TYPEC_SOURCE) if (port->pwr_role == TYPEC_SOURCE)
tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
...@@ -2504,6 +2542,7 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2504,6 +2542,7 @@ static void run_state_machine(struct tcpm_port *port)
break; break;
case SOFT_RESET_SEND: case SOFT_RESET_SEND:
port->message_id = 0; port->message_id = 0;
port->rx_msgid = -1;
if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET)) if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
tcpm_set_state_cond(port, hard_reset_state(port), 0); tcpm_set_state_cond(port, hard_reset_state(port), 0);
else else
...@@ -2568,6 +2607,14 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2568,6 +2607,14 @@ static void run_state_machine(struct tcpm_port *port)
break; break;
case PR_SWAP_SRC_SNK_SOURCE_OFF: case PR_SWAP_SRC_SNK_SOURCE_OFF:
tcpm_set_cc(port, TYPEC_CC_RD); 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)) { if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
tcpm_set_state(port, ERROR_RECOVERY, 0); tcpm_set_state(port, ERROR_RECOVERY, 0);
break; break;
...@@ -2575,7 +2622,6 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -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); tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
break; break;
case PR_SWAP_SRC_SNK_SINK_ON: case PR_SWAP_SRC_SNK_SINK_ON:
tcpm_set_pwr_role(port, TYPEC_SINK);
tcpm_swap_complete(port, 0); tcpm_swap_complete(port, 0);
tcpm_set_state(port, SNK_STARTUP, 0); tcpm_set_state(port, SNK_STARTUP, 0);
break; break;
...@@ -2587,8 +2633,15 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2587,8 +2633,15 @@ static void run_state_machine(struct tcpm_port *port)
case PR_SWAP_SNK_SRC_SOURCE_ON: case PR_SWAP_SNK_SRC_SOURCE_ON:
tcpm_set_cc(port, tcpm_rp_cc(port)); tcpm_set_cc(port, tcpm_rp_cc(port));
tcpm_set_vbus(port, true); 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_set_pwr_role(port, TYPEC_SOURCE);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
tcpm_swap_complete(port, 0); tcpm_swap_complete(port, 0);
tcpm_set_state(port, SRC_STARTUP, 0); tcpm_set_state(port, SRC_STARTUP, 0);
break; break;
...@@ -3292,6 +3345,20 @@ static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo, ...@@ -3292,6 +3345,20 @@ static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo,
return nr_pdo; return nr_pdo;
} }
static int tcpm_copy_vdos(u32 *dest_vdo, const u32 *src_vdo,
unsigned int nr_vdo)
{
unsigned int i;
if (nr_vdo > VDO_MAX_OBJECTS)
nr_vdo = VDO_MAX_OBJECTS;
for (i = 0; i < nr_vdo; i++)
dest_vdo[i] = src_vdo[i];
return nr_vdo;
}
void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo,
unsigned int nr_pdo) unsigned int nr_pdo)
{ {
...@@ -3382,6 +3449,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) ...@@ -3382,6 +3449,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
tcpc->config->nr_src_pdo); tcpc->config->nr_src_pdo);
port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo,
tcpc->config->nr_snk_pdo); tcpc->config->nr_snk_pdo);
port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo,
tcpc->config->nr_snk_vdo);
port->max_snk_mv = tcpc->config->max_snk_mv; port->max_snk_mv = tcpc->config->max_snk_mv;
port->max_snk_ma = tcpc->config->max_snk_ma; port->max_snk_ma = tcpc->config->max_snk_ma;
......
...@@ -60,6 +60,9 @@ struct tcpc_config { ...@@ -60,6 +60,9 @@ struct tcpc_config {
const u32 *snk_pdo; const u32 *snk_pdo;
unsigned int nr_snk_pdo; unsigned int nr_snk_pdo;
const u32 *snk_vdo;
unsigned int nr_snk_vdo;
unsigned int max_snk_mv; unsigned int max_snk_mv;
unsigned int max_snk_ma; unsigned int max_snk_ma;
unsigned int max_snk_mw; unsigned int max_snk_mw;
......
...@@ -502,8 +502,15 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, ...@@ -502,8 +502,15 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
*/ */
sg_init_table(scatterlist, num_pages); sg_init_table(scatterlist, num_pages);
/* Now set the pages for each scatterlist */ /* Now set the pages for each scatterlist */
for (i = 0; i < num_pages; i++) for (i = 0; i < num_pages; i++) {
sg_set_page(scatterlist + i, pages[i], PAGE_SIZE, 0); unsigned int len = PAGE_SIZE - offset;
if (len > count)
len = count;
sg_set_page(scatterlist + i, pages[i], len, offset);
offset = 0;
count -= len;
}
dma_buffers = dma_map_sg(g_dev, dma_buffers = dma_map_sg(g_dev,
scatterlist, scatterlist,
...@@ -524,20 +531,20 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, ...@@ -524,20 +531,20 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
u32 addr = sg_dma_address(sg); u32 addr = sg_dma_address(sg);
/* Note: addrs is the address + page_count - 1 /* Note: addrs is the address + page_count - 1
* The firmware expects the block to be page * The firmware expects blocks after the first to be page-
* aligned and a multiple of the page size * aligned and a multiple of the page size
*/ */
WARN_ON(len == 0); WARN_ON(len == 0);
WARN_ON(len & ~PAGE_MASK); WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
WARN_ON(addr & ~PAGE_MASK); WARN_ON(i && (addr & ~PAGE_MASK));
if (k > 0 && if (k > 0 &&
((addrs[k - 1] & PAGE_MASK) | ((addrs[k - 1] & PAGE_MASK) +
((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT) (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
== addr) { == (addr & PAGE_MASK))
addrs[k - 1] += (len >> PAGE_SHIFT); addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
} else { else
addrs[k++] = addr | ((len >> PAGE_SHIFT) - 1); addrs[k++] = (addr & PAGE_MASK) |
} (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
} }
/* Partial cache lines (fragments) require special measures */ /* Partial cache lines (fragments) require special measures */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment