Merge tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH: "Here is the big set of USB and PHY driver patches for 5.2-rc1 There is the usual set of: - USB gadget updates - PHY driver updates and additions - USB serial driver updates and fixes - typec updates and new chips supported - mtu3 driver updates - xhci driver updates - other tiny driver updates Nothing really interesting, just constant forward progress. All of these have been in linux-next for a while with no reported issues. The usb-gadget and usb-serial trees were merged a bit "late", but both of them had been in linux-next before they got merged here last Friday" * tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (206 commits) USB: serial: f81232: implement break control USB: serial: f81232: add high baud rate support USB: serial: f81232: clear overrun flag USB: serial: f81232: fix interrupt worker not stop usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA usb: dwc3: Fix default lpm_nyet_threshold value usb: dwc3: debug: Print GET_STATUS(device) tracepoint usb: dwc3: Do core validation early on probe usb: dwc3: gadget: Set lpm_capable usb: gadget: atmel: tie wake lock to running clock usb: gadget: atmel: support USB suspend usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask dwc2: gadget: Fix completed transfer size calculation in DDMA usb: dwc2: Set lpm mode parameters depend on HW configuration usb: dwc2: Fix channel disable flow usb: dwc2: Set actual frame number for completed ISOC transfer usb: gadget: do not use __constant_cpu_to_le16 usb: dwc2: gadget: Increase descriptors count for ISOC's usb: introduce usb_ep_type_string() function usb: dwc3: move synchronize_irq() out of the spinlock protected block ...
This commit is contained in:
@@ -727,8 +727,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
|
||||
}
|
||||
ed->speed = (urb->dev->speed == USB_SPEED_LOW) ?
|
||||
FHCI_LOW_SPEED : FHCI_FULL_SPEED;
|
||||
ed->max_pkt_size = usb_maxpacket(urb->dev,
|
||||
urb->pipe, usb_pipeout(urb->pipe));
|
||||
ed->max_pkt_size = usb_endpoint_maxp(&urb->ep->desc);
|
||||
urb->ep->hcpriv = ed;
|
||||
fhci_dbg(fhci, "new ep speed=%d max_pkt_size=%d\n",
|
||||
ed->speed, ed->max_pkt_size);
|
||||
@@ -768,8 +767,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
|
||||
if (urb->transfer_flags & URB_ZERO_PACKET &&
|
||||
urb->transfer_buffer_length > 0 &&
|
||||
((urb->transfer_buffer_length %
|
||||
usb_maxpacket(urb->dev, urb->pipe,
|
||||
usb_pipeout(urb->pipe))) == 0))
|
||||
usb_endpoint_maxp(&urb->ep->desc)) == 0))
|
||||
urb_state = US_BULK0;
|
||||
while (data_len > 4096) {
|
||||
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt,
|
||||
@@ -807,8 +805,8 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
|
||||
break;
|
||||
case FHCI_TF_CTRL:
|
||||
ed->dev_addr = usb_pipedevice(urb->pipe);
|
||||
ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe,
|
||||
usb_pipeout(urb->pipe));
|
||||
ed->max_pkt_size = usb_endpoint_maxp(&urb->ep->desc);
|
||||
|
||||
/* setup stage */
|
||||
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP,
|
||||
USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true);
|
||||
|
@@ -3203,6 +3203,8 @@ static int __init u132_hcd_init(void)
|
||||
return -ENODEV;
|
||||
printk(KERN_INFO "driver %s\n", hcd_name);
|
||||
workqueue = create_singlethread_workqueue("u132");
|
||||
if (!workqueue)
|
||||
return -ENOMEM;
|
||||
retval = platform_driver_register(&u132_platform_driver);
|
||||
if (retval)
|
||||
destroy_workqueue(workqueue);
|
||||
|
@@ -487,8 +487,8 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
|
||||
/* Write 1 to disable the port */
|
||||
writel(port_status | PORT_PE, addr);
|
||||
port_status = readl(addr);
|
||||
xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n",
|
||||
wIndex, port_status);
|
||||
xhci_dbg(xhci, "disable port %d-%d, portsc: 0x%x\n",
|
||||
hcd->self.busnum, wIndex + 1, port_status);
|
||||
}
|
||||
|
||||
static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
|
||||
@@ -537,8 +537,9 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
|
||||
/* Change bits are all write 1 to clear */
|
||||
writel(port_status | status, addr);
|
||||
port_status = readl(addr);
|
||||
xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n",
|
||||
port_change_bit, wIndex, port_status);
|
||||
|
||||
xhci_dbg(xhci, "clear port%d %s change, portsc: 0x%x\n",
|
||||
wIndex + 1, port_change_bit, port_status);
|
||||
}
|
||||
|
||||
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
|
||||
@@ -565,13 +566,16 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
|
||||
rhub = xhci_get_rhub(hcd);
|
||||
port = rhub->ports[index];
|
||||
temp = readl(port->addr);
|
||||
|
||||
xhci_dbg(xhci, "set port power %d-%d %s, portsc: 0x%x\n",
|
||||
hcd->self.busnum, index + 1, on ? "ON" : "OFF", temp);
|
||||
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
|
||||
if (on) {
|
||||
/* Power on */
|
||||
writel(temp | PORT_POWER, port->addr);
|
||||
temp = readl(port->addr);
|
||||
xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n",
|
||||
index, temp);
|
||||
readl(port->addr);
|
||||
} else {
|
||||
/* Power off */
|
||||
writel(temp & ~PORT_POWER, port->addr);
|
||||
@@ -666,12 +670,17 @@ void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
|
||||
u32 link_state)
|
||||
{
|
||||
u32 temp;
|
||||
u32 portsc;
|
||||
|
||||
temp = readl(port->addr);
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
portsc = readl(port->addr);
|
||||
temp = xhci_port_state_to_neutral(portsc);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | link_state;
|
||||
writel(temp, port->addr);
|
||||
|
||||
xhci_dbg(xhci, "Set port %d-%d link state, portsc: 0x%x, write 0x%x",
|
||||
port->rhub->hcd->self.busnum, port->hcd_portnum + 1,
|
||||
portsc, temp);
|
||||
}
|
||||
|
||||
static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
|
||||
@@ -840,7 +849,9 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
|
||||
} else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) {
|
||||
int time_left;
|
||||
|
||||
xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1);
|
||||
xhci_dbg(xhci, "resume USB2 port %d-%d\n",
|
||||
hcd->self.busnum, wIndex + 1);
|
||||
|
||||
bus_state->resume_done[wIndex] = 0;
|
||||
clear_bit(wIndex, &bus_state->resuming_ports);
|
||||
|
||||
@@ -867,9 +878,8 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
|
||||
} else {
|
||||
int port_status = readl(port->addr);
|
||||
|
||||
xhci_warn(xhci, "Port resume %i msec timed out, portsc = 0x%x\n",
|
||||
XHCI_MAX_REXIT_TIMEOUT_MS,
|
||||
port_status);
|
||||
xhci_warn(xhci, "Port resume timed out, port %d-%d: 0x%x\n",
|
||||
hcd->self.busnum, wIndex + 1, port_status);
|
||||
*status |= USB_PORT_STAT_SUSPEND;
|
||||
clear_bit(wIndex, &bus_state->rexit_ports);
|
||||
}
|
||||
@@ -1124,9 +1134,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
if (status == 0xffffffff)
|
||||
goto error;
|
||||
|
||||
xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n",
|
||||
wIndex, temp);
|
||||
xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
|
||||
xhci_dbg(xhci, "Get port status %d-%d read: 0x%x, return 0x%x",
|
||||
hcd->self.busnum, wIndex + 1, temp, status);
|
||||
|
||||
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
|
||||
/* if USB 3.1 extended port status return additional 4 bytes */
|
||||
@@ -1182,7 +1191,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
temp = readl(ports[wIndex]->addr);
|
||||
if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
|
||||
|| (temp & PORT_PLS_MASK) >= XDEV_U3) {
|
||||
xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n");
|
||||
xhci_warn(xhci, "USB core suspending port %d-%d not in U0/U1/U2\n",
|
||||
hcd->self.busnum, wIndex + 1);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@@ -206,19 +206,6 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
|
||||
return xhci_mtk_host_enable(mtk);
|
||||
}
|
||||
|
||||
/* ignore the error if the clock does not exist */
|
||||
static struct clk *optional_clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *opt_clk;
|
||||
|
||||
opt_clk = devm_clk_get(dev, id);
|
||||
/* ignore error number except EPROBE_DEFER */
|
||||
if (IS_ERR(opt_clk) && (PTR_ERR(opt_clk) != -EPROBE_DEFER))
|
||||
opt_clk = NULL;
|
||||
|
||||
return opt_clk;
|
||||
}
|
||||
|
||||
static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)
|
||||
{
|
||||
struct device *dev = mtk->dev;
|
||||
@@ -229,15 +216,15 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)
|
||||
return PTR_ERR(mtk->sys_clk);
|
||||
}
|
||||
|
||||
mtk->ref_clk = optional_clk_get(dev, "ref_ck");
|
||||
mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck");
|
||||
if (IS_ERR(mtk->ref_clk))
|
||||
return PTR_ERR(mtk->ref_clk);
|
||||
|
||||
mtk->mcu_clk = optional_clk_get(dev, "mcu_ck");
|
||||
mtk->mcu_clk = devm_clk_get_optional(dev, "mcu_ck");
|
||||
if (IS_ERR(mtk->mcu_clk))
|
||||
return PTR_ERR(mtk->mcu_clk);
|
||||
|
||||
mtk->dma_clk = optional_clk_get(dev, "dma_ck");
|
||||
mtk->dma_clk = devm_clk_get_optional(dev, "dma_ck");
|
||||
return PTR_ERR_OR_ZERO(mtk->dma_clk);
|
||||
}
|
||||
|
||||
|
@@ -165,8 +165,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
||||
struct xhci_hcd *xhci;
|
||||
struct resource *res;
|
||||
struct usb_hcd *hcd;
|
||||
struct clk *clk;
|
||||
struct clk *reg_clk;
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
@@ -235,31 +233,32 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
||||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = resource_size(res);
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
|
||||
/*
|
||||
* Not all platforms have clks so it is not an error if the
|
||||
* clock do not exist.
|
||||
*/
|
||||
reg_clk = devm_clk_get(&pdev->dev, "reg");
|
||||
if (!IS_ERR(reg_clk)) {
|
||||
ret = clk_prepare_enable(reg_clk);
|
||||
if (ret)
|
||||
goto put_hcd;
|
||||
} else if (PTR_ERR(reg_clk) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
xhci->reg_clk = devm_clk_get_optional(&pdev->dev, "reg");
|
||||
if (IS_ERR(xhci->reg_clk)) {
|
||||
ret = PTR_ERR(xhci->reg_clk);
|
||||
goto put_hcd;
|
||||
}
|
||||
|
||||
clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (!IS_ERR(clk)) {
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
goto disable_reg_clk;
|
||||
} else if (PTR_ERR(clk) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
ret = clk_prepare_enable(xhci->reg_clk);
|
||||
if (ret)
|
||||
goto put_hcd;
|
||||
|
||||
xhci->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
if (IS_ERR(xhci->clk)) {
|
||||
ret = PTR_ERR(xhci->clk);
|
||||
goto disable_reg_clk;
|
||||
}
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
ret = clk_prepare_enable(xhci->clk);
|
||||
if (ret)
|
||||
goto disable_reg_clk;
|
||||
|
||||
priv_match = of_device_get_match_data(&pdev->dev);
|
||||
if (priv_match) {
|
||||
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
|
||||
@@ -271,8 +270,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
||||
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
|
||||
xhci->clk = clk;
|
||||
xhci->reg_clk = reg_clk;
|
||||
xhci->main_hcd = hcd;
|
||||
xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
|
||||
dev_name(&pdev->dev), hcd);
|
||||
@@ -348,10 +345,10 @@ put_usb3_hcd:
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
|
||||
disable_clk:
|
||||
clk_disable_unprepare(clk);
|
||||
clk_disable_unprepare(xhci->clk);
|
||||
|
||||
disable_reg_clk:
|
||||
clk_disable_unprepare(reg_clk);
|
||||
clk_disable_unprepare(xhci->reg_clk);
|
||||
|
||||
put_hcd:
|
||||
usb_put_hcd(hcd);
|
||||
|
@@ -1569,18 +1569,19 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||
"WARN: xHC returned failed port status event\n");
|
||||
|
||||
port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0]));
|
||||
xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
|
||||
|
||||
max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
|
||||
|
||||
if ((port_id <= 0) || (port_id > max_ports)) {
|
||||
xhci_warn(xhci, "Invalid port id %d\n", port_id);
|
||||
xhci_warn(xhci, "Port change event with invalid port ID %d\n",
|
||||
port_id);
|
||||
inc_deq(xhci, xhci->event_ring);
|
||||
return;
|
||||
}
|
||||
|
||||
port = &xhci->hw_ports[port_id - 1];
|
||||
if (!port || !port->rhub || port->hcd_portnum == DUPLICATE_ENTRY) {
|
||||
xhci_warn(xhci, "Event for invalid port %u\n", port_id);
|
||||
xhci_warn(xhci, "Port change event, no port for port ID %u\n",
|
||||
port_id);
|
||||
bogus_port_status = true;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1597,6 +1598,9 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||
hcd_portnum = port->hcd_portnum;
|
||||
portsc = readl(port->addr);
|
||||
|
||||
xhci_dbg(xhci, "Port change event, %d-%d, id %d, portsc: 0x%x\n",
|
||||
hcd->self.busnum, hcd_portnum + 1, port_id, portsc);
|
||||
|
||||
trace_xhci_handle_port_status(hcd_portnum, portsc);
|
||||
|
||||
if (hcd->state == HC_STATE_SUSPENDED) {
|
||||
@@ -3275,6 +3279,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
field |= TRB_IOC;
|
||||
more_trbs_coming = false;
|
||||
td->last_trb = ring->enqueue;
|
||||
|
||||
if (xhci_urb_suitable_for_idt(urb)) {
|
||||
memcpy(&send_addr, urb->transfer_buffer,
|
||||
trb_buff_len);
|
||||
field |= TRB_IDT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only set interrupt on short packet for IN endpoints */
|
||||
@@ -3414,6 +3424,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
if (urb->transfer_buffer_length > 0) {
|
||||
u32 length_field, remainder;
|
||||
|
||||
if (xhci_urb_suitable_for_idt(urb)) {
|
||||
memcpy(&urb->transfer_dma, urb->transfer_buffer,
|
||||
urb->transfer_buffer_length);
|
||||
field |= TRB_IDT;
|
||||
}
|
||||
|
||||
remainder = xhci_td_remainder(xhci, 0,
|
||||
urb->transfer_buffer_length,
|
||||
urb->transfer_buffer_length,
|
||||
|
@@ -161,6 +161,7 @@ struct tegra_xusb_soc {
|
||||
} ports;
|
||||
|
||||
bool scale_ss_clock;
|
||||
bool has_ipfs;
|
||||
};
|
||||
|
||||
struct tegra_xusb {
|
||||
@@ -637,16 +638,18 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void tegra_xusb_ipfs_config(struct tegra_xusb *tegra,
|
||||
struct resource *regs)
|
||||
static void tegra_xusb_config(struct tegra_xusb *tegra,
|
||||
struct resource *regs)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
|
||||
value |= IPFS_EN_FPCI;
|
||||
ipfs_writel(tegra, value, IPFS_XUSB_HOST_CONFIGURATION_0);
|
||||
if (tegra->soc->has_ipfs) {
|
||||
value = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
|
||||
value |= IPFS_EN_FPCI;
|
||||
ipfs_writel(tegra, value, IPFS_XUSB_HOST_CONFIGURATION_0);
|
||||
|
||||
usleep_range(10, 20);
|
||||
usleep_range(10, 20);
|
||||
}
|
||||
|
||||
/* Program BAR0 space */
|
||||
value = fpci_readl(tegra, XUSB_CFG_4);
|
||||
@@ -661,13 +664,15 @@ static void tegra_xusb_ipfs_config(struct tegra_xusb *tegra,
|
||||
value |= XUSB_IO_SPACE_EN | XUSB_MEM_SPACE_EN | XUSB_BUS_MASTER_EN;
|
||||
fpci_writel(tegra, value, XUSB_CFG_1);
|
||||
|
||||
/* Enable interrupt assertion */
|
||||
value = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
|
||||
value |= IPFS_IP_INT_MASK;
|
||||
ipfs_writel(tegra, value, IPFS_XUSB_HOST_INTR_MASK_0);
|
||||
if (tegra->soc->has_ipfs) {
|
||||
/* Enable interrupt assertion */
|
||||
value = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
|
||||
value |= IPFS_IP_INT_MASK;
|
||||
ipfs_writel(tegra, value, IPFS_XUSB_HOST_INTR_MASK_0);
|
||||
|
||||
/* Set hysteresis */
|
||||
ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
|
||||
/* Set hysteresis */
|
||||
ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra_xusb_clk_enable(struct tegra_xusb *tegra)
|
||||
@@ -1015,10 +1020,12 @@ static int tegra_xusb_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(tegra->fpci_base))
|
||||
return PTR_ERR(tegra->fpci_base);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||||
tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(tegra->ipfs_base))
|
||||
return PTR_ERR(tegra->ipfs_base);
|
||||
if (tegra->soc->has_ipfs) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||||
tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(tegra->ipfs_base))
|
||||
return PTR_ERR(tegra->ipfs_base);
|
||||
}
|
||||
|
||||
tegra->xhci_irq = platform_get_irq(pdev, 0);
|
||||
if (tegra->xhci_irq < 0)
|
||||
@@ -1208,7 +1215,7 @@ static int tegra_xusb_probe(struct platform_device *pdev)
|
||||
goto disable_rpm;
|
||||
}
|
||||
|
||||
tegra_xusb_ipfs_config(tegra, regs);
|
||||
tegra_xusb_config(tegra, regs);
|
||||
|
||||
err = tegra_xusb_load_firmware(tegra);
|
||||
if (err < 0) {
|
||||
@@ -1380,6 +1387,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
|
||||
.usb3 = { .offset = 0, .count = 2, },
|
||||
},
|
||||
.scale_ss_clock = true,
|
||||
.has_ipfs = true,
|
||||
};
|
||||
MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
|
||||
|
||||
@@ -1411,12 +1419,38 @@ static const struct tegra_xusb_soc tegra210_soc = {
|
||||
.usb3 = { .offset = 0, .count = 4, },
|
||||
},
|
||||
.scale_ss_clock = false,
|
||||
.has_ipfs = true,
|
||||
};
|
||||
MODULE_FIRMWARE("nvidia/tegra210/xusb.bin");
|
||||
|
||||
static const char * const tegra186_supply_names[] = {
|
||||
};
|
||||
|
||||
static const struct tegra_xusb_phy_type tegra186_phy_types[] = {
|
||||
{ .name = "usb3", .num = 3, },
|
||||
{ .name = "usb2", .num = 3, },
|
||||
{ .name = "hsic", .num = 1, },
|
||||
};
|
||||
|
||||
static const struct tegra_xusb_soc tegra186_soc = {
|
||||
.firmware = "nvidia/tegra186/xusb.bin",
|
||||
.supply_names = tegra186_supply_names,
|
||||
.num_supplies = ARRAY_SIZE(tegra186_supply_names),
|
||||
.phy_types = tegra186_phy_types,
|
||||
.num_types = ARRAY_SIZE(tegra186_phy_types),
|
||||
.ports = {
|
||||
.usb3 = { .offset = 0, .count = 3, },
|
||||
.usb2 = { .offset = 3, .count = 3, },
|
||||
.hsic = { .offset = 6, .count = 1, },
|
||||
},
|
||||
.scale_ss_clock = false,
|
||||
.has_ipfs = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_xusb_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-xusb", .data = &tegra124_soc },
|
||||
{ .compatible = "nvidia,tegra210-xusb", .data = &tegra210_soc },
|
||||
{ .compatible = "nvidia,tegra186-xusb", .data = &tegra186_soc },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);
|
||||
|
@@ -366,6 +366,11 @@ DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_config_ep,
|
||||
TP_ARGS(ctx)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(xhci_log_ep_ctx, xhci_add_endpoint,
|
||||
TP_PROTO(struct xhci_ep_ctx *ctx),
|
||||
TP_ARGS(ctx)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
|
||||
TP_PROTO(struct xhci_slot_ctx *ctx),
|
||||
TP_ARGS(ctx),
|
||||
@@ -432,6 +437,31 @@ DEFINE_EVENT(xhci_log_slot_ctx, xhci_configure_endpoint,
|
||||
TP_ARGS(ctx)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(xhci_log_ctrl_ctx,
|
||||
TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx),
|
||||
TP_ARGS(ctrl_ctx),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, drop)
|
||||
__field(u32, add)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->drop = le32_to_cpu(ctrl_ctx->drop_flags);
|
||||
__entry->add = le32_to_cpu(ctrl_ctx->add_flags);
|
||||
),
|
||||
TP_printk("%s", xhci_decode_ctrl_ctx(__entry->drop, __entry->add)
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(xhci_log_ctrl_ctx, xhci_address_ctrl_ctx,
|
||||
TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx),
|
||||
TP_ARGS(ctrl_ctx)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(xhci_log_ctrl_ctx, xhci_configure_endpoint_ctrl_ctx,
|
||||
TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx),
|
||||
TP_ARGS(ctrl_ctx)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(xhci_log_ring,
|
||||
TP_PROTO(struct xhci_ring *ring),
|
||||
TP_ARGS(ring),
|
||||
|
@@ -893,7 +893,7 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
|
||||
struct xhci_port **ports;
|
||||
int port_index;
|
||||
unsigned long flags;
|
||||
u32 t1, t2;
|
||||
u32 t1, t2, portsc;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
@@ -902,10 +902,15 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
|
||||
ports = xhci->usb3_rhub.ports;
|
||||
while (port_index--) {
|
||||
t1 = readl(ports[port_index]->addr);
|
||||
portsc = t1;
|
||||
t1 = xhci_port_state_to_neutral(t1);
|
||||
t2 = t1 & ~PORT_WAKE_BITS;
|
||||
if (t1 != t2)
|
||||
if (t1 != t2) {
|
||||
writel(t2, ports[port_index]->addr);
|
||||
xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
|
||||
xhci->usb3_rhub.hcd->self.busnum,
|
||||
port_index + 1, portsc, t2);
|
||||
}
|
||||
}
|
||||
|
||||
/* disable usb2 ports Wake bits */
|
||||
@@ -913,12 +918,16 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
|
||||
ports = xhci->usb2_rhub.ports;
|
||||
while (port_index--) {
|
||||
t1 = readl(ports[port_index]->addr);
|
||||
portsc = t1;
|
||||
t1 = xhci_port_state_to_neutral(t1);
|
||||
t2 = t1 & ~PORT_WAKE_BITS;
|
||||
if (t1 != t2)
|
||||
if (t1 != t2) {
|
||||
writel(t2, ports[port_index]->addr);
|
||||
xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
|
||||
xhci->usb2_rhub.hcd->self.busnum,
|
||||
port_index + 1, portsc, t2);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
}
|
||||
|
||||
@@ -1238,6 +1247,21 @@ EXPORT_SYMBOL_GPL(xhci_resume);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT),
|
||||
* we'll copy the actual data into the TRB address register. This is limited to
|
||||
* transfers up to 8 bytes on output endpoints of any kind with wMaxPacketSize
|
||||
* >= 8 bytes. If suitable for IDT only one Transfer TRB per TD is allowed.
|
||||
*/
|
||||
static int xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags)
|
||||
{
|
||||
if (xhci_urb_suitable_for_idt(urb))
|
||||
return 0;
|
||||
|
||||
return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* xhci_get_endpoint_index - Used for passing endpoint bitmasks between the core and
|
||||
* HCDs. Find the index for an endpoint given its descriptor. Use the return
|
||||
@@ -1783,6 +1807,7 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
unsigned int ep_index;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
u32 added_ctxs;
|
||||
u32 new_add_flags, new_drop_flags;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
@@ -1873,6 +1898,9 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
/* Store the usb_device pointer for later use */
|
||||
ep->hcpriv = udev;
|
||||
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
|
||||
trace_xhci_add_endpoint(ep_ctx);
|
||||
|
||||
xhci_debugfs_create_endpoint(xhci, virt_dev, ep_index);
|
||||
|
||||
xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
|
||||
@@ -2747,6 +2775,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
||||
}
|
||||
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx);
|
||||
|
||||
trace_xhci_configure_endpoint_ctrl_ctx(ctrl_ctx);
|
||||
trace_xhci_configure_endpoint(slot_ctx);
|
||||
|
||||
if (!ctx_change)
|
||||
@@ -4012,6 +4042,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
trace_xhci_address_ctx(xhci, virt_dev->in_ctx,
|
||||
le32_to_cpu(slot_ctx->dev_info) >> 27);
|
||||
|
||||
trace_xhci_address_ctrl_ctx(ctrl_ctx);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
trace_xhci_setup_device(virt_dev);
|
||||
ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma,
|
||||
@@ -5154,6 +5185,7 @@ static const struct hc_driver xhci_hc_driver = {
|
||||
/*
|
||||
* managing i/o requests and associated device resources
|
||||
*/
|
||||
.map_urb_for_dma = xhci_map_urb_for_dma,
|
||||
.urb_enqueue = xhci_urb_enqueue,
|
||||
.urb_dequeue = xhci_urb_dequeue,
|
||||
.alloc_dev = xhci_alloc_dev,
|
||||
|
@@ -1303,6 +1303,8 @@ enum xhci_setup_dev {
|
||||
#define TRB_IOC (1<<5)
|
||||
/* The buffer pointer contains immediate data */
|
||||
#define TRB_IDT (1<<6)
|
||||
/* TDs smaller than this might use IDT */
|
||||
#define TRB_IDT_MAX_SIZE 8
|
||||
|
||||
/* Block Event Interrupt */
|
||||
#define TRB_BEI (1<<9)
|
||||
@@ -2149,6 +2151,21 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
|
||||
urb->stream_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: As per spec Isochronous IDT transmissions are supported. We bypass
|
||||
* them anyways as we where unable to find a device that matches the
|
||||
* constraints.
|
||||
*/
|
||||
static inline bool xhci_urb_suitable_for_idt(struct urb *urb)
|
||||
{
|
||||
if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) &&
|
||||
usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
|
||||
urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline char *xhci_slot_state_string(u32 state)
|
||||
{
|
||||
switch (state) {
|
||||
@@ -2384,6 +2401,35 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline const char *xhci_decode_ctrl_ctx(unsigned long drop,
|
||||
unsigned long add)
|
||||
{
|
||||
static char str[1024];
|
||||
unsigned int bit;
|
||||
int ret = 0;
|
||||
|
||||
if (drop) {
|
||||
ret = sprintf(str, "Drop:");
|
||||
for_each_set_bit(bit, &drop, 32)
|
||||
ret += sprintf(str + ret, " %d%s",
|
||||
bit / 2,
|
||||
bit % 2 ? "in":"out");
|
||||
ret += sprintf(str + ret, ", ");
|
||||
}
|
||||
|
||||
if (add) {
|
||||
ret += sprintf(str + ret, "Add:%s%s",
|
||||
(add & SLOT_FLAG) ? " slot":"",
|
||||
(add & EP0_FLAG) ? " ep0":"");
|
||||
add &= ~(SLOT_FLAG | EP0_FLAG);
|
||||
for_each_set_bit(bit, &add, 32)
|
||||
ret += sprintf(str + ret, " %d%s",
|
||||
bit / 2,
|
||||
bit % 2 ? "in":"out");
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline const char *xhci_decode_slot_context(u32 info, u32 info2,
|
||||
u32 tt_info, u32 state)
|
||||
{
|
||||
|
Reference in New Issue
Block a user