USB / PHY / Thunderbolt fixes and ids for 6.7-rc3

Here are a number of reverts, fixes, and new device ids for 6.7-rc3 for
 the USB, PHY, and Thunderbolt driver subsystems.  Include in here are:
   - reverts of some PHY drivers that went into 6.7-rc1 that shouldn't
     have been merged yet, the author is reworking them based on review
     comments as they were using older apis that shouldn't be used
     anymore for newer drivers
   - small thunderbolt driver fixes for reported issues
   - USB driver fixes for a variety of small issues in dwc3, typec, xhci,
     and other smaller drivers.
   - new device ids for usb-serial and onboard_usb_hub drivers.
 
 All of these have been in linux-next with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZWJQEw8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymq6ACcDMyH78Tv6QeSiI6+czelYbIWarUAoNdM4CEs
 DAb8WIkleXLSzrV+PHJN
 =IYJt
 -----END PGP SIGNATURE-----

Merge tag 'usb-6.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB / PHY / Thunderbolt fixes from Greg KH:
 "Here are a number of reverts, fixes, and new device ids for 6.7-rc3
  for the USB, PHY, and Thunderbolt driver subsystems. Include in here
  are:

   - reverts of some PHY drivers that went into 6.7-rc1 that shouldn't
     have been merged yet, the author is reworking them based on review
     comments as they were using older apis that shouldn't be used
     anymore for newer drivers

   - small thunderbolt driver fixes for reported issues

   - USB driver fixes for a variety of small issues in dwc3, typec,
     xhci, and other smaller drivers.

   - new device ids for usb-serial and onboard_usb_hub drivers.

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

* tag 'usb-6.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (33 commits)
  USB: serial: option: add Luat Air72*U series products
  USB: dwc3: qcom: fix ACPI platform device leak
  USB: dwc3: qcom: fix software node leak on probe errors
  USB: dwc3: qcom: fix resource leaks on probe deferral
  USB: dwc3: qcom: simplify wakeup interrupt setup
  USB: dwc3: qcom: fix wakeup after probe deferral
  dt-bindings: usb: qcom,dwc3: fix example wakeup interrupt types
  usb: misc: onboard-hub: add support for Microchip USB5744
  dt-bindings: usb: microchip,usb5744: Add second supply
  usb: misc: ljca: Fix enumeration error on Dell Latitude 9420
  USB: serial: option: add Fibocom L7xx modules
  USB: xhci-plat: fix legacy PHY double init
  usb: typec: tipd: Supply also I2C driver data
  usb: xhci-mtk: fix in-ep's start-split check failure
  usb: dwc3: set the dma max_seg_size
  usb: config: fix iteration issue in 'usb_get_bos_descriptor()'
  usb: dwc3: add missing of_node_put and platform_device_put
  USB: dwc2: write HCINT with INTMASK applied
  usb: misc: ljca: Drop _ADR support to get ljca children devices
  usb: cdnsp: Fix deadlock issue during using NCM gadget
  ...
This commit is contained in:
Linus Torvalds 2023-11-25 18:22:42 -08:00
commit 090472ed9c
29 changed files with 175 additions and 2245 deletions

View file

@ -36,7 +36,11 @@ properties:
vdd-supply:
description:
VDD power supply to the hub
3V3 power supply to the hub
vdd2-supply:
description:
1V2 power supply to the hub
peer-hub:
$ref: /schemas/types.yaml#/definitions/phandle
@ -62,6 +66,7 @@ allOf:
properties:
reset-gpios: false
vdd-supply: false
vdd2-supply: false
peer-hub: false
i2c-bus: false
else:

View file

@ -521,8 +521,8 @@ examples:
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>;
<GIC_SPI 488 IRQ_TYPE_EDGE_BOTH>,
<GIC_SPI 489 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "hs_phy_irq", "ss_phy_irq",
"dm_hs_phy_irq", "dp_hs_phy_irq";

View file

@ -41,7 +41,7 @@ examples:
- |
usb {
phys = <&usb2_phy1>, <&usb3_phy1>;
phy-names = "usb";
phy-names = "usb2", "usb3";
#address-cells = <1>;
#size-cells = <0>;

View file

@ -87,7 +87,6 @@ source "drivers/phy/motorola/Kconfig"
source "drivers/phy/mscc/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
source "drivers/phy/realtek/Kconfig"
source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"

View file

@ -26,7 +26,6 @@ obj-y += allwinner/ \
mscc/ \
qualcomm/ \
ralink/ \
realtek/ \
renesas/ \
rockchip/ \
samsung/ \

View file

@ -1,32 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Phy drivers for Realtek platforms
#
if ARCH_REALTEK || COMPILE_TEST
config PHY_RTK_RTD_USB2PHY
tristate "Realtek RTD USB2 PHY Transceiver Driver"
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
select USB_COMMON
help
Enable this to support Realtek SoC USB2 phy transceiver.
The DHC (digital home center) RTD series SoCs used the Synopsys
DWC3 USB IP. This driver will do the PHY initialization
of the parameters.
config PHY_RTK_RTD_USB3PHY
tristate "Realtek RTD USB3 PHY Transceiver Driver"
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
select USB_COMMON
help
Enable this to support Realtek SoC USB3 phy transceiver.
The DHC (digital home center) RTD series SoCs used the Synopsys
DWC3 USB IP. This driver will do the PHY initialization
of the parameters.
endif # ARCH_REALTEK || COMPILE_TEST

View file

@ -1,3 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_RTK_RTD_USB2PHY) += phy-rtk-usb2.o
obj-$(CONFIG_PHY_RTK_RTD_USB3PHY) += phy-rtk-usb3.o

File diff suppressed because it is too large Load diff

View file

@ -1,761 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* phy-rtk-usb3.c RTK usb3.0 phy driver
*
* copyright (c) 2023 realtek semiconductor corporation
*
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/nvmem-consumer.h>
#include <linux/regmap.h>
#include <linux/sys_soc.h>
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/phy.h>
#define USB_MDIO_CTRL_PHY_BUSY BIT(7)
#define USB_MDIO_CTRL_PHY_WRITE BIT(0)
#define USB_MDIO_CTRL_PHY_ADDR_SHIFT 8
#define USB_MDIO_CTRL_PHY_DATA_SHIFT 16
#define MAX_USB_PHY_DATA_SIZE 0x30
#define PHY_ADDR_0X09 0x09
#define PHY_ADDR_0X0B 0x0b
#define PHY_ADDR_0X0D 0x0d
#define PHY_ADDR_0X10 0x10
#define PHY_ADDR_0X1F 0x1f
#define PHY_ADDR_0X20 0x20
#define PHY_ADDR_0X21 0x21
#define PHY_ADDR_0X30 0x30
#define REG_0X09_FORCE_CALIBRATION BIT(9)
#define REG_0X0B_RX_OFFSET_RANGE_MASK 0xc
#define REG_0X0D_RX_DEBUG_TEST_EN BIT(6)
#define REG_0X10_DEBUG_MODE_SETTING 0x3c0
#define REG_0X10_DEBUG_MODE_SETTING_MASK 0x3f8
#define REG_0X1F_RX_OFFSET_CODE_MASK 0x1e
#define USB_U3_TX_LFPS_SWING_TRIM_SHIFT 4
#define USB_U3_TX_LFPS_SWING_TRIM_MASK 0xf
#define AMPLITUDE_CONTROL_COARSE_MASK 0xff
#define AMPLITUDE_CONTROL_FINE_MASK 0xffff
#define AMPLITUDE_CONTROL_COARSE_DEFAULT 0xff
#define AMPLITUDE_CONTROL_FINE_DEFAULT 0xffff
#define PHY_ADDR_MAP_ARRAY_INDEX(addr) (addr)
#define ARRAY_INDEX_MAP_PHY_ADDR(index) (index)
struct phy_reg {
void __iomem *reg_mdio_ctl;
};
struct phy_data {
u8 addr;
u16 data;
};
struct phy_cfg {
int param_size;
struct phy_data param[MAX_USB_PHY_DATA_SIZE];
bool check_efuse;
bool do_toggle;
bool do_toggle_once;
bool use_default_parameter;
bool check_rx_front_end_offset;
};
struct phy_parameter {
struct phy_reg phy_reg;
/* Get from efuse */
u8 efuse_usb_u3_tx_lfps_swing_trim;
/* Get from dts */
u32 amplitude_control_coarse;
u32 amplitude_control_fine;
};
struct rtk_phy {
struct usb_phy phy;
struct device *dev;
struct phy_cfg *phy_cfg;
int num_phy;
struct phy_parameter *phy_parameter;
struct dentry *debug_dir;
};
#define PHY_IO_TIMEOUT_USEC (50000)
#define PHY_IO_DELAY_US (100)
static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
{
int ret;
unsigned int val;
ret = read_poll_timeout(readl, val, ((val & mask) == result),
PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
if (ret) {
pr_err("%s can't program USB phy\n", __func__);
return -ETIMEDOUT;
}
return 0;
}
static int rtk_phy3_wait_vbusy(struct phy_reg *phy_reg)
{
return utmi_wait_register(phy_reg->reg_mdio_ctl, USB_MDIO_CTRL_PHY_BUSY, 0);
}
static u16 rtk_phy_read(struct phy_reg *phy_reg, char addr)
{
unsigned int tmp;
u32 value;
tmp = (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT);
writel(tmp, phy_reg->reg_mdio_ctl);
rtk_phy3_wait_vbusy(phy_reg);
value = readl(phy_reg->reg_mdio_ctl);
value = value >> USB_MDIO_CTRL_PHY_DATA_SHIFT;
return (u16)value;
}
static int rtk_phy_write(struct phy_reg *phy_reg, char addr, u16 data)
{
unsigned int val;
val = USB_MDIO_CTRL_PHY_WRITE |
(addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT) |
(data << USB_MDIO_CTRL_PHY_DATA_SHIFT);
writel(val, phy_reg->reg_mdio_ctl);
rtk_phy3_wait_vbusy(phy_reg);
return 0;
}
static void do_rtk_usb3_phy_toggle(struct rtk_phy *rtk_phy, int index, bool connect)
{
struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
struct phy_reg *phy_reg;
struct phy_parameter *phy_parameter;
struct phy_data *phy_data;
u8 addr;
u16 data;
int i;
phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
phy_reg = &phy_parameter->phy_reg;
if (!phy_cfg->do_toggle)
return;
i = PHY_ADDR_MAP_ARRAY_INDEX(PHY_ADDR_0X09);
phy_data = phy_cfg->param + i;
addr = phy_data->addr;
data = phy_data->data;
if (!addr && !data) {
addr = PHY_ADDR_0X09;
data = rtk_phy_read(phy_reg, addr);
phy_data->addr = addr;
phy_data->data = data;
}
rtk_phy_write(phy_reg, addr, data & (~REG_0X09_FORCE_CALIBRATION));
mdelay(1);
rtk_phy_write(phy_reg, addr, data | REG_0X09_FORCE_CALIBRATION);
}
static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
{
struct phy_cfg *phy_cfg;
struct phy_reg *phy_reg;
struct phy_parameter *phy_parameter;
int i = 0;
phy_cfg = rtk_phy->phy_cfg;
phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
phy_reg = &phy_parameter->phy_reg;
if (phy_cfg->use_default_parameter)
goto do_toggle;
for (i = 0; i < phy_cfg->param_size; i++) {
struct phy_data *phy_data = phy_cfg->param + i;
u8 addr = phy_data->addr;
u16 data = phy_data->data;
if (!addr && !data)
continue;
rtk_phy_write(phy_reg, addr, data);
}
do_toggle:
if (phy_cfg->do_toggle_once)
phy_cfg->do_toggle = true;
do_rtk_usb3_phy_toggle(rtk_phy, index, false);
if (phy_cfg->do_toggle_once) {
u16 check_value = 0;
int count = 10;
u16 value_0x0d, value_0x10;
/* Enable Debug mode by set 0x0D and 0x10 */
value_0x0d = rtk_phy_read(phy_reg, PHY_ADDR_0X0D);
value_0x10 = rtk_phy_read(phy_reg, PHY_ADDR_0X10);
rtk_phy_write(phy_reg, PHY_ADDR_0X0D,
value_0x0d | REG_0X0D_RX_DEBUG_TEST_EN);
rtk_phy_write(phy_reg, PHY_ADDR_0X10,
(value_0x10 & ~REG_0X10_DEBUG_MODE_SETTING_MASK) |
REG_0X10_DEBUG_MODE_SETTING);
check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
while (!(check_value & BIT(15))) {
check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
mdelay(1);
if (count-- < 0)
break;
}
if (!(check_value & BIT(15)))
dev_info(rtk_phy->dev, "toggle fail addr=0x%02x, data=0x%04x\n",
PHY_ADDR_0X30, check_value);
/* Disable Debug mode by set 0x0D and 0x10 to default*/
rtk_phy_write(phy_reg, PHY_ADDR_0X0D, value_0x0d);
rtk_phy_write(phy_reg, PHY_ADDR_0X10, value_0x10);
phy_cfg->do_toggle = false;
}
if (phy_cfg->check_rx_front_end_offset) {
u16 rx_offset_code, rx_offset_range;
u16 code_mask = REG_0X1F_RX_OFFSET_CODE_MASK;
u16 range_mask = REG_0X0B_RX_OFFSET_RANGE_MASK;
bool do_update = false;
rx_offset_code = rtk_phy_read(phy_reg, PHY_ADDR_0X1F);
if (((rx_offset_code & code_mask) == 0x0) ||
((rx_offset_code & code_mask) == code_mask))
do_update = true;
rx_offset_range = rtk_phy_read(phy_reg, PHY_ADDR_0X0B);
if (((rx_offset_range & range_mask) == range_mask) && do_update) {
dev_warn(rtk_phy->dev, "Don't update rx_offset_range (rx_offset_code=0x%x, rx_offset_range=0x%x)\n",
rx_offset_code, rx_offset_range);
do_update = false;
}
if (do_update) {
u16 tmp1, tmp2;
tmp1 = rx_offset_range & (~range_mask);
tmp2 = rx_offset_range & range_mask;
tmp2 += (1 << 2);
rx_offset_range = tmp1 | (tmp2 & range_mask);
rtk_phy_write(phy_reg, PHY_ADDR_0X0B, rx_offset_range);
goto do_toggle;
}
}
return 0;
}
static int rtk_phy_init(struct phy *phy)
{
struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
int ret = 0;
int i;
unsigned long phy_init_time = jiffies;
for (i = 0; i < rtk_phy->num_phy; i++)
ret = do_rtk_phy_init(rtk_phy, i);
dev_dbg(rtk_phy->dev, "Initialized RTK USB 3.0 PHY (take %dms)\n",
jiffies_to_msecs(jiffies - phy_init_time));
return ret;
}
static int rtk_phy_exit(struct phy *phy)
{
return 0;
}
static const struct phy_ops ops = {
.init = rtk_phy_init,
.exit = rtk_phy_exit,
.owner = THIS_MODULE,
};
static void rtk_phy_toggle(struct usb_phy *usb3_phy, bool connect, int port)
{
int index = port;
struct rtk_phy *rtk_phy = NULL;
rtk_phy = dev_get_drvdata(usb3_phy->dev);
if (index > rtk_phy->num_phy) {
dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
__func__, index, rtk_phy->num_phy);
return;
}
do_rtk_usb3_phy_toggle(rtk_phy, index, connect);
}
static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
u16 portstatus, u16 portchange)
{
bool connect = false;
pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
__func__, port, (int)portstatus, (int)portchange);
if (portstatus & USB_PORT_STAT_CONNECTION)
connect = true;
if (portchange & USB_PORT_STAT_C_CONNECTION)
rtk_phy_toggle(x, connect, port);
return 0;
}
#ifdef CONFIG_DEBUG_FS
static struct dentry *create_phy_debug_root(void)
{
struct dentry *phy_debug_root;
phy_debug_root = debugfs_lookup("phy", usb_debug_root);
if (!phy_debug_root)
phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
return phy_debug_root;
}
static int rtk_usb3_parameter_show(struct seq_file *s, void *unused)
{
struct rtk_phy *rtk_phy = s->private;
struct phy_cfg *phy_cfg;
int i, index;
phy_cfg = rtk_phy->phy_cfg;
seq_puts(s, "Property:\n");
seq_printf(s, " check_efuse: %s\n",
phy_cfg->check_efuse ? "Enable" : "Disable");
seq_printf(s, " do_toggle: %s\n",
phy_cfg->do_toggle ? "Enable" : "Disable");
seq_printf(s, " do_toggle_once: %s\n",
phy_cfg->do_toggle_once ? "Enable" : "Disable");
seq_printf(s, " use_default_parameter: %s\n",
phy_cfg->use_default_parameter ? "Enable" : "Disable");
for (index = 0; index < rtk_phy->num_phy; index++) {
struct phy_reg *phy_reg;
struct phy_parameter *phy_parameter;
phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
phy_reg = &phy_parameter->phy_reg;
seq_printf(s, "PHY %d:\n", index);
for (i = 0; i < phy_cfg->param_size; i++) {
struct phy_data *phy_data = phy_cfg->param + i;
u8 addr = ARRAY_INDEX_MAP_PHY_ADDR(i);
u16 data = phy_data->data;
if (!phy_data->addr && !data)
seq_printf(s, " addr = 0x%02x, data = none ==> read value = 0x%04x\n",
addr, rtk_phy_read(phy_reg, addr));
else
seq_printf(s, " addr = 0x%02x, data = 0x%04x ==> read value = 0x%04x\n",
addr, data, rtk_phy_read(phy_reg, addr));
}
seq_puts(s, "PHY Property:\n");
seq_printf(s, " efuse_usb_u3_tx_lfps_swing_trim: 0x%x\n",
(int)phy_parameter->efuse_usb_u3_tx_lfps_swing_trim);
seq_printf(s, " amplitude_control_coarse: 0x%x\n",
(int)phy_parameter->amplitude_control_coarse);
seq_printf(s, " amplitude_control_fine: 0x%x\n",
(int)phy_parameter->amplitude_control_fine);
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(rtk_usb3_parameter);
static inline void create_debug_files(struct rtk_phy *rtk_phy)
{
struct dentry *phy_debug_root = NULL;
phy_debug_root = create_phy_debug_root();
if (!phy_debug_root)
return;
rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root);
debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
&rtk_usb3_parameter_fops);
return;
}
static inline void remove_debug_files(struct rtk_phy *rtk_phy)
{
debugfs_remove_recursive(rtk_phy->debug_dir);
}
#else
static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
#endif /* CONFIG_DEBUG_FS */
static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
struct phy_parameter *phy_parameter, int index)
{
struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
u8 value = 0;
struct nvmem_cell *cell;
if (!phy_cfg->check_efuse)
goto out;
cell = nvmem_cell_get(rtk_phy->dev, "usb_u3_tx_lfps_swing_trim");
if (IS_ERR(cell)) {
dev_dbg(rtk_phy->dev, "%s no usb_u3_tx_lfps_swing_trim: %ld\n",
__func__, PTR_ERR(cell));
} else {
unsigned char *buf;
size_t buf_size;
buf = nvmem_cell_read(cell, &buf_size);
if (!IS_ERR(buf)) {
value = buf[0] & USB_U3_TX_LFPS_SWING_TRIM_MASK;
kfree(buf);
}
nvmem_cell_put(cell);
}
if (value > 0 && value < 0x8)
phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = 0x8;
else
phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = (u8)value;
out:
return 0;
}
static void update_amplitude_control_value(struct rtk_phy *rtk_phy,
struct phy_parameter *phy_parameter)
{
struct phy_cfg *phy_cfg;
struct phy_reg *phy_reg;
phy_reg = &phy_parameter->phy_reg;
phy_cfg = rtk_phy->phy_cfg;
if (phy_parameter->amplitude_control_coarse != AMPLITUDE_CONTROL_COARSE_DEFAULT) {
u16 val_mask = AMPLITUDE_CONTROL_COARSE_MASK;
u16 data;
if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
} else {
data = phy_cfg->param[PHY_ADDR_0X20].data;
}
data &= (~val_mask);
data |= (phy_parameter->amplitude_control_coarse & val_mask);
phy_cfg->param[PHY_ADDR_0X20].data = data;
}
if (phy_parameter->efuse_usb_u3_tx_lfps_swing_trim) {
u8 efuse_val = phy_parameter->efuse_usb_u3_tx_lfps_swing_trim;
u16 val_mask = USB_U3_TX_LFPS_SWING_TRIM_MASK;
int val_shift = USB_U3_TX_LFPS_SWING_TRIM_SHIFT;
u16 data;
if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
} else {
data = phy_cfg->param[PHY_ADDR_0X20].data;
}
data &= ~(val_mask << val_shift);
data |= ((efuse_val & val_mask) << val_shift);
phy_cfg->param[PHY_ADDR_0X20].data = data;
}
if (phy_parameter->amplitude_control_fine != AMPLITUDE_CONTROL_FINE_DEFAULT) {
u16 val_mask = AMPLITUDE_CONTROL_FINE_MASK;
if (!phy_cfg->param[PHY_ADDR_0X21].addr && !phy_cfg->param[PHY_ADDR_0X21].data)
phy_cfg->param[PHY_ADDR_0X21].addr = PHY_ADDR_0X21;
phy_cfg->param[PHY_ADDR_0X21].data =
phy_parameter->amplitude_control_fine & val_mask;
}
}
static int parse_phy_data(struct rtk_phy *rtk_phy)
{
struct device *dev = rtk_phy->dev;
struct phy_parameter *phy_parameter;
int ret = 0;
int index;
rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
rtk_phy->num_phy, GFP_KERNEL);
if (!rtk_phy->phy_parameter)
return -ENOMEM;
for (index = 0; index < rtk_phy->num_phy; index++) {
phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
phy_parameter->phy_reg.reg_mdio_ctl = of_iomap(dev->of_node, 0) + index;
/* Amplitude control address 0x20 bit 0 to bit 7 */
if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-coarse-tuning",
&phy_parameter->amplitude_control_coarse))
phy_parameter->amplitude_control_coarse = AMPLITUDE_CONTROL_COARSE_DEFAULT;
/* Amplitude control address 0x21 bit 0 to bit 16 */
if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-fine-tuning",
&phy_parameter->amplitude_control_fine))
phy_parameter->amplitude_control_fine = AMPLITUDE_CONTROL_FINE_DEFAULT;
get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
update_amplitude_control_value(rtk_phy, phy_parameter);
}
return ret;
}
static int rtk_usb3phy_probe(struct platform_device *pdev)
{
struct rtk_phy *rtk_phy;
struct device *dev = &pdev->dev;
struct phy *generic_phy;
struct phy_provider *phy_provider;
const struct phy_cfg *phy_cfg;
int ret;
phy_cfg = of_device_get_match_data(dev);
if (!phy_cfg) {
dev_err(dev, "phy config are not assigned!\n");
return -EINVAL;
}
rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
if (!rtk_phy)
return -ENOMEM;
rtk_phy->dev = &pdev->dev;
rtk_phy->phy.dev = rtk_phy->dev;
rtk_phy->phy.label = "rtk-usb3phy";
rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
rtk_phy->num_phy = 1;
ret = parse_phy_data(rtk_phy);
if (ret)
goto err;
platform_set_drvdata(pdev, rtk_phy);
generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
if (IS_ERR(generic_phy))
return PTR_ERR(generic_phy);
phy_set_drvdata(generic_phy, rtk_phy);
phy_provider = devm_of_phy_provider_register(rtk_phy->dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
ret = usb_add_phy_dev(&rtk_phy->phy);
if (ret)
goto err;
create_debug_files(rtk_phy);
err:
return ret;
}
static void rtk_usb3phy_remove(struct platform_device *pdev)
{
struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
remove_debug_files(rtk_phy);
usb_remove_phy(&rtk_phy->phy);
}
static const struct phy_cfg rtd1295_phy_cfg = {
.param_size = MAX_USB_PHY_DATA_SIZE,
.param = { [0] = {0x01, 0x4008}, [1] = {0x01, 0xe046},
[2] = {0x02, 0x6046}, [3] = {0x03, 0x2779},
[4] = {0x04, 0x72f5}, [5] = {0x05, 0x2ad3},
[6] = {0x06, 0x000e}, [7] = {0x07, 0x2e00},
[8] = {0x08, 0x3591}, [9] = {0x09, 0x525c},
[10] = {0x0a, 0xa600}, [11] = {0x0b, 0xa904},
[12] = {0x0c, 0xc000}, [13] = {0x0d, 0xef1c},
[14] = {0x0e, 0x2000}, [15] = {0x0f, 0x0000},
[16] = {0x10, 0x000c}, [17] = {0x11, 0x4c00},
[18] = {0x12, 0xfc00}, [19] = {0x13, 0x0c81},
[20] = {0x14, 0xde01}, [21] = {0x15, 0x0000},
[22] = {0x16, 0x0000}, [23] = {0x17, 0x0000},
[24] = {0x18, 0x0000}, [25] = {0x19, 0x4004},
[26] = {0x1a, 0x1260}, [27] = {0x1b, 0xff00},
[28] = {0x1c, 0xcb00}, [29] = {0x1d, 0xa03f},
[30] = {0x1e, 0xc2e0}, [31] = {0x1f, 0x2807},
[32] = {0x20, 0x947a}, [33] = {0x21, 0x88aa},
[34] = {0x22, 0x0057}, [35] = {0x23, 0xab66},
[36] = {0x24, 0x0800}, [37] = {0x25, 0x0000},
[38] = {0x26, 0x040a}, [39] = {0x27, 0x01d6},
[40] = {0x28, 0xf8c2}, [41] = {0x29, 0x3080},
[42] = {0x2a, 0x3082}, [43] = {0x2b, 0x2078},
[44] = {0x2c, 0xffff}, [45] = {0x2d, 0xffff},
[46] = {0x2e, 0x0000}, [47] = {0x2f, 0x0040}, },
.check_efuse = false,
.do_toggle = true,
.do_toggle_once = false,
.use_default_parameter = false,
.check_rx_front_end_offset = false,
};
static const struct phy_cfg rtd1619_phy_cfg = {
.param_size = MAX_USB_PHY_DATA_SIZE,
.param = { [8] = {0x08, 0x3591},
[38] = {0x26, 0x840b},
[40] = {0x28, 0xf842}, },
.check_efuse = false,
.do_toggle = true,
.do_toggle_once = false,
.use_default_parameter = false,
.check_rx_front_end_offset = false,
};
static const struct phy_cfg rtd1319_phy_cfg = {
.param_size = MAX_USB_PHY_DATA_SIZE,
.param = { [1] = {0x01, 0xac86},
[6] = {0x06, 0x0003},
[9] = {0x09, 0x924c},
[10] = {0x0a, 0xa608},
[11] = {0x0b, 0xb905},
[14] = {0x0e, 0x2010},
[32] = {0x20, 0x705a},
[33] = {0x21, 0xf645},
[34] = {0x22, 0x0013},
[35] = {0x23, 0xcb66},
[41] = {0x29, 0xff00}, },
.check_efuse = true,
.do_toggle = true,
.do_toggle_once = false,
.use_default_parameter = false,
.check_rx_front_end_offset = false,
};
static const struct phy_cfg rtd1619b_phy_cfg = {
.param_size = MAX_USB_PHY_DATA_SIZE,
.param = { [1] = {0x01, 0xac8c},
[6] = {0x06, 0x0017},
[9] = {0x09, 0x724c},
[10] = {0x0a, 0xb610},
[11] = {0x0b, 0xb90d},
[13] = {0x0d, 0xef2a},
[15] = {0x0f, 0x9050},
[16] = {0x10, 0x000c},
[32] = {0x20, 0x70ff},
[34] = {0x22, 0x0013},
[35] = {0x23, 0xdb66},
[38] = {0x26, 0x8609},
[41] = {0x29, 0xff13},
[42] = {0x2a, 0x3070}, },
.check_efuse = true,
.do_toggle = false,
.do_toggle_once = true,
.use_default_parameter = false,
.check_rx_front_end_offset = false,
};
static const struct phy_cfg rtd1319d_phy_cfg = {
.param_size = MAX_USB_PHY_DATA_SIZE,
.param = { [1] = {0x01, 0xac89},
[4] = {0x04, 0xf2f5},
[6] = {0x06, 0x0017},
[9] = {0x09, 0x424c},
[10] = {0x0a, 0x9610},
[11] = {0x0b, 0x9901},
[12] = {0x0c, 0xf000},
[13] = {0x0d, 0xef2a},
[14] = {0x0e, 0x1000},
[15] = {0x0f, 0x9050},
[32] = {0x20, 0x7077},
[35] = {0x23, 0x0b62},
[37] = {0x25, 0x10ec},
[42] = {0x2a, 0x3070}, },
.check_efuse = true,
.do_toggle = false,
.do_toggle_once = true,
.use_default_parameter = false,
.check_rx_front_end_offset = true,
};
static const struct of_device_id usbphy_rtk_dt_match[] = {
{ .compatible = "realtek,rtd1295-usb3phy", .data = &rtd1295_phy_cfg },
{ .compatible = "realtek,rtd1319-usb3phy", .data = &rtd1319_phy_cfg },
{ .compatible = "realtek,rtd1319d-usb3phy", .data = &rtd1319d_phy_cfg },
{ .compatible = "realtek,rtd1619-usb3phy", .data = &rtd1619_phy_cfg },
{ .compatible = "realtek,rtd1619b-usb3phy", .data = &rtd1619b_phy_cfg },
{},
};
MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
static struct platform_driver rtk_usb3phy_driver = {
.probe = rtk_usb3phy_probe,
.remove_new = rtk_usb3phy_remove,
.driver = {
.name = "rtk-usb3phy",
.of_match_table = usbphy_rtk_dt_match,
},
};
module_platform_driver(rtk_usb3phy_driver);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform: rtk-usb3phy");
MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
MODULE_DESCRIPTION("Realtek usb 3.0 phy driver");

View file

@ -1143,7 +1143,7 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
* Only set bonding if the link was not already bonded. This
* avoids the lane adapter to re-enter bonding state.
*/
if (width == TB_LINK_WIDTH_SINGLE) {
if (width == TB_LINK_WIDTH_SINGLE && !tb_is_upstream_port(port)) {
ret = tb_port_set_lane_bonding(port, true);
if (ret)
goto err_lane1;
@ -2880,6 +2880,7 @@ static int tb_switch_lane_bonding_disable(struct tb_switch *sw)
return tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100);
}
/* Note updating sw->link_width done in tb_switch_update_link_attributes() */
static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width)
{
struct tb_port *up, *down, *port;
@ -2919,10 +2920,10 @@ static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width)
return ret;
}
sw->link_width = width;
return 0;
}
/* Note updating sw->link_width done in tb_switch_update_link_attributes() */
static int tb_switch_asym_disable(struct tb_switch *sw)
{
struct tb_port *up, *down;
@ -2957,7 +2958,6 @@ static int tb_switch_asym_disable(struct tb_switch *sw)
return ret;
}
sw->link_width = TB_LINK_WIDTH_DUAL;
return 0;
}

View file

@ -213,7 +213,17 @@ static void tb_add_dp_resources(struct tb_switch *sw)
if (!tb_switch_query_dp_resource(sw, port))
continue;
list_add(&port->list, &tcm->dp_resources);
/*
* If DP IN on device router exist, position it at the
* beginning of the DP resources list, so that it is used
* before DP IN of the host router. This way external GPU(s)
* will be prioritized when pairing DP IN to a DP OUT.
*/
if (tb_route(sw))
list_add(&port->list, &tcm->dp_resources);
else
list_add_tail(&port->list, &tcm->dp_resources);
tb_port_dbg(port, "DP IN resource available\n");
}
}

View file

@ -1529,6 +1529,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
unsigned long flags;
int counter = 0;
local_bh_disable();
spin_lock_irqsave(&pdev->lock, flags);
if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) {
@ -1541,6 +1542,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
cdnsp_died(pdev);
spin_unlock_irqrestore(&pdev->lock, flags);
local_bh_enable();
return IRQ_HANDLED;
}
@ -1557,6 +1559,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
cdnsp_update_erst_dequeue(pdev, event_ring_deq, 1);
spin_unlock_irqrestore(&pdev->lock, flags);
local_bh_enable();
return IRQ_HANDLED;
}

View file

@ -1047,7 +1047,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
dev_notice(ddev, "descriptor type invalid, skip\n");
continue;
goto skip_to_next_descriptor;
}
switch (cap_type) {
@ -1078,6 +1078,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
break;
}
skip_to_next_descriptor:
total_len -= length;
buffer += length;
}

View file

@ -622,29 +622,6 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type,
ret = 0;
}
mutex_unlock(&hub->status_mutex);
/*
* There is no need to lock status_mutex here, because status_mutex
* protects hub->status, and the phy driver only checks the port
* status without changing the status.
*/
if (!ret) {
struct usb_device *hdev = hub->hdev;
/*
* Only roothub will be notified of port state changes,
* since the USB PHY only cares about changes at the next
* level.
*/
if (is_root_hub(hdev)) {
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
if (hcd->usb_phy)
usb_phy_notify_port_status(hcd->usb_phy,
port1 - 1, *status, *change);
}
}
return ret;
}

View file

@ -2015,15 +2015,17 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
{
struct dwc2_qtd *qtd;
struct dwc2_host_chan *chan;
u32 hcint, hcintmsk;
u32 hcint, hcintraw, hcintmsk;
chan = hsotg->hc_ptr_array[chnum];
hcint = dwc2_readl(hsotg, HCINT(chnum));
hcintraw = dwc2_readl(hsotg, HCINT(chnum));
hcintmsk = dwc2_readl(hsotg, HCINTMSK(chnum));
hcint = hcintraw & hcintmsk;
dwc2_writel(hsotg, hcint, HCINT(chnum));
if (!chan) {
dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
dwc2_writel(hsotg, hcint, HCINT(chnum));
return;
}
@ -2032,11 +2034,9 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
chnum);
dev_vdbg(hsotg->dev,
" hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
hcint, hcintmsk, hcint & hcintmsk);
hcintraw, hcintmsk, hcint);
}
dwc2_writel(hsotg, hcint, HCINT(chnum));
/*
* If we got an interrupt after someone called
* dwc2_hcd_endpoint_disable() we don't want to crash below
@ -2046,8 +2046,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
return;
}
chan->hcint = hcint;
hcint &= hcintmsk;
chan->hcint = hcintraw;
/*
* If the channel was halted due to a dequeue, the qtd list might

View file

@ -2034,6 +2034,8 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_put(dev);
dma_set_max_seg_size(dev, UINT_MAX);
return 0;
err_exit_debugfs:

View file

@ -505,6 +505,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL;
mode = DWC3_GCTL_PRTCAP_DEVICE;
}
dwc3_set_mode(dwc, mode);
dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
dwc3_role_switch.set = dwc3_usb_role_switch_set;
@ -526,7 +527,6 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
}
}
dwc3_set_mode(dwc, mode);
return 0;
}
#else

View file

@ -546,10 +546,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
pdata ? pdata->hs_phy_irq_index : -1);
if (irq > 0) {
/* Keep wakeup interrupts disabled until suspend */
irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 HS", qcom);
if (ret) {
dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret);
@ -561,10 +560,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq",
pdata ? pdata->dp_hs_phy_irq_index : -1);
if (irq > 0) {
irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 DP_HS", qcom);
if (ret) {
dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret);
@ -576,10 +574,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq",
pdata ? pdata->dm_hs_phy_irq_index : -1);
if (irq > 0) {
irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 DM_HS", qcom);
if (ret) {
dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret);
@ -591,10 +588,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq",
pdata ? pdata->ss_phy_irq_index : -1);
if (irq > 0) {
irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 SS", qcom);
if (ret) {
dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret);
@ -758,6 +754,7 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
if (!qcom->dwc3) {
ret = -ENODEV;
dev_err(dev, "failed to get dwc3 platform device\n");
of_platform_depopulate(dev);
}
node_put:
@ -766,9 +763,9 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
return ret;
}
static struct platform_device *
dwc3_qcom_create_urs_usb_platdev(struct device *dev)
static struct platform_device *dwc3_qcom_create_urs_usb_platdev(struct device *dev)
{
struct platform_device *urs_usb = NULL;
struct fwnode_handle *fwh;
struct acpi_device *adev;
char name[8];
@ -788,9 +785,26 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
adev = to_acpi_device_node(fwh);
if (!adev)
return NULL;
goto err_put_handle;
return acpi_create_platform_device(adev, NULL);
urs_usb = acpi_create_platform_device(adev, NULL);
if (IS_ERR_OR_NULL(urs_usb))
goto err_put_handle;
return urs_usb;
err_put_handle:
fwnode_handle_put(fwh);
return urs_usb;
}
static void dwc3_qcom_destroy_urs_usb_platdev(struct platform_device *urs_usb)
{
struct fwnode_handle *fwh = urs_usb->dev.fwnode;
platform_device_unregister(urs_usb);
fwnode_handle_put(fwh);
}
static int dwc3_qcom_probe(struct platform_device *pdev)
@ -874,13 +888,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
if (IS_ERR(qcom->qscratch_base)) {
ret = PTR_ERR(qcom->qscratch_base);
goto clk_disable;
goto free_urs;
}
ret = dwc3_qcom_setup_irq(pdev);
if (ret) {
dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
goto clk_disable;
goto free_urs;
}
/*
@ -899,7 +913,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
goto depopulate;
goto free_urs;
}
ret = dwc3_qcom_interconnect_init(qcom);
@ -931,10 +945,16 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
interconnect_exit:
dwc3_qcom_interconnect_exit(qcom);
depopulate:
if (np)
if (np) {
of_platform_depopulate(&pdev->dev);
else
platform_device_put(pdev);
} else {
device_remove_software_node(&qcom->dwc3->dev);
platform_device_del(qcom->dwc3);
}
platform_device_put(qcom->dwc3);
free_urs:
if (qcom->urs_usb)
dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
clk_disable:
for (i = qcom->num_clocks - 1; i >= 0; i--) {
clk_disable_unprepare(qcom->clks[i]);
@ -953,11 +973,16 @@ static void dwc3_qcom_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int i;
device_remove_software_node(&qcom->dwc3->dev);
if (np)
if (np) {
of_platform_depopulate(&pdev->dev);
else
platform_device_put(pdev);
} else {
device_remove_software_node(&qcom->dwc3->dev);
platform_device_del(qcom->dwc3);
}
platform_device_put(qcom->dwc3);
if (qcom->urs_usb)
dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
for (i = qcom->num_clocks - 1; i >= 0; i--) {
clk_disable_unprepare(qcom->clks[i]);

View file

@ -183,10 +183,13 @@ static enum usb_device_speed __get_dwc3_maximum_speed(struct device_node *np)
ret = of_property_read_string(dwc3_np, "maximum-speed", &maximum_speed);
if (ret < 0)
return USB_SPEED_UNKNOWN;
goto out;
ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
out:
of_node_put(dwc3_np);
return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
}
@ -339,6 +342,9 @@ static int dwc3_rtk_probe_dwc3_core(struct dwc3_rtk *rtk)
switch_usb2_role(rtk, rtk->cur_role);
platform_device_put(dwc3_pdev);
of_node_put(dwc3_node);
return 0;
err_pdev_put:

View file

@ -650,9 +650,8 @@ static int check_isoc_ss_overlap(struct mu3h_sch_ep_info *sch_ep, u32 offset)
if (sch_ep->ep_type == ISOC_OUT_EP) {
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + j + CS_OFFSET);
/* use cs to indicate existence of in-ss @(base+j) */
if (tt->fs_bus_bw_in[k])
k = XHCI_MTK_BW_INDEX(base + j);
if (tt->in_ss_cnt[k])
return -ESCH_SS_OVERLAP;
}
} else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
@ -769,6 +768,14 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j];
}
}
if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
k = XHCI_MTK_BW_INDEX(base);
if (used)
tt->in_ss_cnt[k]++;
else
tt->in_ss_cnt[k]--;
}
}
if (used)

View file

@ -38,6 +38,7 @@
* @fs_bus_bw_in: save bandwidth used by FS/LS IN eps in each uframes
* @ls_bus_bw: save bandwidth used by LS eps in each uframes
* @fs_frame_bw: save bandwidth used by FS/LS eps in each FS frames
* @in_ss_cnt: the count of Start-Split for IN eps
* @ep_list: Endpoints using this TT
*/
struct mu3h_sch_tt {
@ -45,6 +46,7 @@ struct mu3h_sch_tt {
u16 fs_bus_bw_in[XHCI_MTK_MAX_ESIT];
u8 ls_bus_bw[XHCI_MTK_MAX_ESIT];
u16 fs_frame_bw[XHCI_MTK_FRAMES_CNT];
u8 in_ss_cnt[XHCI_MTK_MAX_ESIT];
struct list_head ep_list;
};

View file

@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/usb/phy.h>
#include <linux/slab.h>
@ -148,7 +149,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
int ret;
int irq;
struct xhci_plat_priv *priv = NULL;
bool of_match;
if (usb_disabled())
return -ENODEV;
@ -253,16 +254,23 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
&xhci->imod_interval);
}
hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
if (IS_ERR(hcd->usb_phy)) {
ret = PTR_ERR(hcd->usb_phy);
if (ret == -EPROBE_DEFER)
goto disable_clk;
hcd->usb_phy = NULL;
} else {
ret = usb_phy_init(hcd->usb_phy);
if (ret)
goto disable_clk;
/*
* Drivers such as dwc3 manages PHYs themself (and rely on driver name
* matching for the xhci platform device).
*/
of_match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
if (of_match) {
hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
if (IS_ERR(hcd->usb_phy)) {
ret = PTR_ERR(hcd->usb_phy);
if (ret == -EPROBE_DEFER)
goto disable_clk;
hcd->usb_phy = NULL;
} else {
ret = usb_phy_init(hcd->usb_phy);
if (ret)
goto disable_clk;
}
}
hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
@ -285,15 +293,17 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
goto dealloc_usb2_hcd;
}
xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
"usb-phy", 1);
if (IS_ERR(xhci->shared_hcd->usb_phy)) {
xhci->shared_hcd->usb_phy = NULL;
} else {
ret = usb_phy_init(xhci->shared_hcd->usb_phy);
if (ret)
dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
__func__, ret);
if (of_match) {
xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
"usb-phy", 1);
if (IS_ERR(xhci->shared_hcd->usb_phy)) {
xhci->shared_hcd->usb_phy = NULL;
} else {
ret = usb_phy_init(xhci->shared_hcd->usb_phy);
if (ret)
dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
__func__, ret);
}
}
xhci->shared_hcd->tpl_support = hcd->tpl_support;

View file

@ -432,6 +432,8 @@ static const struct usb_device_id onboard_hub_id_table[] = {
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2744) }, /* USB5744 USB 2.0 */
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x5744) }, /* USB5744 USB 3.0 */
{ USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */
{ USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */
{ USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */

View file

@ -16,6 +16,11 @@ static const struct onboard_hub_pdata microchip_usb424_data = {
.num_supplies = 1,
};
static const struct onboard_hub_pdata microchip_usb5744_data = {
.reset_us = 0,
.num_supplies = 2,
};
static const struct onboard_hub_pdata realtek_rts5411_data = {
.reset_us = 0,
.num_supplies = 1,
@ -50,6 +55,8 @@ static const struct of_device_id onboard_hub_match[] = {
{ .compatible = "usb424,2412", .data = &microchip_usb424_data, },
{ .compatible = "usb424,2514", .data = &microchip_usb424_data, },
{ .compatible = "usb424,2517", .data = &microchip_usb424_data, },
{ .compatible = "usb424,2744", .data = &microchip_usb5744_data, },
{ .compatible = "usb424,5744", .data = &microchip_usb5744_data, },
{ .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
{ .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
{ .compatible = "usb4b4,6504", .data = &cypress_hx3_data, },

View file

@ -457,8 +457,8 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
u64 adr, u8 id)
{
struct ljca_match_ids_walk_data wd = { 0 };
struct acpi_device *parent, *adev;
struct device *dev = adap->dev;
struct acpi_device *parent;
char uid[4];
parent = ACPI_COMPANION(dev);
@ -466,17 +466,7 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
return;
/*
* get auxdev ACPI handle from the ACPI device directly
* under the parent that matches _ADR.
*/
adev = acpi_find_child_device(parent, adr, false);
if (adev) {
ACPI_COMPANION_SET(&auxdev->dev, adev);
return;
}
/*
* _ADR is a grey area in the ACPI specification, some
* Currently LJCA hw doesn't use _ADR instead the shipped
* platforms use _HID to distinguish children devices.
*/
switch (adr) {
@ -656,10 +646,11 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap)
unsigned int i;
int ret;
/* Not all LJCA chips implement SPI, a timeout reading the descriptors is normal */
ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf,
sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS);
if (ret < 0)
return ret;
return (ret == -ETIMEDOUT) ? 0 : ret;
/* check firmware response */
desc = (struct ljca_spi_descriptor *)buf;

View file

@ -203,8 +203,8 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5829E_ESIM 0x81e4
#define DELL_PRODUCT_5829E 0x81e6
#define DELL_PRODUCT_FM101R 0x8213
#define DELL_PRODUCT_FM101R_ESIM 0x8215
#define DELL_PRODUCT_FM101R_ESIM 0x8213
#define DELL_PRODUCT_FM101R 0x8215
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
@ -609,6 +609,8 @@ static void option_instat_callback(struct urb *urb);
#define UNISOC_VENDOR_ID 0x1782
/* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */
#define TOZED_PRODUCT_LT70C 0x4055
/* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
#define LUAT_PRODUCT_AIR720U 0x4e00
/* Device flags */
@ -1546,7 +1548,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
.driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff),
.driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
.driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) },
@ -2249,6 +2252,7 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
{ USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x0001, 0xff, 0xff, 0xff) }, /* Fibocom L716-EU (ECM/RNDIS mode) */
{ USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
.driver_info = RSVD(4) | RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
@ -2271,6 +2275,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);

View file

@ -4273,7 +4273,8 @@ static void run_state_machine(struct tcpm_port *port)
current_lim = PD_P_SNK_STDBY_MW / 5;
tcpm_set_current_limit(port, current_lim, 5000);
/* Not sink vbus if operational current is 0mA */
tcpm_set_charge(port, !!pdo_max_current(port->snk_pdo[0]));
tcpm_set_charge(port, !port->pd_supported ||
pdo_max_current(port->snk_pdo[0]));
if (!port->pd_supported)
tcpm_set_state(port, SNK_READY, 0);
@ -5391,6 +5392,15 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port)
if (port->bist_request == BDO_MODE_TESTDATA && port->tcpc->set_bist_data)
port->tcpc->set_bist_data(port->tcpc, false);
switch (port->state) {
case ERROR_RECOVERY:
case PORT_RESET:
case PORT_RESET_WAIT_OFF:
return;
default:
break;
}
if (port->ams != NONE_AMS)
port->ams = NONE_AMS;
if (port->hard_reset_count < PD_N_HARD_RESET_COUNT)

View file

@ -968,16 +968,17 @@ static int tps25750_start_patch_burst_mode(struct tps6598x *tps)
ret = of_property_match_string(np, "reg-names", "patch-address");
if (ret < 0) {
dev_err(tps->dev, "failed to get patch-address %d\n", ret);
return ret;
goto release_fw;
}
ret = of_property_read_u32_index(np, "reg", ret, &addr);
if (ret)
return ret;
goto release_fw;
if (addr == 0 || (addr >= 0x20 && addr <= 0x23)) {
dev_err(tps->dev, "wrong patch address %u\n", addr);
return -EINVAL;
ret = -EINVAL;
goto release_fw;
}
bpms_data.addr = (u8)addr;
@ -1226,7 +1227,10 @@ static int tps6598x_probe(struct i2c_client *client)
TPS_REG_INT_PLUG_EVENT;
}
tps->data = device_get_match_data(tps->dev);
if (dev_fwnode(tps->dev))
tps->data = device_get_match_data(tps->dev);
else
tps->data = i2c_get_match_data(client);
if (!tps->data)
return -EINVAL;
@ -1425,7 +1429,7 @@ static const struct of_device_id tps6598x_of_match[] = {
MODULE_DEVICE_TABLE(of, tps6598x_of_match);
static const struct i2c_device_id tps6598x_id[] = {
{ "tps6598x" },
{ "tps6598x", (kernel_ulong_t)&tps6598x_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, tps6598x_id);

View file

@ -144,10 +144,6 @@ struct usb_phy {
*/
int (*set_wakeup)(struct usb_phy *x, bool enabled);
/* notify phy port status change */
int (*notify_port_status)(struct usb_phy *x, int port,
u16 portstatus, u16 portchange);
/* notify phy connect status change */
int (*notify_connect)(struct usb_phy *x,
enum usb_device_speed speed);
@ -320,15 +316,6 @@ usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
return 0;
}
static inline int
usb_phy_notify_port_status(struct usb_phy *x, int port, u16 portstatus, u16 portchange)
{
if (x && x->notify_port_status)
return x->notify_port_status(x, port, portstatus, portchange);
else
return 0;
}
static inline int
usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
{