summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2022-04-21 11:16:09 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2022-04-21 11:16:09 +0200
commit4811863eae2d1e710862e10d7171edbe8041056f (patch)
tree8899ceeff211b381ec7f08e2dc6c8a3d44f4a1e7 /drivers
parent7a942b81e4d10b4f729c19b09b5d330bfeb6ba0e (diff)
parentaaac1c35ed14c81a8ffc93874f8b004deae9e172 (diff)
downloadbarebox-4811863eae2d1e710862e10d7171edbe8041056f.tar.gz
barebox-4811863eae2d1e710862e10d7171edbe8041056f.tar.xz
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ide-sff.c2
-rw-r--r--drivers/gpio/gpio-clps711x.c10
-rw-r--r--drivers/gpio/gpiolib.c26
-rw-r--r--drivers/mci/mci_spi.c31
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c2
-rw-r--r--drivers/net/designware_eqos.c14
-rw-r--r--drivers/net/phy/Kconfig6
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/dp83td510.c45
-rw-r--r--drivers/net/phy/mv88e6xxx/chip.c28
-rw-r--r--drivers/net/phy/mv88e6xxx/chip.h1
-rw-r--r--drivers/net/phy/mv88e6xxx/port.c12
-rw-r--r--drivers/net/phy/mv88e6xxx/port.h2
-rw-r--r--drivers/net/phy/phy.c13
-rw-r--r--drivers/usb/host/xhci-ring.c29
-rw-r--r--drivers/usb/host/xhci.c17
-rw-r--r--drivers/usb/host/xhci.h8
17 files changed, 189 insertions, 58 deletions
diff --git a/drivers/ata/ide-sff.c b/drivers/ata/ide-sff.c
index 7884b62bab..69055e0585 100644
--- a/drivers/ata/ide-sff.c
+++ b/drivers/ata/ide-sff.c
@@ -96,7 +96,7 @@ static int ata_wait_busy(struct ide_port *ide, unsigned timeout)
{
uint8_t status;
uint64_t start = get_time_ns();
- uint64_t toffs = timeout * 1000 * 1000;
+ uint64_t toffs = timeout * MSECOND;
do {
status = ata_rd_status(ide);
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
index 67bce79bc3..a1965b33e4 100644
--- a/drivers/gpio/gpio-clps711x.c
+++ b/drivers/gpio/gpio-clps711x.c
@@ -25,17 +25,15 @@ static int clps711x_gpio_probe(struct device_d *dev)
return PTR_ERR(iores);
dat = IOMEM(iores->start);
+ iores = dev_request_mem_resource(dev, 1);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
switch (id) {
case 3:
- iores = dev_request_mem_resource(dev, 1);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
dir_inv = IOMEM(iores->start);
break;
default:
- iores = dev_request_mem_resource(dev, 1);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
dir = IOMEM(iores->start);
break;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f709d11f75..c9b33bcd6c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -414,22 +414,19 @@ free_array:
}
EXPORT_SYMBOL(gpio_array_to_id);
-static int gpiochip_find_base(int start, int ngpio)
+static int gpiochip_find_base(int ngpio)
{
int i;
int spare = 0;
int base = -ENOSPC;
- if (start < 0)
- start = 0;
-
- for (i = start; i < ARCH_NR_GPIOS; i++) {
+ for (i = ARCH_NR_GPIOS - 1; i >= 0; i--) {
struct gpio_chip *chip = gpio_desc[i].chip;
if (!chip) {
spare++;
if (spare == ngpio) {
- base = i + 1 - ngpio;
+ base = i;
break;
}
} else {
@@ -614,14 +611,17 @@ int gpiochip_add(struct gpio_chip *chip)
{
int base, i;
- base = gpiochip_find_base(chip->base, chip->ngpio);
- if (base < 0)
- return base;
-
- if (chip->base >= 0 && chip->base != base)
- return -EBUSY;
+ if (chip->base >= 0) {
+ for (i = 0; i < chip->ngpio; i++) {
+ if (gpio_desc[chip->base + i].chip)
+ return -EBUSY;
+ }
+ } else {
+ chip->base = gpiochip_find_base(chip->ngpio);
+ if (chip->base < 0)
+ return -ENOSPC;
+ }
- chip->base = base;
list_add_tail(&chip->list, &chip_list);
diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c
index ed3ddf890f..6ae2824edd 100644
--- a/drivers/mci/mci_spi.c
+++ b/drivers/mci/mci_spi.c
@@ -18,6 +18,8 @@
#include <mci.h>
#include <crc.h>
#include <crc7.h>
+#include <of.h>
+#include <gpiod.h>
#define to_spi_host(mci) container_of(mci, struct mmc_spi_host, mci)
#define spi_setup(spi) spi->master->setup(spi)
@@ -47,6 +49,7 @@ struct mmc_spi_host {
struct mci_host mci;
struct spi_device *spi;
struct device_d *dev;
+ int detect_pin;
/* for bulk data transfers */
struct spi_transfer t_tx;
@@ -351,8 +354,23 @@ static int mmc_spi_init(struct mci_host *mci, struct device_d *mci_dev)
return 0;
}
+static int spi_mci_card_present(struct mci_host *mci)
+{
+ struct mmc_spi_host *host = to_spi_host(mci);
+ int ret;
+
+ /* No gpio, assume card is present */
+ if (!gpio_is_valid(host->detect_pin))
+ return 1;
+
+ ret = gpio_get_value(host->detect_pin);
+
+ return ret == 0 ? 1 : 0;
+}
+
static int spi_mci_probe(struct device_d *dev)
{
+ struct device_node *np = dev_of_node(dev);
struct spi_device *spi = (struct spi_device *)dev->type_data;
struct mmc_spi_host *host;
void *ones;
@@ -362,6 +380,7 @@ static int spi_mci_probe(struct device_d *dev)
host->mci.send_cmd = mmc_spi_request;
host->mci.set_ios = mmc_spi_set_ios;
host->mci.init = mmc_spi_init;
+ host->mci.card_present = spi_mci_card_present;
host->mci.hw_dev = dev;
/* MMC and SD specs only seem to care that sampling is on the
@@ -415,14 +434,26 @@ static int spi_mci_probe(struct device_d *dev)
host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
host->mci.host_caps = MMC_CAP_SPI;
+ host->detect_pin = -EINVAL;
+
+ if (np) {
+ host->mci.devname = xstrdup(of_alias_get(np));
+ host->detect_pin = gpiod_get(dev, NULL, GPIOD_IN);
+ }
mci_register(&host->mci);
return 0;
}
+static __maybe_unused struct of_device_id spi_mci_compatible[] = {
+ { .compatible = "mmc-spi-slot" },
+ { /* sentinel */ }
+};
+
static struct driver_d spi_mci_driver = {
.name = "spi_mci",
.probe = spi_mci_probe,
+ .of_compatible = DRV_OF_COMPAT(spi_mci_compatible),
};
device_spi_driver(spi_mci_driver);
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index cf532b1399..0ed7fd3d04 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -697,6 +697,8 @@ static const struct spi_device_id spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "is25lq128", INFO(0x9d6018, 0, 64 * 1024, 256, 0) },
/* Macronix */
diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
index 8d2a21c220..6b372e4274 100644
--- a/drivers/net/designware_eqos.c
+++ b/drivers/net/designware_eqos.c
@@ -112,6 +112,8 @@ struct eqos_mtl_regs {
#define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f
#define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7)
#define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5)
+#define EQOS_MTL_RXQ0_OPERATION_MODE_FEP BIT(4)
+#define EQOS_MTL_RXQ0_OPERATION_MODE_FUP BIT(3)
#define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16
#define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff
@@ -415,9 +417,11 @@ static int eqos_start(struct eth_device *edev)
/* Before we reset the mac, we must insure the PHY is not powered down
* as the dw controller needs all clock domains to be running, including
* the PHY clock, to come out of a mac reset. */
- ret = phy_resume(edev->phydev);
- if (ret)
- return ret;
+ if (edev->phydev) {
+ ret = phy_resume(edev->phydev);
+ if (ret)
+ return ret;
+ }
/* Configure MTL */
@@ -433,7 +437,9 @@ static int eqos_start(struct eth_device *edev)
/* Enable Store and Forward mode for RX, since no jumbo frame */
setbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
- EQOS_MTL_RXQ0_OPERATION_MODE_RSF);
+ EQOS_MTL_RXQ0_OPERATION_MODE_RSF |
+ EQOS_MTL_RXQ0_OPERATION_MODE_FEP |
+ EQOS_MTL_RXQ0_OPERATION_MODE_FUP);
/* Transmit/Receive queue fifo size; use all RAM for 1 queue */
val = readl(&eqos->mac_regs->hw_feature1);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 9f74335443..cd20e1de27 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -29,6 +29,12 @@ config DP83867_PHY
help
Currently supports the DP83867 PHY.
+config DP83TD510_PHY
+ tristate "Texas Instruments DP83TD510 Ethernet 10Base-T1L PHY"
+ help
+ Support for the DP83TD510 Ethernet 10Base-T1L PHY. This PHY supports
+ a 10M single pair Ethernet connection for up to 1000 meter cable.
+
config LXT_PHY
bool "Driver for the Intel LXT PHYs"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 54b83e06dd..83f46f11d3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -17,4 +17,5 @@ obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_DP83867_PHY) += dp83867.o
+obj-$(CONFIG_DP83TD510_PHY) += dp83td510.o
diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c
new file mode 100644
index 0000000000..44c551e795
--- /dev/null
+++ b/drivers/net/phy/dp83td510.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <common.h>
+#include <linux/phy.h>
+
+#define DP83TD510E_PHY_ID 0x20000181
+
+#define DP83TD510E_PHY_STS 0x10
+#define DP83TD510E_LINK_STATUS BIT(0)
+
+static int dp83td510_read_status(struct phy_device *phydev)
+{
+ u16 phy_sts;
+
+ phy_sts = phy_read(phydev, DP83TD510E_PHY_STS);
+
+ phydev->link = !!(phy_sts & DP83TD510E_LINK_STATUS);
+ if (phydev->link) {
+ phydev->duplex = DUPLEX_FULL;
+ phydev->speed = SPEED_10;
+ } else {
+ phydev->speed = SPEED_UNKNOWN;
+ phydev->duplex = DUPLEX_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static int dp83td510_config_init(struct phy_device *phydev)
+{
+ phydev->supported = SUPPORTED_10baseT_Full | SUPPORTED_Autoneg;
+ phydev->advertising = SUPPORTED_10baseT_Full | SUPPORTED_Autoneg;
+
+ return 0;
+}
+
+static struct phy_driver dp83td510_driver[] = {
+ {
+ PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID),
+ .drv.name = "TI DP83TD510E",
+ .read_status = dp83td510_read_status,
+ .config_init = dp83td510_config_init,
+ }
+};
+device_phy_drivers(dp83td510_driver);
diff --git a/drivers/net/phy/mv88e6xxx/chip.c b/drivers/net/phy/mv88e6xxx/chip.c
index ae59d134e7..a7d707095b 100644
--- a/drivers/net/phy/mv88e6xxx/chip.c
+++ b/drivers/net/phy/mv88e6xxx/chip.c
@@ -36,6 +36,7 @@ enum mv88e6xxx_model {
MV88E6190X,
MV88E6191,
MV88E6240,
+ MV88E6250,
MV88E6290,
MV88E6320,
MV88E6321,
@@ -224,6 +225,18 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.port_link_state = mv88e6352_port_link_state,
};
+static const struct mv88e6xxx_ops mv88e6250_ops = {
+ /* MV88E6XXX_FAMILY_6250 */
+ .get_eeprom = mv88e6xxx_g2_get_eeprom16,
+ .set_eeprom = mv88e6xxx_g2_set_eeprom16,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6250_port_set_speed,
+};
+
static const struct mv88e6xxx_ops mv88e6290_ops = {
/* MV88E6XXX_FAMILY_6390 */
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
@@ -525,6 +538,17 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ops = &mv88e6240_ops,
},
+ [MV88E6250] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6250",
+ .num_ports = 7,
+ .port_base_addr = 0x08,
+ .global1_addr = 0xf,
+ .global2_addr = 0x7,
+ .ops = &mv88e6250_ops,
+ },
+
[MV88E6290] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
.family = MV88E6XXX_FAMILY_6390,
@@ -932,6 +956,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
.data = &mv88e6xxx_table[MV88E6085],
},
{
+ .compatible = "marvell,mv88e6250",
+ .data = &mv88e6xxx_table[MV88E6250],
+ },
+ {
.compatible = "marvell,mv88e6190",
.data = &mv88e6xxx_table[MV88E6190],
},
diff --git a/drivers/net/phy/mv88e6xxx/chip.h b/drivers/net/phy/mv88e6xxx/chip.h
index 12037ca95c..30fdac9a9f 100644
--- a/drivers/net/phy/mv88e6xxx/chip.h
+++ b/drivers/net/phy/mv88e6xxx/chip.h
@@ -19,6 +19,7 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
+ MV88E6XXX_FAMILY_6250, /* 6250 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
diff --git a/drivers/net/phy/mv88e6xxx/port.c b/drivers/net/phy/mv88e6xxx/port.c
index 79694e5237..93a789e658 100644
--- a/drivers/net/phy/mv88e6xxx/port.c
+++ b/drivers/net/phy/mv88e6xxx/port.c
@@ -277,6 +277,18 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
}
+/* Support 10, 100 (e.g. 88E6250 family) */
+int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+ if (speed == SPEED_MAX)
+ speed = 100;
+
+ if (speed > 100)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
diff --git a/drivers/net/phy/mv88e6xxx/port.h b/drivers/net/phy/mv88e6xxx/port.h
index f47f392b87..4bc5072948 100644
--- a/drivers/net/phy/mv88e6xxx/port.h
+++ b/drivers/net/phy/mv88e6xxx/port.h
@@ -90,6 +90,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400
@@ -121,6 +122,7 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup);
int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 85cdd7862f..adff9dadd1 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -54,6 +54,13 @@ int phy_update_status(struct phy_device *phydev)
return ret;
}
+ /*
+ * If the phy is a fixed-link, set it to active state to trigger
+ * MAC configuration
+ */
+ if (!phydev->bus && !phydev->link)
+ phydev->link = 1;
+
if (phydev->speed == oldspeed && phydev->duplex == oldduplex &&
phydev->link == oldlink)
return 0;
@@ -311,7 +318,7 @@ struct phy_device *of_phy_register_fixed_link(struct device_node *np,
phydev->dev.parent = &edev->dev;
phydev->registered = 1;
- phydev->link = 1;
+ phydev->link = 0;
if (of_property_read_u32(np, "speed", &phydev->speed))
return NULL;
@@ -401,10 +408,6 @@ static int phy_device_attach(struct phy_device *phy, struct eth_device *edev,
phy->adjust_link = adjust_link;
- /* If the phy is a fixed-link, then call adjust_link directly */
- if (!phy->bus && adjust_link)
- adjust_link(edev);
-
return 0;
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index fe432952ec..60764222af 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -436,7 +436,8 @@ static int event_ready(struct xhci_ctrl *ctrl)
* @param expected TRB type expected from Event TRB
* @return pointer to event trb
*/
-union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
+union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected,
+ unsigned int timeout_ms)
{
trb_type type;
uint64_t start = get_time_ns();
@@ -460,16 +461,8 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
BUG_ON(GET_COMP_CODE(
le32_to_cpu(event->generic.field[2])) !=
COMP_SUCCESS);
- else
- dev_err(ctrl->dev, "Unexpected XHCI event TRB, skipping... "
- "(%08x %08x %08x %08x)\n",
- le32_to_cpu(event->generic.field[0]),
- le32_to_cpu(event->generic.field[1]),
- le32_to_cpu(event->generic.field[2]),
- le32_to_cpu(event->generic.field[3]));
-
xhci_acknowledge_event(ctrl);
- } while (!is_timeout_non_interruptible(start, 5 * SECOND));
+ } while (!is_timeout_non_interruptible(start, timeout_ms * MSECOND));
if (expected == TRB_TRANSFER)
return NULL;
@@ -495,7 +488,7 @@ static void abort_td(struct usb_device *udev, int ep_index)
xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING);
- event = xhci_wait_for_event(ctrl, TRB_TRANSFER);
+ event = xhci_wait_for_event(ctrl, TRB_TRANSFER, XHCI_TIMEOUT_DEFAULT);
field = le32_to_cpu(event->trans_event.flags);
BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
BUG_ON(TRB_TO_EP_INDEX(field) != ep_index);
@@ -503,7 +496,7 @@ static void abort_td(struct usb_device *udev, int ep_index)
!= COMP_STOP)));
xhci_acknowledge_event(ctrl);
- event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
event->event_cmd.status)) != COMP_SUCCESS);
@@ -511,7 +504,7 @@ static void abort_td(struct usb_device *udev, int ep_index)
xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue |
ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ);
- event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
event->event_cmd.status)) != COMP_SUCCESS);
@@ -557,7 +550,7 @@ static void record_transfer_result(struct usb_device *udev,
* @return returns 0 if successful else -1 on failure
*/
int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
- int length, void *buffer)
+ int length, void *buffer, unsigned int timeout_ms)
{
int num_trbs = 0;
struct xhci_generic_trb *start_trb;
@@ -726,7 +719,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
giveback_first_trb(udev, ep_index, start_cycle, start_trb);
- event = xhci_wait_for_event(ctrl, TRB_TRANSFER);
+ event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms);
if (!event) {
dev_dbg(&udev->dev, "XHCI bulk transfer timed out, aborting...\n");
abort_td(udev, ep_index);
@@ -767,7 +760,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
*/
int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
struct devrequest *req, int length,
- void *buffer)
+ void *buffer, unsigned int timeout_ms)
{
int ret;
int start_cycle;
@@ -936,7 +929,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
giveback_first_trb(udev, ep_index, start_cycle, start_trb);
- event = xhci_wait_for_event(ctrl, TRB_TRANSFER);
+ event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms);
if (!event)
goto abort;
field = le32_to_cpu(event->trans_event.flags);
@@ -959,7 +952,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))
== COMP_SHORT_TX) {
/* Short data stage, clear up additional status stage event */
- event = xhci_wait_for_event(ctrl, TRB_TRANSFER);
+ event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms);
if (!event)
goto abort;
BUG_ON(TRB_TO_SLOT_ID(field) != slot_id);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 7336a0911a..ce93d345f9 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -443,7 +443,7 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change)
xhci_flush_cache((uintptr_t)in_ctx->bytes, in_ctx->size);
xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0,
ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP);
- event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id);
@@ -629,7 +629,7 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr)
ctrl_ctx->drop_flags = 0;
xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV);
- event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id);
switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) {
@@ -704,7 +704,7 @@ static int _xhci_alloc_device(struct usb_device *udev)
}
xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT);
- event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))
!= COMP_SUCCESS);
@@ -1097,7 +1097,7 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe,
* (at most) one TD. A TD (comprised of sg list entries) can
* take several service intervals to transmit.
*/
- return xhci_bulk_tx(udev, pipe, length, buffer);
+ return xhci_bulk_tx(udev, pipe, length, buffer, 0);
}
/**
@@ -1115,7 +1115,7 @@ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe,
if (usb_pipetype(pipe) != PIPE_BULK)
return -EINVAL;
- return xhci_bulk_tx(udev, pipe, length, buffer);
+ return xhci_bulk_tx(udev, pipe, length, buffer, timeout_ms);
}
/**
@@ -1131,7 +1131,8 @@ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe,
*/
static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
void *buffer, int length,
- struct devrequest *setup, int root_portnr)
+ struct devrequest *setup, int root_portnr,
+ unsigned int timeout_ms)
{
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
int ret = 0;
@@ -1155,7 +1156,7 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
}
}
- return xhci_ctrl_tx(udev, pipe, setup, length, buffer);
+ return xhci_ctrl_tx(udev, pipe, setup, length, buffer, timeout_ms);
}
static int xhci_lowlevel_init(struct xhci_ctrl *ctrl)
@@ -1239,7 +1240,7 @@ static int xhci_submit_control_msg(struct usb_device *udev,
}
return _xhci_submit_control_msg(udev, pipe, buffer, length, setup,
- root_portnr);
+ root_portnr, timeout_ms);
}
static int xhci_submit_bulk_msg(struct usb_device *udev,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 401fa65637..e445438e81 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1247,11 +1247,13 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr,
u32 slot_id, u32 ep_index, trb_type cmd);
void xhci_acknowledge_event(struct xhci_ctrl *ctrl);
-union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected);
+#define XHCI_TIMEOUT_DEFAULT 5000
+union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected,
+ unsigned int timeout_ms);
int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
- int length, void *buffer);
+ int length, void *buffer, unsigned int timeout_ms);
int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
- struct devrequest *req, int length, void *buffer);
+ struct devrequest *req, int length, void *buffer, unsigned int timeout_ms);
int xhci_check_maxpacket(struct usb_device *udev);
void xhci_flush_cache(uintptr_t addr, u32 type_len);
void xhci_inval_cache(uintptr_t addr, u32 type_len);