Re: Huawei integrated modem causes instant resume from suspend on Acer P648-G3
Am Mittwoch, den 27.09.2017, 14:14 +0800 schrieb Daniel Drake: > There are no errors in the logs showing any suspend/resume-related issues. > When the system wakes up due to the modem, log-wise it appears to be a > normal resume. > > Does anyone have any suggestions for how we can investigate further, or how > we should workaround this issue in upstreamable form? Hi, unfortunately you left out the most important information 1) kernel version? 2) driver used? 3) device descriptors (lsusb) 4) s2idle or S3? Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2] r8152: add Linksys USB3GIGV1 id
Am Dienstag, den 26.09.2017, 08:19 -0700 schrieb Doug Anderson: > > I know that for at least some of the adapters in the CDC Ethernet > blacklist it was claimed that the CDC Ethernet support in the adapter > was kinda broken anyway so the blacklist made sense. ...but for the > Linksys Gigabit adapter the CDC Ethernet driver seems to work OK, it's > just not quite as full featured / efficient as the R8152 driver. > > Is that not a concern? I guess you could tell people in this > situation that they simply need to enable the R8152 driver to get > continued support for their Ethernet adapter? Hi, yes, it is a valid concern. An #ifdef will be needed. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Issue with Gadget UVC and dummy_hcd
Hi, Alan Stern writes: > On Tue, 26 Sep 2017, Felipe Balbi wrote: > >> > Does uvc use isochronous transfers? I assume it would, since it's a >> > video protocol. >> >> yes, it does :-) >> >> > dummy-hcd does not support isochronous. I don't know what would happen >> >> really? Then why is it registering iso endpoints to the gadget layer? >> >> static const struct { >> const char *name; >> const struct usb_ep_caps caps; >> } ep_info[] = { >> #define EP_INFO(_name, _caps) \ >> { \ >> .name = _name, \ >> .caps = _caps, \ >> } >> >> /* everyone has ep0 */ >> EP_INFO(ep0name, >> USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), >> /* act like a pxa250: fifteen fixed function endpoints */ >> EP_INFO("ep1in-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep2out-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep3in-iso", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep4out-iso", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep5in-int", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep6in-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep7out-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep8in-iso", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep9out-iso", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep10in-int", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep11in-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep12out-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep13in-iso", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep14out-iso", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep15in-int", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), >> /* or like sa1100: two fixed function endpoints */ >> EP_INFO("ep1out-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep2in-bulk", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), >> /* and now some generic EPs so we have enough in multi config */ >> EP_INFO("ep3out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep4in", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep5out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep6out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep7in", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep8out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep9in", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep10out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep11out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep12in", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep13out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> EP_INFO("ep14in", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), >> EP_INFO("ep15out", >> USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), >> >> #undef EP_INFO >> }; >> >> > if you tried it, but one way or another it would not work the way you >> > want. >> >> if that's really the case, then maybe we should remove all the iso >> endpoints from dummy. Right? > > Or comment them out, in case somebody decides to add isochronous Kinda pointless to leave commented out code, but fine. > support in the future. Yes, there's no point having them in the > driver, given the way it works currently. All isochronous URBs > complete with a -ENOSYS error status: > > switch (usb_pipetype(urb->pipe)) { > case PIPE_ISOCHRONOUS: > /* FIXME is it urb->interval since the last xfer? >* use urb->iso_frame_desc[i]. >* complete whether or not ep has requests queued. >* report random errors, to debug drivers. >*/ > limit = max(limit, periodic_bytes(dum, ep)); > status = -ENOSYS; >
Re: Type-C port on the Asmedia ASM1142
On 26.09.2017 22:08, Adrian Bocaniciu wrote: On Tue, 26 Sep 2017 09:53:23 +0300 Mathias Nyman wrote: Do you have any more details, logs or documentation about these 10Gbps ASM1142 bugs in xHCI driver? I'd be interested in getting that fixed Thanks Mathias I know exactly what must be changed in the XHCI driver, but I did not have time to implement it. If I will succeed soon to have a weekend in which I will not be busy, I could submit a complete patch. I can test the support for 10 Gb/s on 6 different kinds of motherboards, 2 with ASM 1142 and 4 with the USB 3.1 controllers from Intel Thunderbolt 3, and also with 3 or 4 different kinds of USB 10 GB/s to SATA 6 Gb/s bridges. The problem in the current XHCI driver was created by a patch from 2 years ago, which added SuperSpeedPlus detection. However, the method used is wrong, according to both the Intel XHCI specification and the ASMedia datasheets. The only explanation for the origin of the wrong detection method that I can imagine is that probably this method was correct for some of the first ASMedia USB 3.1 controllers, maybe for ASM 1042. I suppose that the first ASMedia XHCI controllers did not implement correctly the XHCI specification, but later they were corrected, at least starting with ASM 1142. Of course, the Intel USB 3.1 controllers must have implemented the Intel specification since the beginning. So the status is that the current Linux XHCI driver cannot detect the SuperSpeedPlus support in any not very old motherboard, i.e. any motherboard with ASM 1142 or newer, or any motherboard with Intel Thunderbolt 3. (The current XHCI driver tries to read a "3.1" value from a register that according to all specifications and datasheets and also according to my experiments can have only the "3.0" value, even in USB 3.1 controllers. The correct SuperSpeedPlus detection involves other registers and it is more complex.) In have already implemented the part that detects the capabilities of the XHCI controller but there are also some changes that must be done to detect correctly the capabilities of a SuperSpeedPlus device after it is connected to a USB 3.1 port, otherwise the 10 Gb/s link is not established. Best regards ! Ok, please let me know which register you refer to, I'd like to get this fixed as soon as possible. Based on what you say I suspect that you talk about the SBRN (Serial bus release number). The early xhci 1.1 spec that was used to write USB3.1 SSP support stated that SBRN contain the serial bus specification release, (in hex) with examples of 30h for USB 3.0 and 31h for USB 3.1 Driver uses this to determine if hosts supports USB 3.0 or usb 3.1 I see that the current public xhci spec only mention 30h (USB 3.0), and in a way that it can be interpreted as 30 being the only option. If this is the case then SBRN itself would be completely useless. Why have a register with the purpose of telling which serial bus release number the hardware supports always forced to 30h? Yes, the first Intel Alpine ridge based USB 3.1 SSP 10Gbps xHCI hosts had this as 30, Newer Intel USB 3.1 SSP capable 10Gbps xHCI hosts have it set to 31h If vendors have interpreted it as "SBRN must equal 30h" then we need to work around that in the driver. We can check if the host supports USB 3.1 from the ports supported protocol capability, see xhci 7.2 xHCI supported protocol capability, major and minor revision fields. These should at least contain major=3 and minor=1 for USB 3.1 capable ports. That at least is unambiguous in all xhci specs (early, and current public) -Mathias -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] usb: renesas_usbhs: fix usbhsf_fifo_clear() behavior
This patch fixes two issues: - the usbhsf_fifo_clear() is possible to cause 10 msec delay if the pipe is RX direction and empty because the FRDY bit will never be set to 1 in such case. - sets the BCLR of {C,Dn}FIFOCTR to 1 even when it's non-DCP pipe and the FRDY bit sets to 0. Fixes: e8d548d54968 ("usb: renesas_usbhs: fifo became independent from pipe.") Cc: # v3.1+ Signed-off-by: Yoshihiro Shimoda --- This patch set is based on the Felipe's usb.git / testing/fixes branch (The commit is 7661ca09b2ff98f48693f431bb01fed62830e433). drivers/usb/renesas_usbhs/fifo.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index d1af831..68f2690 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -282,11 +282,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + int ret = 0; - if (!usbhs_pipe_is_dcp(pipe)) - usbhsf_fifo_barrier(priv, fifo); + if (!usbhs_pipe_is_dcp(pipe)) { + /* +* This driver checks the pipe condition first to avoid -EBUSY +* from usbhsf_fifo_barrier() with about 10 msec delay in +* the interrupt handler if the pipe is RX direction and empty. +*/ + if (usbhs_pipe_is_dir_in(pipe)) + ret = usbhs_pipe_is_accessible(pipe); + if (!ret) + ret = usbhsf_fifo_barrier(priv, fifo); + } - usbhs_write(priv, fifo->ctr, BCLR); + /* +* if non-DCP pipe, this driver should set BCLR when +* usbhsf_fifo_barrier() returns 0. +*/ + if (!ret) + usbhs_write(priv, fifo->ctr, BCLR); } static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 8/8] tty/serial: atmel: Prevent a warning on suspend
The atmel serial port driver reported the following warning on suspend: atmel_usart f802.serial: ttyS1: Unable to drain transmitter As the ATMEL_US_TXEMPTY status bit in ATMEL_US_CSR is always cleared when the transmitter is disabled, we need to know the transmitter's state to return the real fifo state. And as ATMEL_US_CR is write-only, it is necessary to save the state of the transmitter in a local variable, and update the variable when TXEN and TXDIS is written in ATMEL_US_CR. After those changes, atmel_tx_empty can return "empty" on suspend, the warning in uart_suspend_port disappears, and suspending is 20ms shorter for each enabled Atmel serial port. Signed-off-by: Romain Izard Tested-by: Nicolas Ferre Acked-by: Nicolas Ferre Acked-by: Richard Genoud --- drivers/tty/serial/atmel_serial.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 7551cab438ff..ce45b4ada0bf 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -171,6 +171,7 @@ struct atmel_uart_port { boolhas_hw_timer; struct timer_list uart_timer; + booltx_stopped; boolsuspended; unsigned intpending; unsigned intpending_status; @@ -380,6 +381,10 @@ static int atmel_config_rs485(struct uart_port *port, */ static u_int atmel_tx_empty(struct uart_port *port) { + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + if (atmel_port->tx_stopped) + return TIOCSER_TEMT; return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0; @@ -485,6 +490,7 @@ static void atmel_stop_tx(struct uart_port *port) * is fully transmitted. */ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS); + atmel_port->tx_stopped = true; /* Disable interrupts */ atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask); @@ -521,6 +527,7 @@ static void atmel_start_tx(struct uart_port *port) /* re-enable the transmitter */ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN); + atmel_port->tx_stopped = false; } /* @@ -1866,6 +1873,7 @@ static int atmel_startup(struct uart_port *port) atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); /* enable xmit & rcvr */ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); + atmel_port->tx_stopped = false; setup_timer(&atmel_port->uart_timer, atmel_uart_timer_callback, @@ -2122,6 +2130,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, /* disable receiver and transmitter */ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS); + atmel_port->tx_stopped = true; /* mode */ if (port->rs485.flags & SER_RS485_ENABLED) { @@ -2207,6 +2216,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, atmel_uart_writel(port, ATMEL_US_BRGR, quot); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); + atmel_port->tx_stopped = false; /* restore interrupts */ atmel_uart_writel(port, ATMEL_US_IER, imr); @@ -2450,6 +2460,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) /* Make sure that tx path is actually able to send characters */ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN); + atmel_port->tx_stopped = false; uart_console_write(port, s, count, atmel_console_putchar); @@ -2511,6 +2522,7 @@ static int __init atmel_console_setup(struct console *co, char *options) { int ret; struct uart_port *port = &atmel_ports[co->index].uart; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int baud = 115200; int bits = 8; int parity = 'n'; @@ -2528,6 +2540,7 @@ static int __init atmel_console_setup(struct console *co, char *options) atmel_uart_writel(port, ATMEL_US_IDR, -1); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); + atmel_port->tx_stopped = false; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] usb: renesas_usbhs: fix usbhsf_fifo_clear() behavior
On Wed, Sep 27, 2017 at 05:04:05PM +0900, Yoshihiro Shimoda wrote: > This patch fixes two issues: > - the usbhsf_fifo_clear() is possible to cause 10 msec delay if >the pipe is RX direction and empty because the FRDY bit will never >be set to 1 in such case. > - sets the BCLR of {C,Dn}FIFOCTR to 1 even when it's non-DCP pipe and >the FRDY bit sets to 0. Should this be two different patches because of this? thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 7/8] atmel_flexcom: Support backup mode
The controller used by a flexcom module is configured at boot, and left alone after this. As the configuration will be lost after backup mode, restore the state of the flexcom driver on resume. Signed-off-by: Romain Izard Acked-by: Nicolas Ferre Tested-by: Nicolas Ferre --- drivers/mfd/atmel-flexcom.c | 65 ++--- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c index 064bde9cff5a..ef1235c4a179 100644 --- a/drivers/mfd/atmel-flexcom.c +++ b/drivers/mfd/atmel-flexcom.c @@ -39,34 +39,44 @@ #define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \ FLEX_MR_OPMODE_MASK) +struct atmel_flexcom { + void __iomem *base; + u32 opmode; + struct clk *clk; +}; static int atmel_flexcom_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct clk *clk; struct resource *res; - void __iomem *base; - u32 opmode; + struct atmel_flexcom *afc; int err; + u32 val; + + afc = devm_kzalloc(&pdev->dev, sizeof(*afc), GFP_KERNEL); + if (!afc) + return -ENOMEM; - err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode); + platform_set_drvdata(pdev, afc); + + err = of_property_read_u32(np, "atmel,flexcom-mode", &afc->opmode); if (err) return err; - if (opmode < ATMEL_FLEXCOM_MODE_USART || - opmode > ATMEL_FLEXCOM_MODE_TWI) + if (afc->opmode < ATMEL_FLEXCOM_MODE_USART || + afc->opmode > ATMEL_FLEXCOM_MODE_TWI) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); + afc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(afc->base)) + return PTR_ERR(afc->base); - clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) - return PTR_ERR(clk); + afc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(afc->clk)) + return PTR_ERR(afc->clk); - err = clk_prepare_enable(clk); + err = clk_prepare_enable(afc->clk); if (err) return err; @@ -76,9 +86,10 @@ static int atmel_flexcom_probe(struct platform_device *pdev) * inaccessible and are read as zero. Also the external I/O lines of the * Flexcom are muxed to reach the selected device. */ - writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR); + val = FLEX_MR_OPMODE(afc->opmode); + writel(val, afc->base + FLEX_MR); - clk_disable_unprepare(clk); + clk_disable_unprepare(afc->clk); return devm_of_platform_populate(&pdev->dev); } @@ -89,10 +100,34 @@ static const struct of_device_id atmel_flexcom_of_match[] = { }; MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match); +#ifdef CONFIG_PM_SLEEP +static int atmel_flexcom_resume(struct device *dev) +{ + struct atmel_flexcom *afc = dev_get_drvdata(dev); + int err; + u32 val; + + err = clk_prepare_enable(afc->clk); + if (err) + return err; + + val = FLEX_MR_OPMODE(afc->opmode), + writel(val, afc->base + FLEX_MR); + + clk_disable_unprepare(afc->clk); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(atmel_flexcom_pm_ops, NULL, +atmel_flexcom_resume); + static struct platform_driver atmel_flexcom_driver = { .probe = atmel_flexcom_probe, .driver = { .name = "atmel_flexcom", + .pm = &atmel_flexcom_pm_ops, .of_match_table = atmel_flexcom_of_match, }, }; -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 6/8] pwm: atmel-tcb: Support backup mode
Save and restore registers for the PWM on suspend and resume, which makes hibernation and backup modes possible. Signed-off-by: Romain Izard Acked-by: Nicolas Ferre --- drivers/pwm/pwm-atmel-tcb.c | 63 +++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 75db585a2a94..acd3ce8ecf3f 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -37,11 +37,20 @@ struct atmel_tcb_pwm_device { unsigned period;/* PWM period expressed in clk cycles */ }; +struct atmel_tcb_channel { + u32 enabled; + u32 cmr; + u32 ra; + u32 rb; + u32 rc; +}; + struct atmel_tcb_pwm_chip { struct pwm_chip chip; spinlock_t lock; struct atmel_tc *tc; struct atmel_tcb_pwm_device *pwms[NPWM]; + struct atmel_tcb_channel bkup[NPWM / 2]; }; static inline struct atmel_tcb_pwm_chip *to_tcb_chip(struct pwm_chip *chip) @@ -175,12 +184,15 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) * Use software trigger to apply the new setting. * If both PWM devices in this group are disabled we stop the clock. */ - if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC))) + if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC))) { __raw_writel(ATMEL_TC_SWTRG | ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(group, CCR)); - else + tcbpwmc->bkup[group].enabled = 1; + } else { __raw_writel(ATMEL_TC_SWTRG, regs + ATMEL_TC_REG(group, CCR)); + tcbpwmc->bkup[group].enabled = 0; + } spin_unlock(&tcbpwmc->lock); } @@ -263,6 +275,7 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) /* Use software trigger to apply the new setting */ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs + ATMEL_TC_REG(group, CCR)); + tcbpwmc->bkup[group].enabled = 1; spin_unlock(&tcbpwmc->lock); return 0; } @@ -445,10 +458,56 @@ static const struct of_device_id atmel_tcb_pwm_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids); +#ifdef CONFIG_PM_SLEEP +static int atmel_tcb_pwm_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev); + void __iomem *base = tcbpwm->tc->regs; + int i; + + for (i = 0; i < (NPWM / 2); i++) { + struct atmel_tcb_channel *chan = &tcbpwm->bkup[i]; + + chan->cmr = readl(base + ATMEL_TC_REG(i, CMR)); + chan->ra = readl(base + ATMEL_TC_REG(i, RA)); + chan->rb = readl(base + ATMEL_TC_REG(i, RB)); + chan->rc = readl(base + ATMEL_TC_REG(i, RC)); + } + return 0; +} + +static int atmel_tcb_pwm_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev); + void __iomem *base = tcbpwm->tc->regs; + int i; + + for (i = 0; i < (NPWM / 2); i++) { + struct atmel_tcb_channel *chan = &tcbpwm->bkup[i]; + + writel(chan->cmr, base + ATMEL_TC_REG(i, CMR)); + writel(chan->ra, base + ATMEL_TC_REG(i, RA)); + writel(chan->rb, base + ATMEL_TC_REG(i, RB)); + writel(chan->rc, base + ATMEL_TC_REG(i, RC)); + if (chan->enabled) { + writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, + base + ATMEL_TC_REG(i, CCR)); + } + } + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(atmel_tcb_pwm_pm_ops, atmel_tcb_pwm_suspend, +atmel_tcb_pwm_resume); + static struct platform_driver atmel_tcb_pwm_driver = { .driver = { .name = "atmel-tcb-pwm", .of_match_table = atmel_tcb_pwm_dt_ids, + .pm = &atmel_tcb_pwm_pm_ops, }, .probe = atmel_tcb_pwm_probe, .remove = atmel_tcb_pwm_remove, -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/8] clk: at91: pmc: Wait for clocks when resuming
Wait for the syncronization of all clocks when resuming, not only the UPLL clock. Do not use regmap_read_poll_timeout, as it will call BUG() when interrupts are masked, which is the case in here. Signed-off-by: Romain Izard Acked-by: Ludovic Desroches Acked-by: Nicolas Ferre --- drivers/clk/at91/pmc.c | 24 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 775af473fe11..5c2b26de303e 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -107,10 +107,20 @@ static int pmc_suspend(void) return 0; } +static bool pmc_ready(unsigned int mask) +{ + unsigned int status; + + regmap_read(pmcreg, AT91_PMC_SR, &status); + + return ((status & mask) == mask) ? 1 : 0; +} + static void pmc_resume(void) { - int i, ret = 0; + int i; u32 tmp; + u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA; regmap_read(pmcreg, AT91_PMC_MCKR, &tmp); if (pmc_cache.mckr != tmp) @@ -134,13 +144,11 @@ static void pmc_resume(void) AT91_PMC_PCR_CMD); } - if (pmc_cache.uckr & AT91_PMC_UPLLEN) { - ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp, - !(tmp & AT91_PMC_LOCKU), - 10, 5000); - if (ret) - pr_crit("USB PLL didn't lock when resuming\n"); - } + if (pmc_cache.uckr & AT91_PMC_UPLLEN) + mask |= AT91_PMC_LOCKU; + + while (!pmc_ready(mask)) + cpu_relax(); } static struct syscore_ops pmc_syscore_ops = { -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/8] mtd: nand: atmel: Avoid ECC errors when leaving backup mode
During backup mode, the contents of all registers will be cleared as the SoC will be completely powered down. For a product that boots on NAND Flash memory, the bootloader will obviously use the related controller to read the Flash and correct any detected error in the memory, before handling back control to the kernel's resuming entry point. But it does not clean the NAND controller registers after use and on its side the kernel driver expects the error locator to be powered down and in a clean state. Add a resume hook for the PMECC error locator, and reset its registers. Signed-off-by: Romain Izard --- Change in v3: * keep the PMECC disabled when not in use, and use atmel_pmecc_resume to reset the controller after the bootloader has left it enabled. drivers/mtd/nand/atmel/nand-controller.c | 3 +++ drivers/mtd/nand/atmel/pmecc.c | 22 ++ drivers/mtd/nand/atmel/pmecc.h | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c index f25eca79f4e5..86c2199380c2 100644 --- a/drivers/mtd/nand/atmel/nand-controller.c +++ b/drivers/mtd/nand/atmel/nand-controller.c @@ -2530,6 +2530,9 @@ static __maybe_unused int atmel_nand_controller_resume(struct device *dev) struct atmel_nand_controller *nc = dev_get_drvdata(dev); struct atmel_nand *nand; + if (nand->pmecc) + atmel_pmecc_resume(nand->pmecc); + list_for_each_entry(nand, &nc->chips, node) { int i; diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c index 146af8218314..ff09c0f25dd4 100644 --- a/drivers/mtd/nand/atmel/pmecc.c +++ b/drivers/mtd/nand/atmel/pmecc.c @@ -765,6 +765,12 @@ void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user, } EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes); +void atmel_pmecc_reset(struct atmel_pmecc *pmecc) +{ + writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); + writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); +} + int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op) { struct atmel_pmecc *pmecc = user->pmecc; @@ -797,14 +803,17 @@ EXPORT_SYMBOL_GPL(atmel_pmecc_enable); void atmel_pmecc_disable(struct atmel_pmecc_user *user) { - struct atmel_pmecc *pmecc = user->pmecc; - - writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); - writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); + atmel_pmecc_reset(user->pmecc); mutex_unlock(&user->pmecc->lock); } EXPORT_SYMBOL_GPL(atmel_pmecc_disable); +void atmel_pmecc_resume(struct atmel_pmecc_user *user) +{ + atmel_pmecc_reset(user->pmecc); +} +EXPORT_SYMBOL_GPL(atmel_pmecc_resume); + int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user) { struct atmel_pmecc *pmecc = user->pmecc; @@ -855,10 +864,7 @@ static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev, /* Disable all interrupts before registering the PMECC handler. */ writel(0x, pmecc->regs.base + ATMEL_PMECC_IDR); - - /* Reset the ECC engine */ - writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); - writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); + atmel_pmecc_reset(pmecc); return pmecc; } diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/atmel/pmecc.h index a8ddbfca2ea5..488a90f1965d 100644 --- a/drivers/mtd/nand/atmel/pmecc.h +++ b/drivers/mtd/nand/atmel/pmecc.h @@ -63,6 +63,7 @@ void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user); int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op); void atmel_pmecc_disable(struct atmel_pmecc_user *user); +void atmel_pmecc_resume(struct atmel_pmecc_user *user); int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user); int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector, void *data, void *ecc); -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 5/8] ehci-atmel: Power down during suspend is normal
When an Atmel SoC is suspended with the backup mode, the USB bus will be powered down. As this is expected, do not return an error to the driver core when ehci_resume detects it. Signed-off-by: Romain Izard Acked-by: Nicolas Ferre --- drivers/usb/host/ehci-atmel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 7440722bfbf0..2a8b9bdc0e57 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -205,7 +205,8 @@ static int __maybe_unused ehci_atmel_drv_resume(struct device *dev) struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd); atmel_start_clock(atmel_ehci); - return ehci_resume(hcd, false); + ehci_resume(hcd, false); + return 0; } #ifdef CONFIG_OF -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/8] Various patches for SAMA5D2 backup mode
While the core of the backup mode for SAMA5D2 has been integrated in v4.13, it is far from complete. Individual controllers in the chip have drivers that do not support the reset of the registers during suspend, and they need to be adapted to handle it. The first patch uses the clock wakeup code from the prototype backup mode instead of the version integrated in the mainline, as the mainline version is not stable. During a test loop with two-second backup suspend, the mainline version will hang in less than one day, whereas the prototype version has been running the same test for more than a week without hanging. While all these patches are provided in a series, the clock, mtd, usb, pwm and mfd patch do not depend on each other. Changes in v2: * drop the IIO patch duplicating existing code * determine the number of programmable clocks to save dynamically * declare a required local variable in the tty/serial patch Changes in v3: * drop dev_printk changes for PMECC * rework the resume code for PMECC * improve comments on PMC clock handling Romain Izard (8): clk: at91: pmc: Wait for clocks when resuming clk: at91: pmc: Save SCSR during suspend clk: at91: pmc: Support backup for programmable clocks mtd: nand: atmel: Avoid ECC errors when leaving backup mode ehci-atmel: Power down during suspend is normal pwm: atmel-tcb: Support backup mode atmel_flexcom: Support backup mode tty/serial: atmel: Prevent a warning on suspend drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/at91/pmc.c | 63 ++- drivers/clk/at91/pmc.h | 2 + drivers/mfd/atmel-flexcom.c | 65 drivers/mtd/nand/atmel/nand-controller.c | 3 ++ drivers/mtd/nand/atmel/pmecc.c | 22 +++ drivers/mtd/nand/atmel/pmecc.h | 1 + drivers/pwm/pwm-atmel-tcb.c | 63 ++- drivers/tty/serial/atmel_serial.c| 13 +++ drivers/usb/host/ehci-atmel.c| 3 +- 10 files changed, 201 insertions(+), 36 deletions(-) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] usb: renesas_usbhs: fix usbhsf_fifo_clear() behavior
Hi Greg, > -Original Message- > From: Greg KH > Sent: Wednesday, September 27, 2017 5:37 PM > > On Wed, Sep 27, 2017 at 05:04:05PM +0900, Yoshihiro Shimoda wrote: > > This patch fixes two issues: > > - the usbhsf_fifo_clear() is possible to cause 10 msec delay if > >the pipe is RX direction and empty because the FRDY bit will never > >be set to 1 in such case. > > - sets the BCLR of {C,Dn}FIFOCTR to 1 even when it's non-DCP pipe and > >the FRDY bit sets to 0. > > Should this be two different patches because of this? I got it. I will make two patches from this patch. Best regards, Yoshihiro Shimoda > thanks, > > greg k-h > -- > To unsubscribe from this list: send the line "unsubscribe linux-usb" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/8] clk: at91: pmc: Save SCSR during suspend
The contents of the System Clock Status Register (SCSR) needs to be restored into the System Clock Enable Register (SCER). As the bootloader will restore some clocks by itself, the issue can be missed as only the USB controller, the LCD controller, the Image Sensor controller and the programmable clocks will be impacted. Fix the obvious typo in the suspend/resume code, as the IMR register does not need to be saved twice. Signed-off-by: Romain Izard Acked-by: Nicolas Ferre --- drivers/clk/at91/pmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 5c2b26de303e..07dc2861ad3f 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -86,7 +86,7 @@ static int pmc_suspend(void) { int i; - regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.scsr); + regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr); regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0); regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr); regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor); @@ -129,7 +129,7 @@ static void pmc_resume(void) if (pmc_cache.pllar != tmp) pr_warn("PLLAR was not configured properly by the firmware\n"); - regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.scsr); + regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr); regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0); regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr); regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor); -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/8] clk: at91: pmc: Support backup for programmable clocks
From: Romain Izard When an AT91 programmable clock is declared in the device tree, register it into the Power Management Controller driver. On entering suspend mode, the driver saves and restores the Programmable Clock registers to support the backup mode for these clocks. Signed-off-by: Romain Izard Acked-by: Nicolas Ferre --- Changes in v2: * register PCKs on clock startup Chnages in v3: * improve comments on hanling 0 in pmc_register_id and pmc_register_pck * declare local variables earlier for checkpatch drivers/clk/at91/clk-programmable.c | 2 ++ drivers/clk/at91/pmc.c | 35 +++ drivers/clk/at91/pmc.h | 2 ++ 3 files changed, 39 insertions(+) diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 85a449cf61e3..0e6aab1252fc 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c @@ -204,6 +204,8 @@ at91_clk_register_programmable(struct regmap *regmap, if (ret) { kfree(prog); hw = ERR_PTR(ret); + } else { + pmc_register_pck(id); } return hw; diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 07dc2861ad3f..1fa27f4ea538 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -22,6 +22,7 @@ #include "pmc.h" #define PMC_MAX_IDS 128 +#define PMC_MAX_PCKS 8 int of_at91_get_clk_range(struct device_node *np, const char *propname, struct clk_range *range) @@ -50,6 +51,7 @@ EXPORT_SYMBOL_GPL(of_at91_get_clk_range); static struct regmap *pmcreg; static u8 registered_ids[PMC_MAX_IDS]; +static u8 registered_pcks[PMC_MAX_PCKS]; static struct { @@ -66,8 +68,13 @@ static struct u32 pcr[PMC_MAX_IDS]; u32 audio_pll0; u32 audio_pll1; + u32 pckr[PMC_MAX_PCKS]; } pmc_cache; +/* + * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored + * without alteration in the table, and 0 is for unused clocks. + */ void pmc_register_id(u8 id) { int i; @@ -82,9 +89,28 @@ void pmc_register_id(u8 id) } } +/* + * As Programmable Clock 0 is valid on AT91 chips, there is an offset + * of 1 between the stored value and the real clock ID. + */ +void pmc_register_pck(u8 pck) +{ + int i; + + for (i = 0; i < PMC_MAX_PCKS; i++) { + if (registered_pcks[i] == 0) { + registered_pcks[i] = pck + 1; + break; + } + if (registered_pcks[i] == (pck + 1)) + break; + } +} + static int pmc_suspend(void) { int i; + u8 num; regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr); regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0); @@ -103,6 +129,10 @@ static int pmc_suspend(void) regmap_read(pmcreg, AT91_PMC_PCR, &pmc_cache.pcr[registered_ids[i]]); } + for (i = 0; registered_pcks[i]; i++) { + num = registered_pcks[i] - 1; + regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]); + } return 0; } @@ -119,6 +149,7 @@ static bool pmc_ready(unsigned int mask) static void pmc_resume(void) { int i; + u8 num; u32 tmp; u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA; @@ -143,6 +174,10 @@ static void pmc_resume(void) pmc_cache.pcr[registered_ids[i]] | AT91_PMC_PCR_CMD); } + for (i = 0; registered_pcks[i]; i++) { + num = registered_pcks[i] - 1; + regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]); + } if (pmc_cache.uckr & AT91_PMC_UPLLEN) mask |= AT91_PMC_LOCKU; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 858e8ef7e8db..d22b1fa9ecdc 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -31,8 +31,10 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname, #ifdef CONFIG_PM void pmc_register_id(u8 id); +void pmc_register_pck(u8 pck); #else static inline void pmc_register_id(u8 id) {} +static inline void pmc_register_pck(u8 pck) {} #endif #endif /* __PMC_H_ */ -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs
QUSB-v2 and QMP-v3 USB PHYs are present on Qualcomm's 14nm and 10nm SOCs. This patch series adds support for runtime PM for these USB PHYs and adds fixes in drivers to follow PHY reset and initialization sequence as per hardware programming manual. Changes since v1: - Incorporated review comments. - Fixes to align with hardware programming manual. - Added support for QUSBv2 and QMPv3 PHYs. - Enable DP/DM asynchronous interrupts from QUSB2 USB2 PHY for remote-wakeup. - Enable LFPS and RX-TERM detection for attach and detach events from QMP USB3 PHY for remotewakeup. - Update sw-vbus overide in PHY wrapper for device mode. - Dropped one dwc3 patch from this series which I will submit with other dwc3 patches. ("usb: dwc3: core: Notify USB3 PHY as well for DRD modes") Manu Gautam (15): phy: qcom-qmp: Power-on PHY before initialization phy: qcom-qusb2: Power-on PHY before initialization phy: qcom-qmp: Fix PHY block reset sequence phy: qcom-qmp: Move SERDES/PCS START after PHY reset phy: qcom-qusb2: Add support for different register layouts dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version phy: qcom-qusb2: Add support for QUSB2 V2 version phy: qcom-qmp: Move register offsets to header file phy: qcom-qmp: Add register offsets for QMP V3 PHY dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY phy: qcom-qmp: Add support for QMP V3 USB3 PHY phy: qcom-qusb2: Set vbus sw-override signal in device mode phy: qcom-qusb2: Add support for runtime PM phy: qcom-qmp: Override lane0_power_present signal in device mode phy: qcom-qmp: Add support for runtime PM Vivek Gautam (2): phy: qcom-qmp: Fix phy pipe clock gating phy: qcom-qmp: Adapt to clk_bulk_* APIs .../devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +- .../devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 +- drivers/phy/qualcomm/phy-qcom-qmp.c| 696 +++-- drivers/phy/qualcomm/phy-qcom-qmp.h| 289 + drivers/phy/qualcomm/phy-qcom-qusb2.c | 412 ++-- 5 files changed, 1148 insertions(+), 260 deletions(-) create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp.h -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 16/17] phy: qcom-qmp: Override lane0_power_present signal in device mode
lane0_power_present signal must be asserted of hardware to operate properly in SS device mode. On some platforms where VBUS line is not connected to SS QMP PHY there is SS_PHY_CTRL register in QSCRATCH wrapper that can be used by software to override VBUS. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 38 + 1 file changed, 38 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index d4e1436..1403de3 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -61,6 +61,9 @@ #define USB3_MODE BIT(0) /* enables USB3 mode */ #define DP_MODEBIT(1) /* enables DP mode */ +/* QSCRATCH register bits */ +#define QSCRATCH_SS_PHY_CTRL 0x30 +#define LANE0_PWR_PRESENT BIT(24) #define PHY_INIT_COMPLETE_TIMEOUT 1000 #define POWER_DOWN_DELAY_US_MIN10 @@ -558,6 +561,7 @@ struct qmp_phy { * @dev: device * @serdes: iomapped memory space for phy's serdes * @dp_com: iomapped memory space for phy's dp_com control block + * @qscratch_base: iomapped memory space for qscratch region * * @clks: array of clocks required by phy * @resets: array of resets required by phy @@ -572,6 +576,7 @@ struct qcom_qmp { struct device *dev; void __iomem *serdes; void __iomem *dp_com; + void __iomem *qscratch_base; struct clk_bulk_data *clks; struct reset_control **resets; @@ -582,6 +587,7 @@ struct qcom_qmp { struct mutex phy_mutex; int init_count; + enum phy_mode mode; }; static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) @@ -1024,6 +1030,26 @@ static int qcom_qmp_phy_exit(struct phy *phy) return 0; } +static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode) +{ + struct qmp_phy *qphy = phy_get_drvdata(phy); + struct qcom_qmp *qmp = qphy->qmp; + + qmp->mode = mode; + + /* Update VBUS override in qscratch register */ + if (qmp->qscratch_base) { + if (mode == PHY_MODE_USB_DEVICE) + qphy_setbits(qmp->qscratch_base, QSCRATCH_SS_PHY_CTRL, +LANE0_PWR_PRESENT); + else + qphy_clrbits(qmp->qscratch_base, QSCRATCH_SS_PHY_CTRL, +LANE0_PWR_PRESENT); + } + + return 0; +} + static int qcom_qmp_phy_vreg_init(struct device *dev) { struct qcom_qmp *qmp = dev_get_drvdata(dev); @@ -1133,6 +1159,7 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) static const struct phy_ops qcom_qmp_phy_gen_ops = { .init = qcom_qmp_phy_init, .exit = qcom_qmp_phy_exit, + .set_mode = qcom_qmp_phy_set_mode, .owner = THIS_MODULE, }; @@ -1273,7 +1300,18 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) qmp->dp_com = base; } + /* Check if platform uses qscratch wrapper */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qscratch"); + if (res) { + /* Can't request region as used by other phy and glue drivers */ + qmp->qscratch_base = devm_ioremap(dev, res->start, + resource_size(res)); + if (IS_ERR(qmp->qscratch_base)) + return PTR_ERR(qmp->qscratch_base); + } + mutex_init(&qmp->phy_mutex); + qmp->mode = PHY_MODE_INVALID; ret = qcom_qmp_phy_clk_init(dev); if (ret) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 17/17] phy: qcom-qmp: Add support for runtime PM
Disable clocks as part of PHY suspend. This also requires enabling PHY autonomous mode to detect lfps/rx_det in suspend state. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 182 +++- drivers/phy/qualcomm/phy-qcom-qmp.h | 3 + 2 files changed, 184 insertions(+), 1 deletion(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 1403de3..a04ba28 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -61,6 +61,20 @@ #define USB3_MODE BIT(0) /* enables USB3 mode */ #define DP_MODEBIT(1) /* enables DP mode */ +/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ +#define ARCVR_DTCT_EN BIT(0) +#define ALFPS_DTCT_EN BIT(1) +#define ARCVR_DTCT_EVENT_SEL BIT(4) + +/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ +#define IRQ_CLEAR BIT(0) + +/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ +#define RCVR_DETECTBIT(0) + +/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ +#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ + /* QSCRATCH register bits */ #define QSCRATCH_SS_PHY_CTRL 0x30 #define LANE0_PWR_PRESENT BIT(24) @@ -111,6 +125,9 @@ enum qphy_reg_layout { QPHY_SW_RESET, QPHY_START_CTRL, QPHY_PCS_READY_STATUS, + QPHY_PCS_AUTONOMOUS_MODE_CTRL, + QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, + QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, }; static const unsigned int pciephy_regs_layout[] = { @@ -138,12 +155,18 @@ enum qphy_reg_layout { [QPHY_SW_RESET] = 0x00, [QPHY_START_CTRL] = 0x08, [QPHY_PCS_READY_STATUS] = 0x17c, + [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, + [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, + [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, }; static const unsigned int qmp_v3_usb3phy_regs_layout[] = { [QPHY_SW_RESET] = 0x00, [QPHY_START_CTRL] = 0x08, [QPHY_PCS_READY_STATUS] = 0x174, + [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, + [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, + [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, }; static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { @@ -539,6 +562,7 @@ struct qmp_phy_cfg { * @tx: iomapped memory space for lane's tx * @rx: iomapped memory space for lane's rx * @pcs: iomapped memory space for lane's pcs + * @pcs_misc: iomapped memory space for lane's pcs_misc * @pipe_clk: pipe lock * @index: lane index * @qmp: QMP phy to which this lane belongs @@ -549,6 +573,7 @@ struct qmp_phy { void __iomem *tx; void __iomem *rx; void __iomem *pcs; + void __iomem *pcs_misc; struct clk *pipe_clk; unsigned int index; struct qcom_qmp *qmp; @@ -587,6 +612,7 @@ struct qcom_qmp { struct mutex phy_mutex; int init_count; + bool phy_initialized; enum phy_mode mode; }; @@ -784,6 +810,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; void __iomem *serdes = qmp->serdes; + void __iomem *dp_com = qmp->dp_com; int ret, i; mutex_lock(&qmp->phy_mutex); @@ -993,6 +1020,7 @@ static int qcom_qmp_phy_init(struct phy *phy) dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret); goto err_pcs_ready; } + qmp->phy_initialized = true; return 0; @@ -1027,6 +1055,135 @@ static int qcom_qmp_phy_exit(struct phy *phy) qcom_qmp_phy_com_exit(qmp); + qmp->phy_initialized = false; + + return 0; +} + +static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) +{ + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qmp->cfg; + void __iomem *pcs = qphy->pcs; + void __iomem *pcs_misc = qphy->pcs_misc; + unsigned int reg; + + /* Clear previous PHY int_status before checking rx_det */ + qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); + /* Writing 1 followed by 0 clears the interrupt */ + qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); + + /* Enable PHY autonomous mode to detect lfps and rx_det detach */ + qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], +ARCVR_DTCT_EN | ALFPS_DTCT_EN); + + /* Enable i/o clamp_n for autonomous mode */ + if (pcs_misc) + qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); + + /* Add delay for int_status to reflect current rx_det state */ + usleep_range(1, 12000); + reg = readl(pcs + cfg->r
[PATCH v2 15/17] phy: qcom-qusb2: Add support for runtime PM
Disable clocks and dp/dm asynchronous interrupts from PHY as part of runtime suspend. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 159 ++ 1 file changed, 159 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 0e9d88b..7414272 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -56,6 +56,18 @@ #define PHY_CLK_SCHEME_SEL BIT(0) +/* QUSB2PHY_INTR_CTRL register bits */ +#define DMSE_INTR_HIGH_SEL BIT(4) +#define DPSE_INTR_HIGH_SEL BIT(3) +#define CHG_DET_INTR_ENBIT(2) +#define DMSE_INTR_EN BIT(1) +#define DPSE_INTR_EN BIT(0) + +/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register bits */ +#define CORE_PLL_EN_FROM_RESET BIT(4) +#define CORE_RESET BIT(5) +#define CORE_RESET_MUX BIT(6) + #defineQUSB2PHY_PLL_ANALOG_CONTROLS_TWO0x04 #defineQUSB2PHY_PLL_CLOCK_INVERTERS0x18c #defineQUSB2PHY_PLL_CMODE 0x2c @@ -73,6 +85,10 @@ #define UTMI_OTG_VBUS_VALIDBIT(20) #define SW_SESSVLD_SEL BIT(28) +#define QSCRATCH_CHARGING_DET_OUTPUT 0x1C +#define LINESTATE_DP BIT(8) +#define LINESTATE_DM BIT(9) + struct qusb2_phy_init_tbl { unsigned int offset; unsigned int val; @@ -98,6 +114,7 @@ struct qusb2_phy_init_tbl { /* set of registers with offsets different per-PHY */ enum qusb2phy_reg_layout { + QUSB2PHY_PLL_CORE_INPUT_OVERRIDE, QUSB2PHY_PLL_STATUS, QUSB2PHY_PORT_TUNE1, QUSB2PHY_PORT_TUNE2, @@ -117,8 +134,10 @@ enum qusb2phy_reg_layout { [QUSB2PHY_PORT_TUNE3] = 0x88, [QUSB2PHY_PORT_TUNE4] = 0x8c, [QUSB2PHY_PORT_TUNE5] = 0x90, + [QUSB2PHY_PORT_TEST1] = 0xb8, [QUSB2PHY_PORT_TEST2] = 0x9c, [QUSB2PHY_PORT_POWERDOWN] = 0xb4, + [QUSB2PHY_INTR_CTRL]= 0xbc, }; static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = { @@ -138,14 +157,17 @@ enum qusb2phy_reg_layout { }; static const unsigned int qusb2_v2_regs_layout[] = { + [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8, [QUSB2PHY_PLL_STATUS] = 0x1a0, [QUSB2PHY_PORT_TUNE1] = 0x240, [QUSB2PHY_PORT_TUNE2] = 0x244, [QUSB2PHY_PORT_TUNE3] = 0x248, [QUSB2PHY_PORT_TUNE4] = 0x24c, [QUSB2PHY_PORT_TUNE5] = 0x250, + [QUSB2PHY_PORT_TEST1] = 0x254, [QUSB2PHY_PORT_TEST2] = 0x258, [QUSB2PHY_PORT_POWERDOWN] = 0x210, + [QUSB2PHY_INTR_CTRL]= 0x230, }; static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = { @@ -180,9 +202,13 @@ struct qusb2_phy_cfg { const unsigned int *regs; unsigned int mask_core_ready; unsigned int disable_ctrl; + unsigned int autoresume_en; /* true if PHY has PLL_TEST register to select clk_scheme */ bool has_pll_test; + + /* true if PHY has PLL_CORE_INPUT_OVERRIDE register to reset PLL */ + bool has_pll_override; }; static const struct qusb2_phy_cfg msm8996_phy_cfg = { @@ -193,6 +219,7 @@ struct qusb2_phy_cfg { .has_pll_test = true, .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), .mask_core_ready = PLL_LOCKED, + .autoresume_en = BIT(3), }; static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = { @@ -203,6 +230,8 @@ struct qusb2_phy_cfg { .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN | POWER_DOWN), .mask_core_ready = CORE_READY_STATUS, + .has_pll_override = true, + .autoresume_en= BIT(0), }; static const char * const qusb2_phy_vreg_names[] = { @@ -229,6 +258,7 @@ struct qusb2_phy_cfg { * * @cfg: phy config data * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme + * @phy_initialized: indicate if PHY has been initialized * @mode: indicate current PHY mode of operation e.g. HOST or DEVICE */ struct qusb2_phy { @@ -247,6 +277,7 @@ struct qusb2_phy { const struct qusb2_phy_cfg *cfg; bool has_se_clk_scheme; + bool phy_initialized; enum phy_mode mode; }; @@ -335,6 +366,115 @@ static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) return 0; } +static int __maybe_unused qusb2_phy_runtime_suspend(struct device *dev) +{ + struct qusb2_phy *qphy = dev_get_drvdata(dev); + const struct qusb2_phy_cfg *cfg = qphy->cfg; + u32 linestate = 0, intr_mask; + + dev_vdbg(dev, "Suspending QUSB2 Phy, mode:%d\
[PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY
QMP V3 USB3 PHY is a DP USB combo PHY with dual RX/TX lanes to support type-c. There is a separate block DP_COM for configuration related to type-c or DP. Add support for dp_com region and secondary rx/tx lanes initialization. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 222 +++- 1 file changed, 219 insertions(+), 3 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 15a734f..d4e1436 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -47,6 +47,21 @@ /* QPHY_COM_PCS_READY_STATUS bit */ #define PCS_READY BIT(0) +/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ +/* DP PHY soft reset */ +#define SW_DPPHY_RESET BIT(0) +/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ +#define SW_DPPHY_RESET_MUX BIT(1) +/* USB3 PHY soft reset */ +#define SW_USB3PHY_RESET BIT(2) +/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ +#define SW_USB3PHY_RESET_MUX BIT(3) + +/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ +#define USB3_MODE BIT(0) /* enables USB3 mode */ +#define DP_MODEBIT(1) /* enables DP mode */ + + #define PHY_INIT_COMPLETE_TIMEOUT 1000 #define POWER_DOWN_DELAY_US_MIN10 #define POWER_DOWN_DELAY_US_MAX11 @@ -122,6 +137,12 @@ enum qphy_reg_layout { [QPHY_PCS_READY_STATUS] = 0x17c, }; +static const unsigned int qmp_v3_usb3phy_regs_layout[] = { + [QPHY_SW_RESET] = 0x00, + [QPHY_START_CTRL] = 0x08, + [QPHY_PCS_READY_STATUS] = 0x174, +}; + static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), @@ -350,6 +371,112 @@ enum qphy_reg_layout { QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), }; +static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { + QMP_PHY_IN
[PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
VBUS signal coming from PHY must be asserted in device for controller to start operation or assert pull-up. For some platforms where VBUS line is not connected to PHY there is HS_PHY_CTRL register in QSCRATCH wrapper that can be used by software to override VBUS signal going to controller. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 39 +++ 1 file changed, 39 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index bda1f4c..0e9d88b 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -68,6 +68,11 @@ #defineQUSB2PHY_IMP_CTRL2 0x224 #defineQUSB2PHY_CHG_CTRL2 0x23c +/* QSCRATCH register bits */ +#define QSCRATCH_HS_PHY_CTRL 0x10 +#define UTMI_OTG_VBUS_VALIDBIT(20) +#define SW_SESSVLD_SEL BIT(28) + struct qusb2_phy_init_tbl { unsigned int offset; unsigned int val; @@ -211,6 +216,7 @@ struct qusb2_phy_cfg { * * @phy: generic phy * @base: iomapped memory space for qubs2 phy + * @qscratch_base: iomapped memory space for qscratch region * * @cfg_ahb_clk: AHB2PHY interface clock * @ref_clk: phy reference clock @@ -223,10 +229,12 @@ struct qusb2_phy_cfg { * * @cfg: phy config data * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme + * @mode: indicate current PHY mode of operation e.g. HOST or DEVICE */ struct qusb2_phy { struct phy *phy; void __iomem *base; + void __iomem *qscratch_base; struct clk *cfg_ahb_clk; struct clk *ref_clk; @@ -239,6 +247,7 @@ struct qusb2_phy { const struct qusb2_phy_cfg *cfg; bool has_se_clk_scheme; + enum phy_mode mode; }; static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val) @@ -307,6 +316,25 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4); } +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) +{ + struct qusb2_phy *qphy = phy_get_drvdata(phy); + + qphy->mode = mode; + + /* Update VBUS override in qscratch register */ + if (qphy->qscratch_base) { + if (mode == PHY_MODE_USB_DEVICE) + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); + else + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); + } + + return 0; +} + static int qusb2_phy_init(struct phy *phy) { struct qusb2_phy *qphy = phy_get_drvdata(phy); @@ -473,6 +501,7 @@ static int qusb2_phy_exit(struct phy *phy) static const struct phy_ops qusb2_phy_gen_ops = { .init = qusb2_phy_init, .exit = qusb2_phy_exit, + .set_mode = qusb2_phy_set_mode, .owner = THIS_MODULE, }; @@ -507,6 +536,16 @@ static int qusb2_phy_probe(struct platform_device *pdev) if (IS_ERR(qphy->base)) return PTR_ERR(qphy->base); + /* Check if platform uses qscratch wrapper */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qscratch"); + if (res) { + /* Can't request region as used by other phy and glue drivers */ + qphy->qscratch_base = devm_ioremap(dev, res->start, + resource_size(res)); + if (IS_ERR(qphy->qscratch_base)) + return PTR_ERR(qphy->qscratch_base); + } + qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb"); if (IS_ERR(qphy->cfg_ahb_clk)) { ret = PTR_ERR(qphy->cfg_ahb_clk); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 12/17] dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY
Update compatible string and clock names for QMP version V3 USB PHY. Signed-off-by: Manu Gautam --- Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt index b6a9f2b..dcf1b8f 100644 --- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt @@ -8,7 +8,8 @@ Required properties: - compatible: compatible list, contains: "qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074 "qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996, - "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996. + "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996, + "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy. - reg: offset and length of register set for PHY's common serdes block. @@ -25,10 +26,13 @@ Required properties: - clock-names: "cfg_ahb" for phy config clock, "aux" for phy aux clock, "ref" for 19.2 MHz ref clk, + "com_aux" for phy common block aux clock, For "qcom,msm8996-qmp-pcie-phy" must contain: "aux", "cfg_ahb", "ref". For "qcom,msm8996-qmp-usb3-phy" must contain: "aux", "cfg_ahb", "ref". + For "qcom,qmp-v3-usb3-phy" must contain: + "aux", "cfg_ahb", "ref", "com_aux". - resets: a list of phandles and reset controller specifier pairs, one for each entry in reset-names. -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 10/17] phy: qcom-qmp: Move register offsets to header file
New revision (v3) of QMP PHY uses different offsets for almost all of the registers. Hence, move these definitions to header file so that updated offsets can be added for QMP v3. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 119 +-- drivers/phy/qualcomm/phy-qcom-qmp.h | 137 2 files changed, 138 insertions(+), 118 deletions(-) create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp.h diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 263cf50..15a734f 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -31,124 +31,7 @@ #include -/* QMP PHY QSERDES COM registers */ -#define QSERDES_COM_BG_TIMER 0x00c -#define QSERDES_COM_SSC_EN_CENTER 0x010 -#define QSERDES_COM_SSC_ADJ_PER1 0x014 -#define QSERDES_COM_SSC_ADJ_PER2 0x018 -#define QSERDES_COM_SSC_PER1 0x01c -#define QSERDES_COM_SSC_PER2 0x020 -#define QSERDES_COM_SSC_STEP_SIZE1 0x024 -#define QSERDES_COM_SSC_STEP_SIZE2 0x028 -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN0x034 -#define QSERDES_COM_CLK_ENABLE10x038 -#define QSERDES_COM_SYS_CLK_CTRL 0x03c -#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040 -#define QSERDES_COM_PLL_IVCO 0x048 -#define QSERDES_COM_LOCK_CMP1_MODE00x04c -#define QSERDES_COM_LOCK_CMP2_MODE00x050 -#define QSERDES_COM_LOCK_CMP3_MODE00x054 -#define QSERDES_COM_LOCK_CMP1_MODE10x058 -#define QSERDES_COM_LOCK_CMP2_MODE10x05c -#define QSERDES_COM_LOCK_CMP3_MODE10x060 -#define QSERDES_COM_BG_TRIM0x070 -#define QSERDES_COM_CLK_EP_DIV 0x074 -#define QSERDES_COM_CP_CTRL_MODE0 0x078 -#define QSERDES_COM_CP_CTRL_MODE1 0x07c -#define QSERDES_COM_PLL_RCTRL_MODE00x084 -#define QSERDES_COM_PLL_RCTRL_MODE10x088 -#define QSERDES_COM_PLL_CCTRL_MODE00x090 -#define QSERDES_COM_PLL_CCTRL_MODE10x094 -#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM0x0a8 -#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac -#define QSERDES_COM_RESETSM_CNTRL 0x0b4 -#define QSERDES_COM_RESTRIM_CTRL 0x0bc -#define QSERDES_COM_RESCODE_DIV_NUM0x0c4 -#define QSERDES_COM_LOCK_CMP_EN0x0c8 -#define QSERDES_COM_LOCK_CMP_CFG 0x0cc -#define QSERDES_COM_DEC_START_MODE00x0d0 -#define QSERDES_COM_DEC_START_MODE10x0d4 -#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc -#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0 -#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4 -#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8 -#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec -#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0 -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114 -#define QSERDES_COM_VCO_TUNE_CTRL 0x124 -#define QSERDES_COM_VCO_TUNE_MAP 0x128 -#define QSERDES_COM_VCO_TUNE1_MODE00x12c -#define QSERDES_COM_VCO_TUNE2_MODE00x130 -#define QSERDES_COM_VCO_TUNE1_MODE10x134 -#define QSERDES_COM_VCO_TUNE2_MODE10x138 -#define QSERDES_COM_VCO_TUNE_TIMER10x144 -#define QSERDES_COM_VCO_TUNE_TIMER20x148 -#define QSERDES_COM_BG_CTRL0x170 -#define QSERDES_COM_CLK_SELECT 0x174 -#define QSERDES_COM_HSCLK_SEL 0x178 -#define QSERDES_COM_CORECLK_DIV0x184 -#define QSERDES_COM_CORE_CLK_EN0x18c -#define QSERDES_COM_C_READY_STATUS 0x190 -#define QSERDES_COM_CMN_CONFIG 0x194 -#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c -#define QSERDES_COM_DEBUG_BUS0 0x1a0 -#define QSERDES_COM_DEBUG_BUS1 0x1a4 -#define QSERDES_COM_DEBUG_BUS2 0x1a8 -#define QSERDES_COM_DEBUG_BUS3 0x1ac -#define QSERDES_COM_DEBUG_BUS_SEL 0x1b0 -#define QSERDES_COM_CORECLK_DIV_MODE1
[PATCH v2 11/17] phy: qcom-qmp: Add register offsets for QMP V3 PHY
Registers offsets for QMP V3 PHY are changed from previous versions (1/2), update same in header file. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.h | 149 1 file changed, 149 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index d930ca7..f7d4c2a 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -134,4 +134,153 @@ #define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC #define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0 +/* Only for QMP V3 PHY - DP COM registers */ +#define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00 +#define QPHY_V3_DP_COM_SW_RESET0x04 +#define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08 +#define QPHY_V3_DP_COM_SWI_CTRL0x0c +#define QPHY_V3_DP_COM_TYPEC_CTRL 0x10 +#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL0x14 +#define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c + +/* Only for QMP V3 PHY - QSERDES COM registers */ +#define QSERDES_V3_COM_BG_TIMER0x00c +#define QSERDES_V3_COM_SSC_EN_CENTER 0x010 +#define QSERDES_V3_COM_SSC_ADJ_PER10x014 +#define QSERDES_V3_COM_SSC_ADJ_PER20x018 +#define QSERDES_V3_COM_SSC_PER10x01c +#define QSERDES_V3_COM_SSC_PER20x020 +#define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024 +#define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028 +#define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034 +#define QSERDES_V3_COM_CLK_ENABLE1 0x038 +#define QSERDES_V3_COM_SYS_CLK_CTRL0x03c +#define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040 +#define QSERDES_V3_COM_PLL_IVCO0x048 +#define QSERDES_V3_COM_LOCK_CMP1_MODE0 0x098 +#define QSERDES_V3_COM_LOCK_CMP2_MODE0 0x09c +#define QSERDES_V3_COM_LOCK_CMP3_MODE0 0x0a0 +#define QSERDES_V3_COM_LOCK_CMP1_MODE1 0x0a4 +#define QSERDES_V3_COM_LOCK_CMP2_MODE1 0x0a8 +#define QSERDES_V3_COM_LOCK_CMP3_MODE1 0x0ac +#define QSERDES_V3_COM_CLK_EP_DIV 0x05c +#define QSERDES_V3_COM_CP_CTRL_MODE0 0x060 +#define QSERDES_V3_COM_CP_CTRL_MODE1 0x064 +#define QSERDES_V3_COM_PLL_RCTRL_MODE0 0x068 +#define QSERDES_V3_COM_PLL_RCTRL_MODE1 0x06c +#define QSERDES_V3_COM_PLL_CCTRL_MODE0 0x070 +#define QSERDES_V3_COM_PLL_CCTRL_MODE1 0x074 +#define QSERDES_V3_COM_SYSCLK_EN_SEL 0x080 +#define QSERDES_V3_COM_RESETSM_CNTRL 0x088 +#define QSERDES_V3_COM_RESETSM_CNTRL2 0x08c +#define QSERDES_V3_COM_LOCK_CMP_EN 0x090 +#define QSERDES_V3_COM_LOCK_CMP_CFG0x094 +#define QSERDES_V3_COM_DEC_START_MODE0 0x0b0 +#define QSERDES_V3_COM_DEC_START_MODE1 0x0b4 +#define QSERDES_V3_COM_DIV_FRAC_START1_MODE0 0x0b8 +#define QSERDES_V3_COM_DIV_FRAC_START2_MODE0 0x0bc +#define QSERDES_V3_COM_DIV_FRAC_START3_MODE0 0x0c0 +#define QSERDES_V3_COM_DIV_FRAC_START1_MODE1 0x0c4 +#define QSERDES_V3_COM_DIV_FRAC_START2_MODE1 0x0c8 +#define QSERDES_V3_COM_DIV_FRAC_START3_MODE1 0x0cc +#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0 0x0d8 +#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0 0x0dc +#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1 0x0e0 +#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1 0x0e4 +#define QSERDES_V3_COM_VCO_TUNE_CTRL 0x0ec +#define QSERDES_V3_COM_VCO_TUNE_MAP0x0f0 +#define QSERDES_V3_COM_VCO_TUNE1_MODE0 0x0f4 +#define QSERDES_V3_COM_VCO_TUNE2_MODE0 0x0f8 +#define QSERDES_V3_COM_VCO_TUNE1_MODE1 0x0fc +#define QSERDES_V3_COM_VCO_TUNE2_MODE1 0x100 +#define QSERDES_V3_COM_VCO_TUNE_TIMER1 0x11c +#define QSERDES_V3_COM_VCO_TUNE_TIMER2 0x120 +#define QSERDES_V3_COM_CLK_SELECT 0x138 +#define QSERDES_V3_COM_HSCLK_SEL 0x13c +#define QSERDES_V3_COM_CORECLK_DIV_MODE0 0x148 +#define QSERDES_V3_COM_CORECLK_DIV_MODE1 0x14c +#define QSERDES_V3_COM_CORE_CLK_EN 0x154 +#define QSERDES_V3_COM_C_READY_STATUS 0x158 +#define QSERDES_V3_COM_CMN_CONFIG 0x15c +#define QSERDES_V3_COM_SVS_MODE_CLK_SEL0x164 +#define QSERDES_V3_COM_DEBUG_BUS0 0x168 +#define QSERDES_V3_COM_DEBUG_BUS1 0x16c +#define QSERDES_V3_COM_D
[PATCH v2 07/17] phy: qcom-qusb2: Add support for different register layouts
New version of QUSB2 PHY has some registers offset changed. Add support to have register layout for a target and update the same in phy_configuration. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 131 -- 1 file changed, 95 insertions(+), 36 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 4a5b2a1..c0c5358 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -37,17 +37,10 @@ #define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1c #define QUSB2PHY_PLL_PWR_CTRL 0x18 -#define QUSB2PHY_PLL_STATUS0x38 +/* QUSB2PHY_PLL_STATUS register bits */ #define PLL_LOCKED BIT(5) -#define QUSB2PHY_PORT_TUNE10x80 -#define QUSB2PHY_PORT_TUNE20x84 -#define QUSB2PHY_PORT_TUNE30x88 -#define QUSB2PHY_PORT_TUNE40x8c -#define QUSB2PHY_PORT_TUNE50x90 -#define QUSB2PHY_PORT_TEST20x9c - -#define QUSB2PHY_PORT_POWERDOWN0xb4 +/* QUSB2PHY_PORT_POWERDOWN register bits */ #define CLAMP_N_EN BIT(5) #define FREEZIO_N BIT(1) #define POWER_DOWN BIT(0) @@ -59,6 +52,11 @@ struct qusb2_phy_init_tbl { unsigned int offset; unsigned int val; + /* +* register part of layout ? +* if yes, then offset gives index in the reg-layout +*/ + int in_layout; }; #define QUSB2_PHY_INIT_CFG(o, v) \ @@ -67,15 +65,50 @@ struct qusb2_phy_init_tbl { .val = v, \ } +#define QUSB2_PHY_INIT_CFG_L(o, v) \ + { \ + .offset = o,\ + .val = v, \ + .in_layout = 1, \ + } + +/* set of registers with offsets different per-PHY */ +enum qusb2phy_reg_layout { + QUSB2PHY_PLL_STATUS, + QUSB2PHY_PORT_TUNE1, + QUSB2PHY_PORT_TUNE2, + QUSB2PHY_PORT_TUNE3, + QUSB2PHY_PORT_TUNE4, + QUSB2PHY_PORT_TUNE5, + QUSB2PHY_PORT_TEST1, + QUSB2PHY_PORT_TEST2, + QUSB2PHY_PORT_POWERDOWN, + QUSB2PHY_INTR_CTRL, +}; + +static const unsigned int msm8996_regs_layout[] = { + [QUSB2PHY_PLL_STATUS] = 0x38, + [QUSB2PHY_PORT_TUNE1] = 0x80, + [QUSB2PHY_PORT_TUNE2] = 0x84, + [QUSB2PHY_PORT_TUNE3] = 0x88, + [QUSB2PHY_PORT_TUNE4] = 0x8c, + [QUSB2PHY_PORT_TUNE5] = 0x90, + [QUSB2PHY_PORT_TEST2] = 0x9c, + [QUSB2PHY_PORT_POWERDOWN] = 0xb4, +}; + static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = { - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8), - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3), - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83), - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30), QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79), QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21), - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14), + + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f), QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), }; @@ -86,11 +119,24 @@ struct qusb2_phy_cfg { unsigned int tbl_num; /* offset to PHY_CLK_SCHEME register in TCSR map */ unsigned int clk_scheme_offset; + + /* array of registers with different offsets */ + const unsigned int *regs; + unsigned int mask_core_ready; + unsigned int disable_ctrl; + + /* true if PHY has PLL_TEST register to select clk_scheme */ + bool has_pll_test; }; static const struct qusb2_phy_cfg msm8996_phy_cfg = { - .tbl = msm8996_init_tbl, - .tbl_num = ARRAY_SIZE(msm8996_init_tbl), + .tbl= msm8996_init_tbl, + .tbl_num= ARRAY_SIZE(msm8996_init_tbl), + .regs = msm8996_regs_layout, + + .has_pll_test = true, + .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), + .mask_core_ready = PLL_LOCKED, }; static const char * const qusb2_phy_vreg_names[] = { @@ -160,12 +206,17 @@ static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val) static inline void qcom_qusb2_phy_configure(void __iomem *base, + const unsigned int *regs, const struct qusb2_phy_init_tbl tbl[], int num) { int i; - for (i = 0; i < num; i++) - writel(tbl[i].val, base + tbl[i].offset); + for (i = 0; i < num; i++) { + if (tbl[i].in
[PATCH v2 09/17] phy: qcom-qusb2: Add support for QUSB2 V2 version
Use register layout to add additional registers present on QUSB2 PHY V2 version for PHY initialization. Other than new registers on V2, following two register's offset and bit definitions are different: POWERDOWN control and PLL_STATUS. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 64 +++ 1 file changed, 64 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index c0c5358..bda1f4c 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -40,15 +40,34 @@ /* QUSB2PHY_PLL_STATUS register bits */ #define PLL_LOCKED BIT(5) +/* QUSB2PHY_PLL_COMMON_STATUS_ONE register bits */ +#define CORE_READY_STATUS BIT(0) + /* QUSB2PHY_PORT_POWERDOWN register bits */ #define CLAMP_N_EN BIT(5) #define FREEZIO_N BIT(1) #define POWER_DOWN BIT(0) +/* QUSB2PHY_PWR_CTRL1 register bits */ +#define PWR_CTRL1_VREF_SUPPLY_TRIM BIT(5) +#define PWR_CTRL1_CLAMP_N_EN BIT(1) + #define QUSB2PHY_REFCLK_ENABLE BIT(0) #define PHY_CLK_SCHEME_SEL BIT(0) +#defineQUSB2PHY_PLL_ANALOG_CONTROLS_TWO0x04 +#defineQUSB2PHY_PLL_CLOCK_INVERTERS0x18c +#defineQUSB2PHY_PLL_CMODE 0x2c +#defineQUSB2PHY_PLL_LOCK_DELAY 0x184 +#defineQUSB2PHY_PLL_DIGITAL_TIMERS_TWO 0xb4 +#defineQUSB2PHY_PLL_BIAS_CONTROL_1 0x194 +#defineQUSB2PHY_PLL_BIAS_CONTROL_2 0x198 +#defineQUSB2PHY_PWR_CTRL2 0x214 +#defineQUSB2PHY_IMP_CTRL1 0x220 +#defineQUSB2PHY_IMP_CTRL2 0x224 +#defineQUSB2PHY_CHG_CTRL2 0x23c + struct qusb2_phy_init_tbl { unsigned int offset; unsigned int val; @@ -113,6 +132,38 @@ enum qusb2phy_reg_layout { QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), }; +static const unsigned int qusb2_v2_regs_layout[] = { + [QUSB2PHY_PLL_STATUS] = 0x1a0, + [QUSB2PHY_PORT_TUNE1] = 0x240, + [QUSB2PHY_PORT_TUNE2] = 0x244, + [QUSB2PHY_PORT_TUNE3] = 0x248, + [QUSB2PHY_PORT_TUNE4] = 0x24c, + [QUSB2PHY_PORT_TUNE5] = 0x250, + [QUSB2PHY_PORT_TEST2] = 0x258, + [QUSB2PHY_PORT_POWERDOWN] = 0x210, +}; + +static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = { + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_LOCK_DELAY, 0x0a), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_BIAS_CONTROL_1, 0x40), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_BIAS_CONTROL_2, 0x20), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PWR_CTRL2, 0x21), + QUSB2_PHY_INIT_CFG(QUSB2PHY_IMP_CTRL1, 0x0), + QUSB2_PHY_INIT_CFG(QUSB2PHY_IMP_CTRL2, 0x58), + + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0x30), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x29), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0xca), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0x04), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE5, 0x03), + + QUSB2_PHY_INIT_CFG(QUSB2PHY_CHG_CTRL2, 0x0), +}; + struct qusb2_phy_cfg { const struct qusb2_phy_init_tbl *tbl; /* number of entries in the table */ @@ -139,6 +190,16 @@ struct qusb2_phy_cfg { .mask_core_ready = PLL_LOCKED, }; +static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = { + .tbl= qusb2_v2_init_tbl, + .tbl_num= ARRAY_SIZE(qusb2_v2_init_tbl), + .regs = qusb2_v2_regs_layout, + + .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN | + POWER_DOWN), + .mask_core_ready = CORE_READY_STATUS, +}; + static const char * const qusb2_phy_vreg_names[] = { "vdda-pll", "vdda-phy-dpdm", }; @@ -419,6 +480,9 @@ static int qusb2_phy_exit(struct phy *phy) { .compatible = "qcom,msm8996-qusb2-phy", .data = &msm8996_phy_cfg, + }, { + .compatible = "qcom,qusb2-v2-phy", + .data = &qusb2_v2_phy_cfg, }, { }, }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 05/17] phy: qcom-qmp: Fix PHY block reset sequence
PHY block or asynchronous reset requires signal to be asserted before de-asserting. Driver is only de-asserting signal which is already low, hence reset operation is a no-op. Fix this by asserting signal first. Also, resetting requires PHY clocks to be turned ON only after reset is finished. Fix that as well. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 28 +++- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 2f427e3..aa27757 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -739,13 +739,16 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) return ret; } - ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); - if (ret) { - dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); - goto err_clk_enable; + for (i = 0; i < cfg->num_resets; i++) { + ret = reset_control_assert(qmp->resets[i]); + if (ret) { + dev_err(qmp->dev, "%s reset assert failed\n", + cfg->reset_list[i]); + goto err_rst_assert; + } } - for (i = 0; i < cfg->num_resets; i++) { + for (i = cfg->num_resets - 1; i >= 0; i--) { ret = reset_control_deassert(qmp->resets[i]); if (ret) { dev_err(qmp->dev, "%s reset deassert failed\n", @@ -754,6 +757,12 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) } } + ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); + if (ret) { + dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); + goto err_rst; + } + if (cfg->has_phy_com_ctrl) qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], SW_PWRDN); @@ -778,7 +787,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) if (ret) { dev_err(qmp->dev, "phy common block init timed-out\n"); - goto err_rst; + goto err_com_init; } } @@ -786,11 +795,12 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) return 0; +err_com_init: + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); err_rst: - while (--i >= 0) + while (++i < cfg->num_resets) reset_control_assert(qmp->resets[i]); - clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); -err_clk_enable: +err_rst_assert: regulator_bulk_disable(cfg->num_vregs, qmp->vregs); mutex_unlock(&qmp->phy_mutex); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 06/17] phy: qcom-qmp: Move SERDES/PCS START after PHY reset
Driver is currently performing PHY reset after starting SERDES/PCS. As per hardware datasheet reset must be done before starting PHY. Hence, update the sequence. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index aa27757..263cf50 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -882,12 +882,12 @@ static int qcom_qmp_phy_init(struct phy *phy) if (cfg->has_pwrdn_delay) usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); - /* start SerDes and Phy-Coding-Sublayer */ - qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); - /* Pull PHY out of reset state */ qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + /* start SerDes and Phy-Coding-Sublayer */ + qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); + status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; mask = cfg->mask_pcs_ready; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 08/17] dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version
Update generic compatible string for QUSB2 V2 PHY. This will allow all targets using QUSB2 V2 use same string. Signed-off-by: Manu Gautam --- Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt index aa0fcb0..42c9742 100644 --- a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt +++ b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt @@ -4,7 +4,10 @@ Qualcomm QUSB2 phy controller QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets. Required properties: - - compatible: compatible list, contains "qcom,msm8996-qusb2-phy". + - compatible: compatible list, contains + "qcom,msm8996-qusb2-phy" for 14nm PHY on msm8996, + "qcom,qusb2-v2-phy" for QUSB2 V2 PHY. + - reg: offset and length of the PHY register set. - #phy-cells: must be 0. -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 04/17] phy: qcom-qusb2: Power-on PHY before initialization
PHY must be powered on before turning ON clocks and attempting to initialize it. Driver is exposing separate init and power_on routines for this. Apparently USB dwc3 core driver performs power-on after init. Also, poweron and init for QUSB2 PHY need to be executed together always, hence remove poweron callback from phy_ops and explicitly perform this from init, similar changes needed for poweroff. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 47 +++ 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 6c57524..4a5b2a1 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -195,54 +195,31 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4); } -static int qusb2_phy_poweron(struct phy *phy) +static int qusb2_phy_init(struct phy *phy) { struct qusb2_phy *qphy = phy_get_drvdata(phy); - int num = ARRAY_SIZE(qphy->vregs); + unsigned int val; + unsigned int clk_scheme; int ret; - dev_vdbg(&phy->dev, "%s(): Powering-on QUSB2 phy\n", __func__); + dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__); /* turn on regulator supplies */ - ret = regulator_bulk_enable(num, qphy->vregs); + ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs); if (ret) return ret; ret = clk_prepare_enable(qphy->iface_clk); if (ret) { dev_err(&phy->dev, "failed to enable iface_clk, %d\n", ret); - regulator_bulk_disable(num, qphy->vregs); - return ret; + goto poweroff_phy; } - return 0; -} - -static int qusb2_phy_poweroff(struct phy *phy) -{ - struct qusb2_phy *qphy = phy_get_drvdata(phy); - - clk_disable_unprepare(qphy->iface_clk); - - regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); - - return 0; -} - -static int qusb2_phy_init(struct phy *phy) -{ - struct qusb2_phy *qphy = phy_get_drvdata(phy); - unsigned int val; - unsigned int clk_scheme; - int ret; - - dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__); - /* enable ahb interface clock to program phy */ ret = clk_prepare_enable(qphy->cfg_ahb_clk); if (ret) { dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret); - return ret; + goto disable_iface_clk; } /* Perform phy reset */ @@ -344,6 +321,11 @@ static int qusb2_phy_init(struct phy *phy) reset_control_assert(qphy->phy_reset); disable_ahb_clk: clk_disable_unprepare(qphy->cfg_ahb_clk); +disable_iface_clk: + clk_disable_unprepare(qphy->iface_clk); +poweroff_phy: + regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); + return ret; } @@ -361,6 +343,9 @@ static int qusb2_phy_exit(struct phy *phy) reset_control_assert(qphy->phy_reset); clk_disable_unprepare(qphy->cfg_ahb_clk); + clk_disable_unprepare(qphy->iface_clk); + + regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); return 0; } @@ -368,8 +353,6 @@ static int qusb2_phy_exit(struct phy *phy) static const struct phy_ops qusb2_phy_gen_ops = { .init = qusb2_phy_init, .exit = qusb2_phy_exit, - .power_on = qusb2_phy_poweron, - .power_off = qusb2_phy_poweroff, .owner = THIS_MODULE, }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 02/17] phy: qcom-qmp: Adapt to clk_bulk_* APIs
From: Vivek Gautam Move from using array of clocks to clk_bulk_* APIs that are available now. Signed-off-by: Vivek Gautam Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 50 - 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 76acaec..90794dd 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -555,7 +555,7 @@ struct qcom_qmp { struct device *dev; void __iomem *serdes; - struct clk **clks; + struct clk_bulk_data *clks; struct reset_control **resets; struct regulator_bulk_data *vregs; @@ -848,22 +848,19 @@ static int qcom_qmp_phy_init(struct phy *phy) void __iomem *pcs = qphy->pcs; void __iomem *status; unsigned int mask, val; - int ret, i; + int ret; dev_vdbg(qmp->dev, "Initializing QMP phy\n"); - for (i = 0; i < qmp->cfg->num_clks; i++) { - ret = clk_prepare_enable(qmp->clks[i]); - if (ret) { - dev_err(qmp->dev, "failed to enable %s clk, err=%d\n", - qmp->cfg->clk_list[i], ret); - goto err_clk; - } + ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); + if (ret) { + dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); + return ret; } ret = qcom_qmp_phy_com_init(qmp); if (ret) - goto err_clk; + goto err_com_init; if (cfg->has_lane_rst) { ret = reset_control_deassert(qphy->lane_rst); @@ -918,9 +915,8 @@ static int qcom_qmp_phy_init(struct phy *phy) reset_control_assert(qphy->lane_rst); err_lane_rst: qcom_qmp_phy_com_exit(qmp); -err_clk: - while (--i >= 0) - clk_disable_unprepare(qmp->clks[i]); +err_com_init: + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); return ret; } @@ -930,7 +926,6 @@ static int qcom_qmp_phy_exit(struct phy *phy) struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qmp->cfg; - int i = cfg->num_clks; clk_disable_unprepare(qphy->pipe_clk); @@ -948,8 +943,7 @@ static int qcom_qmp_phy_exit(struct phy *phy) qcom_qmp_phy_com_exit(qmp); - while (--i >= 0) - clk_disable_unprepare(qmp->clks[i]); + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); return 0; } @@ -998,29 +992,17 @@ static int qcom_qmp_phy_reset_init(struct device *dev) static int qcom_qmp_phy_clk_init(struct device *dev) { struct qcom_qmp *qmp = dev_get_drvdata(dev); - int ret, i; + int num = qmp->cfg->num_clks; + int i; - qmp->clks = devm_kcalloc(dev, qmp->cfg->num_clks, -sizeof(*qmp->clks), GFP_KERNEL); + qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); if (!qmp->clks) return -ENOMEM; - for (i = 0; i < qmp->cfg->num_clks; i++) { - struct clk *_clk; - const char *name = qmp->cfg->clk_list[i]; - - _clk = devm_clk_get(dev, name); - if (IS_ERR(_clk)) { - ret = PTR_ERR(_clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get %s clk, %d\n", - name, ret); - return ret; - } - qmp->clks[i] = _clk; - } + for (i = 0; i < num; i++) + qmp->clks->id = qmp->cfg->clk_list[i]; - return 0; + return devm_clk_bulk_get(dev, num, qmp->clks); } /* -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 01/17] phy: qcom-qmp: Fix phy pipe clock gating
From: Vivek Gautam Pipe clock comes out of the phy and is available as long as the phy is turned on. Clock controller fails to gate this clock after the phy is turned off and generates a warning. / # [ 33.048561] gcc_usb3_phy_pipe_clk status stuck at 'on' [ 33.048585] [ cut here ] [ 33.052621] WARNING: CPU: 1 PID: 18 at ../drivers/clk/qcom/clk-branch.c:97 clk_branch_wait+0xf0/0x108 [ 33.057384] Modules linked in: [ 33.066497] CPU: 1 PID: 18 Comm: kworker/1:0 Tainted: GW 4.12.0-rc7-00024-gfe926e34c36d-dirty #96 [ 33.069451] Hardware name: Qualcomm Technologies, Inc. DB820c (DT) ... [ 33.278565] [] clk_branch_wait+0xf0/0x108 [ 33.286375] [] clk_branch2_disable+0x28/0x34 [ 33.291761] [] clk_core_disable+0x5c/0x88 [ 33.297660] [] clk_core_disable_lock+0x20/0x34 [ 33.303129] [] clk_disable+0x1c/0x24 [ 33.309384] [] qcom_qmp_phy_poweroff+0x20/0x48 [ 33.314328] [] phy_power_off+0x80/0xdc [ 33.320492] [] dwc3_core_exit+0x94/0xa0 [ 33.325784] [] dwc3_suspend_common+0x50/0x60 [ 33.331080] [] dwc3_runtime_suspend+0x48/0x6c [ 33.336810] [] pm_generic_runtime_suspend+0x28/0x38 [ 33.342627] [] __rpm_callback+0x150/0x254 [ 33.349222] [] rpm_callback+0x24/0x78 [ 33.354604] [] rpm_suspend+0xe0/0x4e4 [ 33.359813] [] pm_runtime_work+0xdc/0xf0 [ 33.365028] [] process_one_work+0x12c/0x28c [ 33.370576] [] worker_thread+0x58/0x3b8 [ 33.376393] [] kthread+0x100/0x12c [ 33.381776] [] ret_from_fork+0x10/0x50 Fix this by enabling pipe clock at the end of phy_init(), and disabling it as the first thing in phy_exit(). Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") Signed-off-by: Vivek Gautam Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 26 -- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index e17f035..76acaec 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -731,19 +731,10 @@ static int qcom_qmp_phy_poweron(struct phy *phy) /* turn on regulator supplies */ ret = regulator_bulk_enable(num, qmp->vregs); - if (ret) { + if (ret) dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); - return ret; - } - - ret = clk_prepare_enable(qphy->pipe_clk); - if (ret) { - dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret); - regulator_bulk_disable(num, qmp->vregs); - return ret; - } - return 0; + return ret; } static int qcom_qmp_phy_poweroff(struct phy *phy) @@ -751,8 +742,6 @@ static int qcom_qmp_phy_poweroff(struct phy *phy) struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; - clk_disable_unprepare(qphy->pipe_clk); - regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs); return 0; @@ -915,7 +904,14 @@ static int qcom_qmp_phy_init(struct phy *phy) goto err_pcs_ready; } - return ret; + /* phy is initialized; we can turn on the pipe clock now */ + ret = clk_prepare_enable(qphy->pipe_clk); + if (ret) { + dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret); + goto err_pcs_ready; + } + + return 0; err_pcs_ready: if (cfg->has_lane_rst) @@ -936,6 +932,8 @@ static int qcom_qmp_phy_exit(struct phy *phy) const struct qmp_phy_cfg *cfg = qmp->cfg; int i = cfg->num_clks; + clk_disable_unprepare(qphy->pipe_clk); + /* PHY reset */ qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 03/17] phy: qcom-qmp: Power-on PHY before initialization
PHY must be powered on before turning ON clocks and attempting to initialize it. Driver is exposing separate init and power_on routines for this. Apparently USB dwc3 core driver performs power-on after init. Also, poweron and init for QMP PHY need to be executed together always, hence remove poweron callback from phy_ops and explicitly perform this from com_init, similar changes needed for poweroff. On similar lines move clk_enable from init to com_init which can be called once for multi lane PHYs. Signed-off-by: Manu Gautam --- drivers/phy/qualcomm/phy-qcom-qmp.c | 61 + 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 90794dd..2f427e3 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -720,33 +720,6 @@ static void qcom_qmp_phy_configure(void __iomem *base, } } -static int qcom_qmp_phy_poweron(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - struct qcom_qmp *qmp = qphy->qmp; - int num = qmp->cfg->num_vregs; - int ret; - - dev_vdbg(&phy->dev, "Powering on QMP phy\n"); - - /* turn on regulator supplies */ - ret = regulator_bulk_enable(num, qmp->vregs); - if (ret) - dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); - - return ret; -} - -static int qcom_qmp_phy_poweroff(struct phy *phy) -{ - struct qmp_phy *qphy = phy_get_drvdata(phy); - struct qcom_qmp *qmp = qphy->qmp; - - regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs); - - return 0; -} - static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; @@ -759,6 +732,19 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) return 0; } + /* turn on regulator supplies */ + ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); + if (ret) { + mutex_unlock(&qmp->phy_mutex); + return ret; + } + + ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); + if (ret) { + dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); + goto err_clk_enable; + } + for (i = 0; i < cfg->num_resets; i++) { ret = reset_control_deassert(qmp->resets[i]); if (ret) { @@ -803,6 +789,9 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) err_rst: while (--i >= 0) reset_control_assert(qmp->resets[i]); + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); +err_clk_enable: + regulator_bulk_disable(cfg->num_vregs, qmp->vregs); mutex_unlock(&qmp->phy_mutex); return ret; @@ -832,6 +821,10 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) while (--i >= 0) reset_control_assert(qmp->resets[i]); + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); + + regulator_bulk_disable(cfg->num_vregs, qmp->vregs); + mutex_unlock(&qmp->phy_mutex); return 0; @@ -852,15 +845,9 @@ static int qcom_qmp_phy_init(struct phy *phy) dev_vdbg(qmp->dev, "Initializing QMP phy\n"); - ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); - if (ret) { - dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); - return ret; - } - ret = qcom_qmp_phy_com_init(qmp); if (ret) - goto err_com_init; + return ret; if (cfg->has_lane_rst) { ret = reset_control_deassert(qphy->lane_rst); @@ -915,8 +902,6 @@ static int qcom_qmp_phy_init(struct phy *phy) reset_control_assert(qphy->lane_rst); err_lane_rst: qcom_qmp_phy_com_exit(qmp); -err_com_init: - clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); return ret; } @@ -943,8 +928,6 @@ static int qcom_qmp_phy_exit(struct phy *phy) qcom_qmp_phy_com_exit(qmp); - clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); - return 0; } @@ -1057,8 +1040,6 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) static const struct phy_ops qcom_qmp_phy_gen_ops = { .init = qcom_qmp_phy_init, .exit = qcom_qmp_phy_exit, - .power_on = qcom_qmp_phy_poweron, - .power_off = qcom_qmp_phy_poweroff, .owner = THIS_MODULE, }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/9] usb: xhci-mtk: check clock stability of U3_MAC
This is useful to find out the root cause when the Super Speed doesn't work. Such as when the T-PHY is switched to PCIe or SATA, and affects Super Speed function, the check will fail. Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-mtk.c |4 1 file changed, 4 insertions(+) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 9502ca4..7a92bb7 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -43,6 +43,7 @@ /* ip_pw_sts1 register */ #define STS1_IP_SLEEP_STS BIT(30) +#define STS1_U3_MAC_RSTBIT(16) #define STS1_XHCI_RST BIT(11) #define STS1_SYS125_RSTBIT(10) #define STS1_REF_RST BIT(8) @@ -125,6 +126,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) check_val = STS1_SYSPLL_STABLE | STS1_REF_RST | STS1_SYS125_RST | STS1_XHCI_RST; + if (mtk->num_u3_ports) + check_val |= STS1_U3_MAC_RST; + ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, (check_val == (value & check_val)), 100, 2); if (ret) { -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/9] usb: xhci-mtk: add optional mcu and dma bus clocks
There are mcu_bus and dma_bus clocks needed to be controlled by driver on some SoCs, so add them as optional ones Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-mtk.c | 79 --- drivers/usb/host/xhci-mtk.h |2 ++ 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index d60463c..e5caabe 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -221,6 +221,44 @@ 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; + + mtk->sys_clk = devm_clk_get(dev, "sys_ck"); + if (IS_ERR(mtk->sys_clk)) { + dev_err(dev, "fail to get sys_ck\n"); + return PTR_ERR(mtk->sys_clk); + } + + mtk->ref_clk = optional_clk_get(dev, "ref_ck"); + if (IS_ERR(mtk->ref_clk)) + return PTR_ERR(mtk->ref_clk); + + mtk->mcu_clk = optional_clk_get(dev, "mcu_ck"); + if (IS_ERR(mtk->mcu_clk)) + return PTR_ERR(mtk->mcu_clk); + + mtk->dma_clk = optional_clk_get(dev, "dma_ck"); + if (IS_ERR(mtk->dma_clk)) + return PTR_ERR(mtk->dma_clk); + + return 0; +} + static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) { int ret; @@ -237,16 +275,34 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) goto sys_clk_err; } + ret = clk_prepare_enable(mtk->mcu_clk); + if (ret) { + dev_err(mtk->dev, "failed to enable mcu_clk\n"); + goto mcu_clk_err; + } + + ret = clk_prepare_enable(mtk->dma_clk); + if (ret) { + dev_err(mtk->dev, "failed to enable dma_clk\n"); + goto dma_clk_err; + } + return 0; +dma_clk_err: + clk_disable_unprepare(mtk->mcu_clk); +mcu_clk_err: + clk_disable_unprepare(mtk->sys_clk); sys_clk_err: clk_disable_unprepare(mtk->ref_clk); ref_clk_err: - return -EINVAL; + return ret; } static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) { + clk_disable_unprepare(mtk->dma_clk); + clk_disable_unprepare(mtk->mcu_clk); clk_disable_unprepare(mtk->sys_clk); clk_disable_unprepare(mtk->ref_clk); } @@ -529,24 +585,9 @@ static int xhci_mtk_probe(struct platform_device *pdev) return PTR_ERR(mtk->vusb33); } - mtk->sys_clk = devm_clk_get(dev, "sys_ck"); - if (IS_ERR(mtk->sys_clk)) { - dev_err(dev, "fail to get sys_ck\n"); - return PTR_ERR(mtk->sys_clk); - } - - /* -* reference clock is usually a "fixed-clock", make it optional -* for backward compatibility and ignore the error if it does -* not exist. -*/ - mtk->ref_clk = devm_clk_get(dev, "ref_ck"); - if (IS_ERR(mtk->ref_clk)) { - if (PTR_ERR(mtk->ref_clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - mtk->ref_clk = NULL; - } + ret = xhci_mtk_clks_get(mtk); + if (ret) + return ret; mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable"); /* optional property, ignore the error if it does not exist */ diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index 67783a7..45ff5c6 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -126,6 +126,8 @@ struct xhci_hcd_mtk { struct regulator *vbus; struct clk *sys_clk;/* sys and mac clock */ struct clk *ref_clk; + struct clk *mcu_clk; + struct clk *dma_clk; struct regmap *pericfg; struct phy **phys; int num_phys; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 8/9] dt-bindings: usb: mtk-xhci: add a optional property to disable u3ports
Add a new optional property to disable u3ports Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/usb/mediatek,mtk-xhci.txt |2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt index 5611a2e..2d9b459 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt @@ -38,6 +38,8 @@ Optional properties: mode; - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup control register, it depends on "mediatek,wakeup-src". + - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, + bit1 for u3port1, ... etc; - vbus-supply : reference to the VBUS regulator; - usb3-lpm-capable : supports USB3.0 LPM - pinctrl-names : a pinctrl state named "default" must be defined -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 9/9] dt-bindings: usb: mtk-xhci: remove dummy clocks and add optional ones
Remove dummy clocks for usb wakeup and add optional ones for MCU_BUS_CK and DMA_BUS_CK. Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/usb/mediatek,mtk-xhci.txt | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt index 2d9b459..3059596 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt @@ -26,10 +26,11 @@ Required properties: - clocks : a list of phandle + clock-specifier pairs, one for each entry in clock-names - clock-names : must contain - "sys_ck": for clock of xHCI MAC - "ref_ck": for reference clock of xHCI MAC - "wakeup_deb_p0": for USB wakeup debounce clock of port0 - "wakeup_deb_p1": for USB wakeup debounce clock of port1 + "sys_ck": controller clock used by normal mode, + the following ones are optional: + "ref_ck": reference clock used by low power mode etc, + "mcu_ck": mcu_bus clock for register access, + "dma_ck": dma_bus clock for data transfer by DMA - phys : a list of phandle + phy specifier pairs @@ -57,9 +58,7 @@ usb30: usb@1127 { clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>, <&pericfg CLK_PERI_USB0>, <&pericfg CLK_PERI_USB1>; - clock-names = "sys_ck", "ref_ck", - "wakeup_deb_p0", - "wakeup_deb_p1"; + clock-names = "sys_ck", "ref_ck"; phys = <&phy_port0 PHY_TYPE_USB3>, <&phy_port1 PHY_TYPE_USB2>; vusb33-supply = <&mt6397_vusb_reg>; @@ -91,9 +90,8 @@ Required properties: - clocks : a list of phandle + clock-specifier pairs, one for each entry in clock-names - - clock-names : must be - "sys_ck": for clock of xHCI MAC - "ref_ck": for reference clock of xHCI MAC + - clock-names : must contain "sys_ck", and the following ones are optional: + "ref_ck", "mcu_ck" and "dma_ck" Optional properties: - vbus-supply : reference to the VBUS regulator; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 7/9] usb: host: modify description for MTK xHCI config
Due to all MediaTek SoCs with xHCI host controller use this driver, remove limitation for specific SoCs Signed-off-by: Chunfeng Yun --- drivers/usb/host/Kconfig |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index fa5692d..bc09a2e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -45,12 +45,12 @@ config USB_XHCI_PLATFORM If unsure, say N. config USB_XHCI_MTK - tristate "xHCI support for Mediatek MT65xx/MT7621" + tristate "xHCI support for MediaTek SoCs" select MFD_SYSCON depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST ---help--- Say 'Y' to enable the support for the xHCI host controller - found in Mediatek MT65xx SoCs. + found in MediaTek SoCs. If unsure, say N. config USB_XHCI_MVEBU -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/9] usb: xhci-mtk: remove dummy wakeup debounce clocks
The wakeup debounce clocks for each ports in fact are not needed, so remove them. Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-mtk.c | 33 - drivers/usb/host/xhci-mtk.h |2 -- 2 files changed, 35 deletions(-) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 97ba51e..d60463c 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -237,25 +237,8 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) goto sys_clk_err; } - if (mtk->wakeup_src) { - ret = clk_prepare_enable(mtk->wk_deb_p0); - if (ret) { - dev_err(mtk->dev, "failed to enable wk_deb_p0\n"); - goto usb_p0_err; - } - - ret = clk_prepare_enable(mtk->wk_deb_p1); - if (ret) { - dev_err(mtk->dev, "failed to enable wk_deb_p1\n"); - goto usb_p1_err; - } - } return 0; -usb_p1_err: - clk_disable_unprepare(mtk->wk_deb_p0); -usb_p0_err: - clk_disable_unprepare(mtk->sys_clk); sys_clk_err: clk_disable_unprepare(mtk->ref_clk); ref_clk_err: @@ -264,10 +247,6 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) { - if (mtk->wakeup_src) { - clk_disable_unprepare(mtk->wk_deb_p1); - clk_disable_unprepare(mtk->wk_deb_p0); - } clk_disable_unprepare(mtk->sys_clk); clk_disable_unprepare(mtk->ref_clk); } @@ -371,18 +350,6 @@ static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk, if (!mtk->wakeup_src) return 0; - mtk->wk_deb_p0 = devm_clk_get(dev, "wakeup_deb_p0"); - if (IS_ERR(mtk->wk_deb_p0)) { - dev_err(dev, "fail to get wakeup_deb_p0\n"); - return PTR_ERR(mtk->wk_deb_p0); - } - - mtk->wk_deb_p1 = devm_clk_get(dev, "wakeup_deb_p1"); - if (IS_ERR(mtk->wk_deb_p1)) { - dev_err(dev, "fail to get wakeup_deb_p1\n"); - return PTR_ERR(mtk->wk_deb_p1); - } - mtk->pericfg = syscon_regmap_lookup_by_phandle(dn, "mediatek,syscon-wakeup"); if (IS_ERR(mtk->pericfg)) { diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index db55a12..67783a7 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -126,8 +126,6 @@ struct xhci_hcd_mtk { struct regulator *vbus; struct clk *sys_clk;/* sys and mac clock */ struct clk *ref_clk; - struct clk *wk_deb_p0; /* port0's wakeup debounce clock */ - struct clk *wk_deb_p1; struct regmap *pericfg; struct phy **phys; int num_phys; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/9] usb: xhci-mtk: use dma_set_mask_and_coherent() in probe function
This patch uses the simpler dma_set_mask_and_coherent() instead of doing these as separate steps Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-mtk.c |7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 8fb6065..c197a6d 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -606,15 +606,10 @@ static int xhci_mtk_probe(struct platform_device *pdev) } /* Initialize dma_mask and coherent_dma_mask to 32-bits */ - ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) goto disable_clk; - if (!dev->dma_mask) - dev->dma_mask = &dev->coherent_dma_mask; - else - dma_set_mask(dev, DMA_BIT_MASK(32)); - hcd = usb_create_hcd(driver, dev, dev_name(dev)); if (!hcd) { ret = -ENOMEM; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/9] usb: xhci-mtk: use ports count from xhci in xhci_mtk_sch_init()
Make use of ports count from xhci but not from ippc in xhci_mtk_sch_init() Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-mtk-sch.c |3 ++- drivers/usb/host/xhci-mtk.c |3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index 6e7ddf6..bfc51bc 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -287,12 +287,13 @@ static bool need_bw_sch(struct usb_host_endpoint *ep, int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk) { + struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); struct mu3h_sch_bw_info *sch_array; int num_usb_bus; int i; /* ss IN and OUT are separated */ - num_usb_bus = mtk->num_u3_ports * 2 + mtk->num_u2_ports; + num_usb_bus = xhci->num_usb3_ports * 2 + xhci->num_usb2_ports; sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL); if (sch_array == NULL) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index c197a6d..9502ca4 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -492,7 +492,6 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) /* called during probe() after chip reset completes */ static int xhci_mtk_setup(struct usb_hcd *hcd) { - struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); int ret; @@ -507,8 +506,6 @@ static int xhci_mtk_setup(struct usb_hcd *hcd) return ret; if (usb_hcd_is_primary_hcd(hcd)) { - mtk->num_u3_ports = xhci->num_usb3_ports; - mtk->num_u2_ports = xhci->num_usb2_ports; ret = xhci_mtk_sch_init(mtk); if (ret) return ret; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/9] usb: xhci-mtk: support option to disable usb3 ports
Add support to disable specific usb3 ports, it's useful when usb3 phy is shared with PCIe or SATA, because we should disable the corresponding usb3 port if the phy is used by PCIe or SATA. Sometimes it's helpful to analyse and solve problems. Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-mtk.c | 18 +++--- drivers/usb/host/xhci-mtk.h |1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 7a92bb7..97ba51e 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -92,6 +92,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) { struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; u32 value, check_val; + int u3_ports_disabed = 0; int ret; int i; @@ -103,8 +104,13 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) value &= ~CTRL1_IP_HOST_PDN; writel(value, &ippc->ip_pw_ctr1); - /* power on and enable all u3 ports */ + /* power on and enable u3 ports except skipped ones */ for (i = 0; i < mtk->num_u3_ports; i++) { + if ((0x1 << i) & mtk->u3p_dis_msk) { + u3_ports_disabed++; + continue; + } + value = readl(&ippc->u3_ctrl_p[i]); value &= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS); value |= CTRL_U3_PORT_HOST_SEL; @@ -126,7 +132,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) check_val = STS1_SYSPLL_STABLE | STS1_REF_RST | STS1_SYS125_RST | STS1_XHCI_RST; - if (mtk->num_u3_ports) + if (mtk->num_u3_ports > u3_ports_disabed) check_val |= STS1_U3_MAC_RST; ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, @@ -149,8 +155,11 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk) if (!mtk->has_ippc) return 0; - /* power down all u3 ports */ + /* power down u3 ports except skipped ones */ for (i = 0; i < mtk->num_u3_ports; i++) { + if ((0x1 << i) & mtk->u3p_dis_msk) + continue; + value = readl(&ippc->u3_ctrl_p[i]); value |= CTRL_U3_PORT_PDN; writel(value, &ippc->u3_ctrl_p[i]); @@ -573,6 +582,9 @@ static int xhci_mtk_probe(struct platform_device *pdev) } mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable"); + /* optional property, ignore the error if it does not exist */ + of_property_read_u32(node, "mediatek,u3p-dis-msk", +&mtk->u3p_dis_msk); ret = usb_wakeup_of_property_parse(mtk, node); if (ret) diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index 3aa5e1d..db55a12 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -121,6 +121,7 @@ struct xhci_hcd_mtk { bool has_ippc; int num_u2_ports; int num_u3_ports; + int u3p_dis_msk; struct regulator *vusb33; struct regulator *vbus; struct clk *sys_clk;/* sys and mac clock */ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/2] usb: renesas_usbhs: bugfix for v4.14
This patch set is based on the Felipe's usb.git / testing/fixes branch (The commit is 7661ca09b2ff98f48693f431bb01fed62830e433). Changes from v1: - Devides two fix things in a patch to two patches. Yoshihiro Shimoda (2): usb: renesas_usbhs: fix the BCLR setting condition for non-DCP pipe usb: renesas_usbhs: fix usbhsf_fifo_clear() for RX direction drivers/usb/renesas_usbhs/fifo.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] usb: renesas_usbhs: fix usbhsf_fifo_clear() for RX direction
This patch fixes an issue that the usbhsf_fifo_clear() is possible to cause 10 msec delay if the pipe is RX direction and empty because the FRDY bit will never be set to 1 in such case. Fixes: e8d548d54968 ("usb: renesas_usbhs: fifo became independent from pipe.") Cc: # v3.1+ Signed-off-by: Yoshihiro Shimoda --- drivers/usb/renesas_usbhs/fifo.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 03cac07..68f2690 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -284,8 +284,17 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int ret = 0; - if (!usbhs_pipe_is_dcp(pipe)) - ret = usbhsf_fifo_barrier(priv, fifo); + if (!usbhs_pipe_is_dcp(pipe)) { + /* +* This driver checks the pipe condition first to avoid -EBUSY +* from usbhsf_fifo_barrier() with about 10 msec delay in +* the interrupt handler if the pipe is RX direction and empty. +*/ + if (usbhs_pipe_is_dir_in(pipe)) + ret = usbhs_pipe_is_accessible(pipe); + if (!ret) + ret = usbhsf_fifo_barrier(priv, fifo); + } /* * if non-DCP pipe, this driver should set BCLR when -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/2] usb: renesas_usbhs: fix the BCLR setting condition for non-DCP pipe
This patch fixes an issue that the driver sets the BCLR bit of {C,Dn}FIFOCTR register to 1 even when it's non-DCP pipe and the FRDY bit of {C,Dn}FIFOCTR register is set to 1. Fixes: e8d548d54968 ("usb: renesas_usbhs: fifo became independent from pipe.") Cc: # v3.1+ Signed-off-by: Yoshihiro Shimoda --- drivers/usb/renesas_usbhs/fifo.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index d1af831..03cac07 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -282,11 +282,17 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + int ret = 0; if (!usbhs_pipe_is_dcp(pipe)) - usbhsf_fifo_barrier(priv, fifo); + ret = usbhsf_fifo_barrier(priv, fifo); - usbhs_write(priv, fifo->ctr, BCLR); + /* +* if non-DCP pipe, this driver should set BCLR when +* usbhsf_fifo_barrier() returns 0. +*/ + if (!ret) + usbhs_write(priv, fifo->ctr, BCLR); } static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] usb: musb: Check for host-mode using is_host_active() on reset interrupt
The sunxi musb has a bug where sometimes it will generate a babble error on device disconnect instead of a disconnect IRQ. When this happens the musb controller switches from host mode to device mode (it clears MUSB_DEVCTL_HM/MUSB_DEVCTL_SESSION and sets MUSB_DEVCTL_BDEVICE) and gets stuck in this state. The babble error is misdetected as a bus reset because MUSB_DEVCTL_HM was cleared. To fix this, use is_host_active() rather than (devctl & MUSB_DEVCTL_HM) to detect babble error so that sunxi musb babble recovery can handle it by restoring the mode. This information is provided by the driver logic and does not rely on register contents. Cc: sta...@vger.kernel.org # v4.1+ Signed-off-by: Jonathan Liu --- drivers/usb/musb/musb_core.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 029692053dd3..1bce7df3e110 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -906,7 +906,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, */ if (int_usb & MUSB_INTR_RESET) { handled = IRQ_HANDLED; - if (devctl & MUSB_DEVCTL_HM) { + if (is_host_active(musb)) { /* * When BABBLE happens what we can depends on which * platform MUSB is running, because some platforms @@ -916,9 +916,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, * drop the session. */ dev_err(musb->controller, "Babble\n"); - - if (is_host_active(musb)) - musb_recover_from_babble(musb); + musb_recover_from_babble(musb); } else { musb_dbg(musb, "BUS RESET as %s", usb_otg_state_string(musb->xceiv->otg->state)); -- 2.13.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Mouse freezes on button depression
Hi Oliver thank you for your reply. Apologies for now replying from gmail. I'm being told my crjb.net address is failing SPF and that I have to shoehorn this email into plain-text for you. Here we go :) I must correct/clarify that the browser forward and back buttons seem to work in chrome and that in testing this evening, they have not frozen or crashed anything. The output I provided before was simply the dmesg record of the mouse being detected on boot or plugin, not any dmesg records produced on the depression of the buttons of concern (which are primarily the DPI+ and DPI- buttons). *Relevant output from usbmon (cat /sys/kernel/debug/usb/usbmon/0u)* I was able to capture my pressing the dpi+ button twice before the mouse driver crashed. a0b1fca52240 1143494193 C Ii:1:015:2 0:1 8 = a0b1fca52240 1143494212 S Ii:1:015:2 -115:1 8 < a0b1fca52240 1144099217 C Ii:1:015:2 0:1 8 = a0b1fca52240 1144099233 S Ii:1:015:2 -115:1 8 < *From lsusb* Bus 001 Device 015: ID 1044:7a13 Chu Yuen Enterprise Co., Ltd *From cat /sys/kernel/debug/usb/devices* T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 15 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=1044 ProdID=7a13 Rev= 2.00 S: Manufacturer=Texas Instruments S: Product=MSP430-USB Mouse S: SerialNumber=8C2F0C5132000C00 C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=01 Driver=usbhid E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=15ms E: Ad=01(O) Atr=03(Int.) MxPS= 8 Ivl=15ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=1ms E: Ad=02(O) Atr=03(Int.) MxPS= 8 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid E: Ad=83(I) Atr=03(Int.) MxPS= 8 Ivl=20ms E: Ad=03(O) Atr=03(Int.) MxPS= 8 Ivl=20ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid E: Ad=84(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=04(O) Atr=03(Int.) MxPS= 64 Ivl=1ms Unplugging and re-plugging the mouse in, it moves to Bus 01, Device 16 and I captured the following: *usbmon output from the DPI - button* a0b20247ab40 1348549098 C Ii:1:016:2 0:1 8 = a0b20247ab40 1348549123 S Ii:1:016:2 -115:1 8 <* * I can confirm that while the mouse cursor became unresponsive/frozen on the computer after pressing this button, when I re-inserted it in, the mouse movement across the screen reflected that the DPI - button had been pressed, as it was sluggish now. So at least the device is reflecting the button being pressed and is responding as such. *usbmon output from the browser-forward button* I pressed thus button three times and the mouse appears to still work! (of course we're now at bus 01, device 017 a0b25856b980 1565643086 C Ii:1:017:2 0:1 8 = 1000 a0b25856b980 1565643113 S Ii:1:017:2 -115:1 8 < a0b25856b980 1565810091 C Ii:1:017:2 0:1 8 = a0b25856b980 1565810113 S Ii:1:017:2 -115:1 8 < a0b25856b980 1566953154 C Ii:1:017:2 0:1 8 = 1000 a0b25856b980 1566953181 S Ii:1:017:2 -115:1 8 < a0b25856b980 1567113163 C Ii:1:017:2 0:1 8 = a0b25856b980 1567113185 S Ii:1:017:2 -115:1 8 < a0b25856b980 1567762196 C Ii:1:017:2 0:1 8 = 1000 a0b25856b980 1567762215 S Ii:1:017:2 -115:1 8 < a0b25856b980 1567890202 C Ii:1:017:2 0:1 8 = a0b25856b980 1567890225 S Ii:1:017:2 -115:1 8 < *usbmon output from the browser-backward button* still not frozen ... a0b25856b980 1710325920 C Ii:1:017:2 0:1 8 = 00ff ff00 a0b25856b980 1710325950 S Ii:1:017:2 -115:1 8 < a0b25856b980 1710343901 C Ii:1:017:2 0:1 8 = 0800 a0b25856b980 1710343919 S Ii:1:017:2 -115:1 8 < a0b25856b980 1710506929 C Ii:1:017:2 0:1 8 = a0b25856b980 1710506952 S Ii:1:017:2 -115:1 8 < a0b25856b980 1710609934 C Ii:1:017:2 0:1 8 = 0800 a0b25856b980 1710609956 S Ii:1:017:2 -115:1 8 < a0b25856b980 1710720943 C Ii:1:017:2 0:1 8 = a0b25856b980 1710720965 S Ii:1:017:2 -115:1 8 < a0b25856b980 1710981955 C Ii:1:017:2 0:1 8 = 0800 a0b25856b980 1710981977 S Ii:1:017:2 -115:1 8 < a0b25856b980 1711079959 C Ii:1:017:2 0:1 8 = a0b25856b980 1711079981 S Ii:1:017:2 -115:1 8 < a0b25856b980 1711615989 C Ii:1:017:2 0:1 8 = 0800 a0b25856b980 1711616014 S Ii:1:017:2 -115:1 8 < a0b25856b980 1711730998 C Ii:1:017:2 0:1 8 = a0b25856b980 1711731020 S Ii:1:017:2 -115:1 8 < a0b25856b980 1712017010 C Ii:1:017:2 0:1 8 = 0800 a0b25856b980 1712017033 S Ii:1:017:2 -115:1 8 < a0b25856b980 1712089016 C Ii:1:017:2 0:1 8 = a0b25856b980 1712089038 S Ii:1:017:2 -115:1 8 < Pressing the DPI+ button made the mouse cursor unresponsive t
[PATCH 08/12] usb: mtu3: get optional vbus for host only mode
When dr_mode is set as USB_DR_MODE_HOST, it's better to try to get optional vbus, this can increase flexibility, although we can set vbus as always on for regulator or put it in host driver to turn it on. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_plat.c |8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 1e473b0..7ca81f4e 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -300,10 +300,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) of_property_read_u32(node, "mediatek,u3p-dis-msk", &ssusb->u3p_dis_msk); - if (ssusb->dr_mode != USB_DR_MODE_OTG) - return 0; - - /* if dual-role mode is supported */ vbus = devm_regulator_get(&pdev->dev, "vbus"); if (IS_ERR(vbus)) { dev_err(dev, "failed to get vbus\n"); @@ -311,6 +307,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) } otg_sx->vbus = vbus; + if (ssusb->dr_mode == USB_DR_MODE_HOST) + return 0; + + /* if dual-role mode is supported */ otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); otg_sx->manual_drd_enabled = of_property_read_bool(node, "enable-manual-drd"); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/12] usb: mtu3: set invalid dr_mode as dual-role mode
Treat dr_mode of USB_DR_MODE_UNKNOWN as USB_DR_MODE_OTG to enhance functional robustness. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_plat.c |6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 7ca81f4e..9ff3357 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -283,10 +283,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) return PTR_ERR(ssusb->ippc_base); ssusb->dr_mode = usb_get_dr_mode(dev); - if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) { - dev_err(dev, "dr_mode is error\n"); - return -EINVAL; - } + if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) + ssusb->dr_mode = USB_DR_MODE_OTG; if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) return 0; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 05/12] usb: mtu3: support 36-bit DMA address
add support for 36-bit DMA address Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h | 17 ++- drivers/usb/mtu3/mtu3_core.c| 34 - drivers/usb/mtu3/mtu3_hw_regs.h | 10 drivers/usb/mtu3/mtu3_qmu.c | 102 --- 4 files changed, 142 insertions(+), 21 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 2795294..ef2dc92 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -46,6 +46,9 @@ #defineMU3D_EP_RXCR1(epnum)(U3D_RX1CSR1 + (((epnum) - 1) * 0x10)) #defineMU3D_EP_RXCR2(epnum)(U3D_RX1CSR2 + (((epnum) - 1) * 0x10)) +#define USB_QMU_TQHIAR(epnum) (U3D_TXQHIAR1 + (((epnum) - 1) * 0x4)) +#define USB_QMU_RQHIAR(epnum) (U3D_RXQHIAR1 + (((epnum) - 1) * 0x4)) + #define USB_QMU_RQCSR(epnum) (U3D_RXQCSR1 + (((epnum) - 1) * 0x10)) #define USB_QMU_RQSAR(epnum) (U3D_RXQSAR1 + (((epnum) - 1) * 0x10)) #define USB_QMU_RQCPR(epnum) (U3D_RXQCPR1 + (((epnum) - 1) * 0x10)) @@ -138,23 +141,33 @@ struct mtu3_fifo_info { * Checksum value is calculated over the 16 bytes of the GPD by default; * @data_buf_len (RX ONLY): This value indicates the length of * the assigned data buffer + * @tx_ext_addr (TX ONLY): [3:0] are 4 extension bits of @buffer, + * [7:4] are 4 extension bits of @next_gpd * @next_gpd: Physical address of the next GPD * @buffer: Physical address of the data buffer * @buf_len: * (TX): This value indicates the length of the assigned data buffer * (RX): The total length of data received * @ext_len: reserved + * @rx_ext_addr(RX ONLY): [3:0] are 4 extension bits of @buffer, + * [7:4] are 4 extension bits of @next_gpd * @ext_flag: * bit5 (TX ONLY): Zero Length Packet (ZLP), */ struct qmu_gpd { __u8 flag; __u8 chksum; - __le16 data_buf_len; + union { + __le16 data_buf_len; + __le16 tx_ext_addr; + }; __le32 next_gpd; __le32 buffer; __le16 buf_len; - __u8 ext_len; + union { + __u8 ext_len; + __u8 rx_ext_addr; + }; __u8 ext_flag; } __packed; diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index 9475798..cd4528f 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -17,6 +17,7 @@ * */ +#include #include #include #include @@ -759,7 +760,31 @@ static void mtu3_hw_exit(struct mtu3 *mtu) mtu3_mem_free(mtu); } -/*-*/ +/** + * we set 32-bit DMA mask by default, here check whether the controller + * supports 36-bit DMA or not, if it does, set 36-bit DMA mask. + */ +static int mtu3_set_dma_mask(struct mtu3 *mtu) +{ + struct device *dev = mtu->dev; + bool is_36bit = false; + int ret = 0; + u32 value; + + value = mtu3_readl(mtu->mac_base, U3D_MISC_CTRL); + if (value & DMA_ADDR_36BIT) { + is_36bit = true; + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36)); + /* If set 36-bit DMA mask fails, fall back to 32-bit DMA mask */ + if (ret) { + is_36bit = false; + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + } + } + dev_info(dev, "dma mask: %s bits\n", is_36bit ? "36" : "32"); + + return ret; +} int ssusb_gadget_init(struct ssusb_mtk *ssusb) { @@ -820,6 +845,12 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) return ret; } + ret = mtu3_set_dma_mask(mtu); + if (ret) { + dev_err(dev, "mtu3 set dma_mask failed:%d\n", ret); + goto dma_mask_err; + } + ret = devm_request_irq(dev, mtu->irq, mtu3_irq, 0, dev_name(dev), mtu); if (ret) { dev_err(dev, "request irq %d failed!\n", mtu->irq); @@ -845,6 +876,7 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) gadget_err: device_init_wakeup(dev, false); +dma_mask_err: irq_err: mtu3_hw_exit(mtu); ssusb->u3d = NULL; diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index 06b2966..b605975 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -58,6 +58,8 @@ #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) +#define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) +#define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) #define U3D_TXQCSR1(SSUSB_DEV_BASE + 0x0510) #define U3D_TXQSAR1(SSUSB_DEV_BASE + 0x0514) @@ -189,6 +191,13 @@ #define QMU_RX_COZ(x) (BIT(16) << (x)) #define QMU_RX_ZLP(x) (BIT(0) << (x)) +/* U3D_TXQHIAR1 */ +/* U3D_RXQHIAR1 */ +#define QMU_LAS
[PATCH 04/12] usb: mtu3: add optional mcu and dma bus clocks
There are mcu_bus and dma_bus clocks needed to be turned on/off by driver on some SoCs, so add them as optional ones Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h |5 ++ drivers/usb/mtu3/mtu3_plat.c | 121 -- 2 files changed, 86 insertions(+), 40 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 6d3278e..2795294 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -206,6 +206,9 @@ struct otg_switch_mtk { * @ippc_base: register base address of IP Power and Clock interface (IPPC) * @vusb33: usb3.3V shared by device/host IP * @sys_clk: system clock of mtu3, shared by device/host IP + * @ref_clk: reference clock + * @mcu_clk: mcu_bus_ck clock for AHB bus etc + * @dma_clk: dma_bus_ck clock for AXI bus etc * @dr_mode: works in which mode: * host only, device only or dual-role mode * @u2_ports: number of usb2.0 host ports @@ -226,6 +229,8 @@ struct ssusb_mtk { struct regulator *vusb33; struct clk *sys_clk; struct clk *ref_clk; + struct clk *mcu_clk; + struct clk *dma_clk; /* otg */ struct otg_switch_mtk otg_switch; enum usb_dr_mode dr_mode; diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 9edad30..fb89920 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -110,15 +110,9 @@ static void ssusb_phy_power_off(struct ssusb_mtk *ssusb) phy_power_off(ssusb->phys[i]); } -static int ssusb_rscs_init(struct ssusb_mtk *ssusb) +static int ssusb_clks_enable(struct ssusb_mtk *ssusb) { - int ret = 0; - - ret = regulator_enable(ssusb->vusb33); - if (ret) { - dev_err(ssusb->dev, "failed to enable vusb33\n"); - goto vusb33_err; - } + int ret; ret = clk_prepare_enable(ssusb->sys_clk); if (ret) { @@ -132,6 +126,52 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) goto ref_clk_err; } + ret = clk_prepare_enable(ssusb->mcu_clk); + if (ret) { + dev_err(ssusb->dev, "failed to enable mcu_clk\n"); + goto mcu_clk_err; + } + + ret = clk_prepare_enable(ssusb->dma_clk); + if (ret) { + dev_err(ssusb->dev, "failed to enable dma_clk\n"); + goto dma_clk_err; + } + + return 0; + +dma_clk_err: + clk_disable_unprepare(ssusb->mcu_clk); +mcu_clk_err: + clk_disable_unprepare(ssusb->ref_clk); +ref_clk_err: + clk_disable_unprepare(ssusb->sys_clk); +sys_clk_err: + return ret; +} + +static void ssusb_clks_disable(struct ssusb_mtk *ssusb) +{ + clk_disable_unprepare(ssusb->dma_clk); + clk_disable_unprepare(ssusb->mcu_clk); + clk_disable_unprepare(ssusb->ref_clk); + clk_disable_unprepare(ssusb->sys_clk); +} + +static int ssusb_rscs_init(struct ssusb_mtk *ssusb) +{ + int ret = 0; + + ret = regulator_enable(ssusb->vusb33); + if (ret) { + dev_err(ssusb->dev, "failed to enable vusb33\n"); + goto vusb33_err; + } + + ret = ssusb_clks_enable(ssusb); + if (ret) + goto clks_err; + ret = ssusb_phy_init(ssusb); if (ret) { dev_err(ssusb->dev, "failed to init phy\n"); @@ -149,20 +189,16 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) phy_err: ssusb_phy_exit(ssusb); phy_init_err: - clk_disable_unprepare(ssusb->ref_clk); -ref_clk_err: - clk_disable_unprepare(ssusb->sys_clk); -sys_clk_err: + ssusb_clks_disable(ssusb); +clks_err: regulator_disable(ssusb->vusb33); vusb33_err: - return ret; } static void ssusb_rscs_exit(struct ssusb_mtk *ssusb) { - clk_disable_unprepare(ssusb->sys_clk); - clk_disable_unprepare(ssusb->ref_clk); + ssusb_clks_disable(ssusb); regulator_disable(ssusb->vusb33); ssusb_phy_power_off(ssusb); ssusb_phy_exit(ssusb); @@ -203,6 +239,19 @@ static int get_iddig_pinctrl(struct ssusb_mtk *ssusb) return 0; } +/* ignore the error if the clock does not exist */ +static struct clk *get_optional_clk(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 get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) { struct device_node *node = pdev->dev.of_node; @@ -225,18 +274,17 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) return PTR_ERR(ssusb->sys_clk); } - /* -* reference clock is usually a "fixed-clock", make it optional -* for backward compatibility and ignore the error if it d
[PATCH 01/12] usb: mtu3: fix error return code in ssusb_gadget_init()
When fail to get irq number, platform_get_irq() may return -EPROBE_DEFER, but we ignore it and always return -ENODEV, so fix it. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_core.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index 99c65b0..9475798 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -774,9 +774,9 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) return -ENOMEM; mtu->irq = platform_get_irq(pdev, 0); - if (mtu->irq <= 0) { + if (mtu->irq < 0) { dev_err(dev, "fail to get irq number\n"); - return -ENODEV; + return mtu->irq; } dev_info(dev, "irq %d\n", mtu->irq); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/12] usb: mtu3: use FORCE/RG_IDDIG to implement manual DRD switch
In order to keep manual DRD switch independent on IDDIG interrupt, make use of FORCE/RG_IDDIG instead of IDDIG EINT interrupt to implement manual DRD switch function. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h | 18 drivers/usb/mtu3/mtu3_dr.c | 61 +-- drivers/usb/mtu3/mtu3_dr.h |6 drivers/usb/mtu3/mtu3_host.c|5 drivers/usb/mtu3/mtu3_hw_regs.h |2 ++ drivers/usb/mtu3/mtu3_plat.c| 38 ++-- 6 files changed, 74 insertions(+), 56 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index ef2dc92..b0c2b5d 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -115,6 +115,19 @@ enum mtu3_g_ep0_state { }; /** + * MTU3_DR_FORCE_NONE: automatically switch host and periperal mode + * by IDPIN signal. + * MTU3_DR_FORCE_HOST: force to enter host mode and override OTG + * IDPIN signal. + * MTU3_DR_FORCE_DEVICE: force to enter peripheral mode. + */ +enum mtu3_dr_force_mode { + MTU3_DR_FORCE_NONE = 0, + MTU3_DR_FORCE_HOST, + MTU3_DR_FORCE_DEVICE, +}; + +/** * @base: the base address of fifo * @limit: the bitmap size in bits * @bitmap: fifo bitmap in unit of @MTU3_EP_FIFO_UNIT @@ -196,7 +209,6 @@ struct mtu3_gpd_ring { * xHCI driver initialization, it's necessary for system bootup * as device. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not -* @id_*: used to maually switch between host and device modes by idpin * @manual_drd_enabled: it's true when supports dual-role device by debugfs * to switch host/device modes depending on user input. */ @@ -207,10 +219,6 @@ struct otg_switch_mtk { struct notifier_block id_nb; struct delayed_work extcon_reg_dwork; bool is_u3_drd; - /* dual-role switch by debugfs */ - struct pinctrl *id_pinctrl; - struct pinctrl_state *id_float; - struct pinctrl_state *id_ground; bool manual_drd_enabled; }; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 5602561..ec442cd 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -261,21 +261,22 @@ static void extcon_register_dwork(struct work_struct *work) * depending on user input. * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode. - * It generates cable state changes by pulling up/down IDPIN and - * notifies driver to switch mode by "extcon-usb-gpio". - * NOTE: when use MICRO receptacle, should not enable this interface. */ static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; - if (to_host) - pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_ground); - else - pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_float); + if (to_host) { + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); + ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); + ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); + } else { + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE); + ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); + ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); + } } - static int ssusb_mode_show(struct seq_file *sf, void *unused) { struct ssusb_mtk *ssusb = sf->private; @@ -388,17 +389,45 @@ static void ssusb_debugfs_exit(struct ssusb_mtk *ssusb) debugfs_remove_recursive(ssusb->dbgfs_root); } +void ssusb_set_force_mode(struct ssusb_mtk *ssusb, + enum mtu3_dr_force_mode mode) +{ + u32 value; + + value = mtu3_readl(ssusb->ippc_base, SSUSB_U2_CTRL(0)); + switch (mode) { + case MTU3_DR_FORCE_DEVICE: + value |= SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG; + break; + case MTU3_DR_FORCE_HOST: + value |= SSUSB_U2_PORT_FORCE_IDDIG; + value &= ~SSUSB_U2_PORT_RG_IDDIG; + break; + case MTU3_DR_FORCE_NONE: + value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG); + break; + default: + return; + } + mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); +} + int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; - INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, extcon_register_dwork); - - if (otg_sx->manual_drd_enabled) + if (otg_sx->manual_drd_enabled) { ssusb_debugfs_init(ssusb); - - /* It is enough to delay 1s for waiting for host initialization */ - schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ); + } else { + INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, +
[PATCH 07/12] usb: mtu3: add support for usb3.1 IP
Support SuperSpeedPlus for usb3.1 device IP Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h|1 + drivers/usb/mtu3/mtu3_core.c | 14 +++--- drivers/usb/mtu3/mtu3_gadget.c |3 ++- drivers/usb/mtu3/mtu3_gadget_ep0.c | 16 drivers/usb/mtu3/mtu3_hw_regs.h|1 + 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index b0c2b5d..d80e4e8 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -94,6 +94,7 @@ enum mtu3_speed { MTU3_SPEED_FULL = 1, MTU3_SPEED_HIGH = 3, MTU3_SPEED_SUPER = 4, + MTU3_SPEED_SUPER_PLUS = 5, }; /** diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index cd4528f..67f7a30 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -237,7 +237,7 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) void mtu3_dev_on_off(struct mtu3 *mtu, int is_on) { - if (mtu->is_u3_ip && (mtu->max_speed == USB_SPEED_SUPER)) + if (mtu->is_u3_ip && mtu->max_speed >= USB_SPEED_SUPER) mtu3_ss_func_set(mtu, is_on); else mtu3_hs_softconn_set(mtu, is_on); @@ -547,6 +547,9 @@ static void mtu3_set_speed(struct mtu3 *mtu) mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN); /* HS/FS detected by HW */ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); + } else if (mtu->max_speed == USB_SPEED_SUPER) { + mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0), +SSUSB_U3_PORT_SSP_SPEED); } dev_info(mtu->dev, "max_speed: %s\n", @@ -624,6 +627,10 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) udev_speed = USB_SPEED_SUPER; maxpkt = 512; break; + case MTU3_SPEED_SUPER_PLUS: + udev_speed = USB_SPEED_SUPER_PLUS; + maxpkt = 512; + break; default: udev_speed = USB_SPEED_UNKNOWN; break; @@ -825,14 +832,15 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) case USB_SPEED_FULL: case USB_SPEED_HIGH: case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: break; default: dev_err(dev, "invalid max_speed: %s\n", usb_speed_string(mtu->max_speed)); /* fall through */ case USB_SPEED_UNKNOWN: - /* default as SS */ - mtu->max_speed = USB_SPEED_SUPER; + /* default as SSP */ + mtu->max_speed = USB_SPEED_SUPER_PLUS; break; } diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index 434fca5..b495471 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -89,6 +89,7 @@ static int mtu3_ep_enable(struct mtu3_ep *mep) switch (mtu->g.speed) { case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { interval = desc->bInterval; @@ -456,7 +457,7 @@ static int mtu3_gadget_wakeup(struct usb_gadget *gadget) return -EOPNOTSUPP; spin_lock_irqsave(&mtu->lock, flags); - if (mtu->g.speed == USB_SPEED_SUPER) { + if (mtu->g.speed >= USB_SPEED_SUPER) { mtu3_setbits(mtu->mac_base, U3D_LINK_POWER_CONTROL, UX_EXIT); } else { mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c index 958d74d..1ca77e8 100644 --- a/drivers/usb/mtu3/mtu3_gadget_ep0.c +++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c @@ -212,8 +212,8 @@ static int ep0_set_sel(struct mtu3 *mtu, struct usb_ctrlrequest *setup) case USB_RECIP_DEVICE: result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED; result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; - /* superspeed only */ - if (mtu->g.speed == USB_SPEED_SUPER) { + + if (mtu->g.speed >= USB_SPEED_SUPER) { result[0] |= mtu->u1_enable << USB_DEV_STAT_U1_ENABLED; result[0] |= mtu->u2_enable << USB_DEV_STAT_U2_ENABLED; } @@ -329,8 +329,8 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu, handled = handle_test_mode(mtu, setup); break; case USB_DEVICE_U1_ENABLE: - if (mtu->g.speed != USB_SPEED_SUPER || - mtu->g.state != USB_STATE_CONFIGURED) + if (mtu->g.speed <= USB_SPEED_SUPER || + mtu->g.state != USB_STATE_CONFIGURED) break; lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTRO
[PATCH 03/12] usb: mtu3: remove dummy wakeup debounce clocks
The wakeup debounce clocks for each ports in fact are not needed, so remove them. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h |4 --- drivers/usb/mtu3/mtu3_host.c | 57 +++--- 2 files changed, 4 insertions(+), 57 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 112723d..6d3278e 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -214,8 +214,6 @@ struct otg_switch_mtk { * disable u3port0, bit1==1 to disable u3port1,... etc * @dbgfs_root: only used when supports manual dual-role switch via debugfs * @wakeup_en: it's true when supports remote wakeup in host mode - * @wk_deb_p0: port0's wakeup debounce clock - * @wk_deb_p1: it's optional, and depends on port1 is supported or not */ struct ssusb_mtk { struct device *dev; @@ -238,8 +236,6 @@ struct ssusb_mtk { struct dentry *dbgfs_root; /* usb wakeup for host mode */ bool wakeup_en; - struct clk *wk_deb_p0; - struct clk *wk_deb_p1; struct regmap *pericfg; }; diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index 4dd9508..edcc591 100644 --- a/drivers/usb/mtu3/mtu3_host.c +++ b/drivers/usb/mtu3/mtu3_host.c @@ -79,20 +79,6 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, if (!ssusb->wakeup_en) return 0; - ssusb->wk_deb_p0 = devm_clk_get(dev, "wakeup_deb_p0"); - if (IS_ERR(ssusb->wk_deb_p0)) { - dev_err(dev, "fail to get wakeup_deb_p0\n"); - return PTR_ERR(ssusb->wk_deb_p0); - } - - if (of_property_read_bool(dn, "wakeup_deb_p1")) { - ssusb->wk_deb_p1 = devm_clk_get(dev, "wakeup_deb_p1"); - if (IS_ERR(ssusb->wk_deb_p1)) { - dev_err(dev, "fail to get wakeup_deb_p1\n"); - return PTR_ERR(ssusb->wk_deb_p1); - } - } - ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn, "mediatek,syscon-wakeup"); if (IS_ERR(ssusb->pericfg)) { @@ -103,36 +89,6 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, return 0; } -static int ssusb_wakeup_clks_enable(struct ssusb_mtk *ssusb) -{ - int ret; - - ret = clk_prepare_enable(ssusb->wk_deb_p0); - if (ret) { - dev_err(ssusb->dev, "failed to enable wk_deb_p0\n"); - goto usb_p0_err; - } - - ret = clk_prepare_enable(ssusb->wk_deb_p1); - if (ret) { - dev_err(ssusb->dev, "failed to enable wk_deb_p1\n"); - goto usb_p1_err; - } - - return 0; - -usb_p1_err: - clk_disable_unprepare(ssusb->wk_deb_p0); -usb_p0_err: - return -EINVAL; -} - -static void ssusb_wakeup_clks_disable(struct ssusb_mtk *ssusb) -{ - clk_disable_unprepare(ssusb->wk_deb_p1); - clk_disable_unprepare(ssusb->wk_deb_p0); -} - static void host_ports_num_get(struct ssusb_mtk *ssusb) { u32 xhci_cap; @@ -286,19 +242,14 @@ void ssusb_host_exit(struct ssusb_mtk *ssusb) int ssusb_wakeup_enable(struct ssusb_mtk *ssusb) { - int ret = 0; - - if (ssusb->wakeup_en) { - ret = ssusb_wakeup_clks_enable(ssusb); + if (ssusb->wakeup_en) ssusb_wakeup_ip_sleep_en(ssusb); - } - return ret; + + return 0; } void ssusb_wakeup_disable(struct ssusb_mtk *ssusb) { - if (ssusb->wakeup_en) { + if (ssusb->wakeup_en) ssusb_wakeup_ip_sleep_dis(ssusb); - ssusb_wakeup_clks_disable(ssusb); - } } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/12] usb: mtu3: support option to disable usb3 ports
Add support to disable specific usb3 ports, it's useful when usb3 phy is shared with PCIe or SATA, because we should disable the corresponding usb3 port if the phy is used by PCIe or SATA. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h |3 +++ drivers/usb/mtu3/mtu3_host.c | 16 +--- drivers/usb/mtu3/mtu3_plat.c |8 ++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index b26fffc..112723d 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -210,6 +210,8 @@ struct otg_switch_mtk { * host only, device only or dual-role mode * @u2_ports: number of usb2.0 host ports * @u3_ports: number of usb3.0 host ports + * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to + * disable u3port0, bit1==1 to disable u3port1,... etc * @dbgfs_root: only used when supports manual dual-role switch via debugfs * @wakeup_en: it's true when supports remote wakeup in host mode * @wk_deb_p0: port0's wakeup debounce clock @@ -232,6 +234,7 @@ struct ssusb_mtk { bool is_host; int u2_ports; int u3_ports; + int u3p_dis_msk; struct dentry *dbgfs_root; /* usb wakeup for host mode */ bool wakeup_en; diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index e42d308..4dd9508 100644 --- a/drivers/usb/mtu3/mtu3_host.c +++ b/drivers/usb/mtu3/mtu3_host.c @@ -151,6 +151,7 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb) void __iomem *ibase = ssusb->ippc_base; int num_u3p = ssusb->u3_ports; int num_u2p = ssusb->u2_ports; + int u3_ports_disabed; u32 check_clk; u32 value; int i; @@ -158,8 +159,14 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb) /* power on host ip */ mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN); - /* power on and enable all u3 ports */ + /* power on and enable u3 ports except skipped ones */ + u3_ports_disabed = 0; for (i = 0; i < num_u3p; i++) { + if ((0x1 << i) & ssusb->u3p_dis_msk) { + u3_ports_disabed++; + continue; + } + value = mtu3_readl(ibase, SSUSB_U3_CTRL(i)); value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS); value |= SSUSB_U3_PORT_HOST_SEL; @@ -175,7 +182,7 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb) } check_clk = SSUSB_XHCI_RST_B_STS; - if (num_u3p) + if (num_u3p > u3_ports_disabed) check_clk = SSUSB_U3_MAC_RST_B_STS; return ssusb_check_clocks(ssusb, check_clk); @@ -190,8 +197,11 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend) int ret; int i; - /* power down and disable all u3 ports */ + /* power down and disable u3 ports except skipped ones */ for (i = 0; i < num_u3p; i++) { + if ((0x1 << i) & ssusb->u3p_dis_msk) + continue; + value = mtu3_readl(ibase, SSUSB_U3_CTRL(i)); value |= SSUSB_U3_PORT_PDN; value |= suspend ? 0 : SSUSB_U3_PORT_DIS; diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 088e3e6..9edad30 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -276,6 +276,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) if (ret) return ret; + /* optional property, ignore the error if it does not exist */ + of_property_read_u32(node, "mediatek,u3p-dis-msk", +&ssusb->u3p_dis_msk); + if (ssusb->dr_mode != USB_DR_MODE_OTG) return 0; @@ -304,8 +308,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) } } - dev_info(dev, "dr_mode: %d, is_u3_dr: %d\n", - ssusb->dr_mode, otg_sx->is_u3_drd); + dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk:%x\n", + ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk); return 0; } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 3/3] usb: dwc3: core: Notify current USB mode to USB3 PHY as well
Driver currently notifies only USB2 PHY on USB mode change. Extend this to USB3 PHY so that PHY drivers based on the mode can release system resources - clocks, regulators etc. Additionally Qualcomm QMP and QUSB2 PHY drivers need to override VBUS signal in PHY wrapper in device mode as USB VBUS line is not connected to PHYs. Also, remove NULL checks for PHY when calling phy_set_mode as PHY ops already check this. Signed-off-by: Manu Gautam --- drivers/usb/dwc3/core.c | 17 - 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 23bb192..dabfa16 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -156,9 +156,8 @@ static void __dwc3_set_mode(struct work_struct *work) } else { if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, true); - if (dwc->usb2_generic_phy) - phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); - + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); + phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); } break; case DWC3_GCTL_PRTCAP_DEVICE: @@ -166,8 +165,8 @@ static void __dwc3_set_mode(struct work_struct *work) if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, false); - if (dwc->usb2_generic_phy) - phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); + phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) @@ -932,8 +931,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, false); - if (dwc->usb2_generic_phy) - phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); + phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { @@ -948,8 +947,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, true); - if (dwc->usb2_generic_phy) - phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); + phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); ret = dwc3_host_init(dwc); if (ret) { -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 1/3] usb: dwc3: Don't reinitialize core during host bus-suspend/resume
Driver powers-off PHYs and reinitializes DWC3 core and gadget on resume. While this works fine for gadget mode but in host mode there is not re-initialization of host stack. Also, resetting bus as part of bus_suspend/resume is not correct which could affect (or disconnect) connected devices. Fix this by not reinitializing core on suspend/resume in host mode for HOST only and OTG/drd configurations. Signed-off-by: Manu Gautam --- drivers/usb/dwc3/core.c | 43 --- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 03474d3..f75613f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -927,6 +927,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: + dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); if (dwc->usb2_phy) @@ -942,6 +943,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; case USB_DR_MODE_HOST: + dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); if (dwc->usb2_phy) @@ -1293,21 +1295,19 @@ static int dwc3_suspend_common(struct dwc3 *dwc) { unsigned long flags; - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + switch (dwc->current_dr_role) { + case DWC3_GCTL_PRTCAP_DEVICE: spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_suspend(dwc); spin_unlock_irqrestore(&dwc->lock, flags); + dwc3_core_exit(dwc); break; - case USB_DR_MODE_HOST: + case DWC3_GCTL_PRTCAP_HOST: default: /* do nothing */ break; } - dwc3_core_exit(dwc); - return 0; } @@ -1316,18 +1316,17 @@ static int dwc3_resume_common(struct dwc3 *dwc) unsigned long flags; int ret; - ret = dwc3_core_init(dwc); - if (ret) - return ret; + switch (dwc->current_dr_role) { + case DWC3_GCTL_PRTCAP_DEVICE: + ret = dwc3_core_init(dwc); + if (ret) + return ret; - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_resume(dwc); spin_unlock_irqrestore(&dwc->lock, flags); - /* FALLTHROUGH */ - case USB_DR_MODE_HOST: + break; + case DWC3_GCTL_PRTCAP_HOST: default: /* do nothing */ break; @@ -1338,7 +1337,7 @@ static int dwc3_resume_common(struct dwc3 *dwc) static int dwc3_runtime_checks(struct dwc3 *dwc) { - switch (dwc->dr_mode) { + switch (dwc->current_dr_role) { case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_OTG: if (dwc->connected) @@ -1381,12 +1380,11 @@ static int dwc3_runtime_resume(struct device *dev) if (ret) return ret; - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + switch (dwc->current_dr_role) { + case DWC3_GCTL_PRTCAP_DEVICE: dwc3_gadget_process_pending_events(dwc); break; - case USB_DR_MODE_HOST: + case DWC3_GCTL_PRTCAP_HOST: default: /* do nothing */ break; @@ -1402,13 +1400,12 @@ static int dwc3_runtime_idle(struct device *dev) { struct dwc3 *dwc = dev_get_drvdata(dev); - switch (dwc->dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + switch (dwc->current_dr_role) { + case DWC3_GCTL_PRTCAP_DEVICE: if (dwc3_runtime_checks(dwc)) return -EBUSY; break; - case USB_DR_MODE_HOST: + case DWC3_GCTL_PRTCAP_HOST: default: /* do nothing */ break; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 2/3] usb: dwc3: pci: Runtime resume child device from wq
Driver currently resumes and increments pm usage_count of its child device (dwc3 main) from its runtime_resume handler. This requires dwc3 runtime_resume to perform pm_runtime_put to decrement the pm usage_count. However runtime_put from dwc3 happens for non pci drivers (e.g. dwc3-if-simple.c) as well which results in dwc3 pm usage_count becoming negative after couple of runtime suspend resume iterations. Fix this by performing runtime_get/put from dwc3-pci driver only using workqueue. Signed-off-by: Manu Gautam --- drivers/usb/dwc3/core.c | 1 - drivers/usb/dwc3/dwc3-pci.c | 29 +++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index f75613f..23bb192 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1391,7 +1391,6 @@ static int dwc3_runtime_resume(struct device *dev) } pm_runtime_mark_last_busy(dev); - pm_runtime_put(dev); return 0; } diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 7e995df..74e4cd3 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ struct dwc3_pci { guid_t guid; unsigned int has_dsm_for_pm:1; + struct work_struct wakeup_work; }; static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; @@ -174,6 +176,22 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) return 0; } +#ifdef CONFIG_PM +static void dwc3_pci_resume_work(struct work_struct *work) +{ + struct dwc3_pci *dwc = container_of(work, struct dwc3_pci, wakeup_work); + struct platform_device *dwc3 = dwc->dwc3; + int ret; + + ret = pm_runtime_get_sync(&dwc3->dev); + if (ret) + return; + + pm_runtime_mark_last_busy(&dwc3->dev); + pm_runtime_put_sync_autosuspend(&dwc3->dev); +} +#endif + static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { @@ -232,6 +250,9 @@ static int dwc3_pci_probe(struct pci_dev *pci, device_init_wakeup(dev, true); pci_set_drvdata(pci, dwc); pm_runtime_put(dev); +#ifdef CONFIG_PM + INIT_WORK(&dwc->wakeup_work, dwc3_pci_resume_work); +#endif return 0; err: @@ -243,6 +264,9 @@ static void dwc3_pci_remove(struct pci_dev *pci) { struct dwc3_pci *dwc = pci_get_drvdata(pci); +#ifdef CONFIG_PM + cancel_work_sync(&dwc->wakeup_work); +#endif device_init_wakeup(&pci->dev, false); pm_runtime_get(&pci->dev); platform_device_unregister(dwc->dwc3); @@ -318,14 +342,15 @@ static int dwc3_pci_runtime_suspend(struct device *dev) static int dwc3_pci_runtime_resume(struct device *dev) { struct dwc3_pci *dwc = dev_get_drvdata(dev); - struct platform_device *dwc3 = dwc->dwc3; int ret; ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0); if (ret) return ret; - return pm_runtime_get(&dwc3->dev); + queue_work(pm_wq, &dwc->wakeup_work); + + return 0; } #endif /* CONFIG_PM */ -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFT] lan78xx: FIX use-after-free in lan78xx_write_reg
We are not releasing 'buf' memory on failure or disconnect a device. Adding 'u8 *buf' as part of 'lan78xx_net' structure to make proper handle for 'buf'. Now releasing 'buf' memory on failure. It's allocate first in lan78xx_probe() and it should be freed last in lan78xx_disconnect(). Signed-off-by: Arvind Yadav --- drivers/net/usb/lan78xx.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index b99a7fb..e653982 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -402,6 +402,7 @@ struct lan78xx_net { struct statstagestats; struct irq_domain_data domain_data; + u8 *buf; }; /* define external phy id */ @@ -3470,6 +3471,9 @@ static void lan78xx_disconnect(struct usb_interface *intf) usb_scuttle_anchored_urbs(&dev->deferred); + kfree(dev->buf); + dev->buf = NULL; + lan78xx_unbind(dev, intf); usb_kill_urb(dev->urb_intr); @@ -3520,7 +3524,6 @@ static int lan78xx_probe(struct usb_interface *intf, int ret; unsigned maxp; unsigned period; - u8 *buf = NULL; udev = interface_to_usbdev(intf); udev = usb_get_dev(udev); @@ -3588,16 +3591,15 @@ static int lan78xx_probe(struct usb_interface *intf, period = dev->ep_intr->desc.bInterval; maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0); - buf = kmalloc(maxp, GFP_KERNEL); - if (buf) { + dev->buf = kmalloc(maxp, GFP_KERNEL); + if (dev->buf) { dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb_intr) { ret = -ENOMEM; - kfree(buf); goto out3; } else { usb_fill_int_urb(dev->urb_intr, dev->udev, -dev->pipe_intr, buf, maxp, +dev->pipe_intr, dev->buf, maxp, intr_complete, dev, period); } } @@ -3626,6 +3628,8 @@ static int lan78xx_probe(struct usb_interface *intf, return 0; out3: + kfree(dev->buf); + dev->buf = NULL; lan78xx_unbind(dev, intf); out2: free_netdev(netdev); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFT] lan78xx: FIX use-after-free in lan78xx_write_reg
On Wed, Sep 27, 2017 at 1:18 PM, Arvind Yadav wrote: > We are not releasing 'buf' memory on failure or disconnect a device. > > Adding 'u8 *buf' as part of 'lan78xx_net' structure to make proper > handle for 'buf'. > Now releasing 'buf' memory on failure. It's allocate first in > lan78xx_probe() and it should be freed last in lan78xx_disconnect(). > > Signed-off-by: Arvind Yadav Hi Arvind, I've tried your patch and still see a crash. Thanks! lan78xx 1-1:90.0 (unnamed net_device) (uninitialized): can't register MDIO bus lan78xx: probe of 1-1:90.0 failed with error -5 usb 1-1: USB disconnect, device number 2 == BUG: KASAN: use-after-free in lan78xx_write_reg.isra.21+0x1a8/0x1b0 Read of size 8 at addr 880063dfac40 by task kworker/1:1/1152 CPU: 1 PID: 1152 Comm: kworker/1:1 Not tainted 4.14.0-rc2-42660-g24b7bd59eec0-dirty #274 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Workqueue: events lan78xx_deferred_multicast_write Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 kasan_report+0x23d/0x350 mm/kasan/report.c:409 __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430 lan78xx_write_reg.isra.21+0x1a8/0x1b0 drivers/net/usb/lan78xx.c:459 lan78xx_deferred_multicast_write+0x10d/0x1a0 drivers/net/usb/lan78xx.c:1043 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 Allocated by task 1848: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 __kmalloc_node+0x192/0x480 mm/slub.c:3827 kmalloc_node ./include/linux/slab.h:535 kvmalloc_node+0x69/0xd0 mm/util.c:397 kvmalloc ./include/linux/mm.h:529 kvzalloc ./include/linux/mm.h:537 alloc_netdev_mqs+0x173/0xea0 net/core/dev.c:8023 alloc_etherdev_mqs+0x38/0x40 net/ethernet/eth.c:391 lan78xx_probe+0x13a/0x3020 drivers/net/usb/lan78xx.c:3545 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 hub_port_connect drivers/usb/core/hub.c:4903 hub_port_connect_change drivers/usb/core/hub.c:5009 port_event drivers/usb/core/hub.c:5115 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 Freed by task 1848: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524 slab_free_hook mm/slub.c:1390 slab_free_freelist_hook mm/slub.c:1412 slab_free mm/slub.c:2988 kfree+0xf6/0x2f0 mm/slub.c:3919 kvfree+0x3b/0x60 mm/util.c:416 netdev_freemem net/core/dev.c:7975 free_netdev+0x304/0x3c0 net/core/dev.c:8137 lan78xx_probe+0x21a4/0x3020 drivers/net/usb/lan78xx.c:3649 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa0
Re: [RFT] lan78xx: FIX use-after-free in lan78xx_write_reg
On Wed, Sep 27, 2017 at 2:06 PM, Andrey Konovalov wrote: > On Wed, Sep 27, 2017 at 1:18 PM, Arvind Yadav > wrote: >> We are not releasing 'buf' memory on failure or disconnect a device. >> >> Adding 'u8 *buf' as part of 'lan78xx_net' structure to make proper >> handle for 'buf'. >> Now releasing 'buf' memory on failure. It's allocate first in >> lan78xx_probe() and it should be freed last in lan78xx_disconnect(). >> >> Signed-off-by: Arvind Yadav > > Hi Arvind, > > I've tried your patch and still see a crash. > > Thanks! > > lan78xx 1-1:90.0 (unnamed net_device) (uninitialized): can't register MDIO bus > lan78xx: probe of 1-1:90.0 failed with error -5 > usb 1-1: USB disconnect, device number 2 > == > BUG: KASAN: use-after-free in lan78xx_write_reg.isra.21+0x1a8/0x1b0 > Read of size 8 at addr 880063dfac40 by task kworker/1:1/1152 It seems that the bug is caused by the fact that the lan78xx_deferred_multicast_write() work is not shut down on lan78xx_probe() failure. > > CPU: 1 PID: 1152 Comm: kworker/1:1 Not tainted > 4.14.0-rc2-42660-g24b7bd59eec0-dirty #274 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 > Workqueue: events lan78xx_deferred_multicast_write > Call Trace: > __dump_stack lib/dump_stack.c:16 > dump_stack+0x292/0x395 lib/dump_stack.c:52 > print_address_description+0x78/0x280 mm/kasan/report.c:252 > kasan_report_error mm/kasan/report.c:351 > kasan_report+0x23d/0x350 mm/kasan/report.c:409 > __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430 > lan78xx_write_reg.isra.21+0x1a8/0x1b0 drivers/net/usb/lan78xx.c:459 > lan78xx_deferred_multicast_write+0x10d/0x1a0 drivers/net/usb/lan78xx.c:1043 > process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 > worker_thread+0x221/0x1850 kernel/workqueue.c:2253 > kthread+0x3a1/0x470 kernel/kthread.c:231 > ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 > > Allocated by task 1848: > save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 > save_stack+0x43/0xd0 mm/kasan/kasan.c:447 > set_track mm/kasan/kasan.c:459 > kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 > __kmalloc_node+0x192/0x480 mm/slub.c:3827 > kmalloc_node ./include/linux/slab.h:535 > kvmalloc_node+0x69/0xd0 mm/util.c:397 > kvmalloc ./include/linux/mm.h:529 > kvzalloc ./include/linux/mm.h:537 > alloc_netdev_mqs+0x173/0xea0 net/core/dev.c:8023 > alloc_etherdev_mqs+0x38/0x40 net/ethernet/eth.c:391 > lan78xx_probe+0x13a/0x3020 drivers/net/usb/lan78xx.c:3545 > usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 > really_probe drivers/base/dd.c:413 > driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 > __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 > bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 > __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 > device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 > bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 > device_add+0xd0b/0x1660 drivers/base/core.c:1835 > usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 > generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 > usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 > really_probe drivers/base/dd.c:413 > driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 > __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 > bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 > __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 > device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 > bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 > device_add+0xd0b/0x1660 drivers/base/core.c:1835 > usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 > hub_port_connect drivers/usb/core/hub.c:4903 > hub_port_connect_change drivers/usb/core/hub.c:5009 > port_event drivers/usb/core/hub.c:5115 > hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 > process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 > worker_thread+0x221/0x1850 kernel/workqueue.c:2253 > kthread+0x3a1/0x470 kernel/kthread.c:231 > ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 > > Freed by task 1848: > save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 > save_stack+0x43/0xd0 mm/kasan/kasan.c:447 > set_track mm/kasan/kasan.c:459 > kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524 > slab_free_hook mm/slub.c:1390 > slab_free_freelist_hook mm/slub.c:1412 > slab_free mm/slub.c:2988 > kfree+0xf6/0x2f0 mm/slub.c:3919 > kvfree+0x3b/0x60 mm/util.c:416 > netdev_freemem net/core/dev.c:7975 > free_netdev+0x304/0x3c0 net/core/dev.c:8137 > lan78xx_probe+0x21a4/0x3020 drivers/net/usb/lan78xx.c:3649 > usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 > really_probe drivers/base/dd.c:413 > driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 > __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 > bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 > __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 > device_initi
Re: Mouse freezes on button depression
apologies, trying to sort out the SPF errors I've been getting On 25/09/17 22:22, Oliver Neukum wrote: Am Sonntag, den 24.09.2017, 13:14 +1000 schrieb Christian Bullow: Upon depressing the DIP switch or forward/backward buttons, the mouse freezes and is unresponsive. The only way to fix this is my unplugging it, and putting it into a /different/ USB port. I am happy to be guided as to how to inform you of the issue and/or capture the messaging from the mouse buttons. *dmesg output* [ 1386.760402] usb 1-1.1: USB disconnect, device number 3 [ 1389.758884] usb 1-1.1: new full-speed USB device number 4 using ehci-pci [ 1389.872812] usb 1-1.1: New USB device found, idVendor=1044, idProduct=7a13 [ 1389.872816] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 1389.872818] usb 1-1.1: Product: MSP430-USB Mouse [ 1389.872820] usb 1-1.1: Manufacturer: Texas Instruments [ 1389.872822] usb 1-1.1: SerialNumber: 8C2F0C5132000C00 [ 1389.903323] input: Texas Instruments MSP430-USB Mouse as /devices/pci:00/:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/0003:1044:7A13.0007/input/input27 [ 1389.963586] hid-generic 0003:1044:7A13.0007: input,hidraw0: USB HID v1.01 Keyboard [Texas Instruments MSP430-USB Mouse] on usb-:00:1a.0-1.1/input0 [ 1389.966651] input: Texas Instruments MSP430-USB Mouse as /devices/pci:00/:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1/0003:1044:7A13.0008/input/input28 [ 1390.027363] hid-generic 0003:1044:7A13.0008: input,hidraw2: USB HID v1.01 Mouse [Texas Instruments MSP430-USB Mouse] on usb-:00:1a.0-1.1/input1 [ 1390.031052] input: Texas Instruments MSP430-USB Mouse as /devices/pci:00/:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.2/0003:1044:7A13.0009/input/input29 [ 1390.091874] hid-generic 0003:1044:7A13.0009: input,hiddev0,hidraw3: USB HID v1.01 Mouse [Texas Instruments MSP430-USB Mouse] on usb-:00:1a.0-1.1/input2 [ 1400.113061] hid-generic 0003:1044:7A13.000A: timeout initializing reports [ 1400.113386] hid-generic 0003:1044:7A13.000A: hiddev0,hidraw5: USB HID v1.01 Device [Texas Instruments MSP430-USB Mouse] on usb-:00:1a.0-1.1/input3 Hi, this dmesg as such is pretty uninformative. Is that what you get as you plug in the mouse or as you push the button? If the latter, we will need a usbmon trace. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] HID: usbhid: fix out-of-bounds bug
On Wed, 27 Sep 2017, Michel Hermier wrote: > Le 27 sept. 2017 07:42, "Alan Stern" a écrit : > > - for (n = 0; n < hdesc->bNumDescriptors; n++) > > + num_descriptors = min_t(int, hdesc->bNumDescriptors, > > + (hdesc->bLength - 6) / 3); > > + for (n = 0; n < num_descriptors; n++) > > if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) > > rsize = le16_to_cpu(hdesc->desc[n]. > wDescriptorLength); > > Yes, this is a lot better. > > > Is it possible to explicit the magic number 6 and 3 in the code. Currently, > it looks like it comes from no where. Yes, it is possible. The 6 is equal to offsetof(struct hid_descriptor, desc) and the 3 is equal to sizeof(struct hid_class_descriptor) (at least, I think it is -- the structure is marked as packed so its size should be 3). In this case I found the numbers to be more readable, but other people may have different opinions. > I'm also wondering if this change will not affect some devices in the wild, > by rejecting hid descriptors with num descriptors == 0 ? It's possible, but I doubt it. If such devices do exist, they should never have worked in the first place. Certainly they would generate warnings or errors during enumeration because of their invalid descriptors. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH resend 09/12] usb: typec: tcpm: only drives the connected cc line when attached
Hi Li, [auto build test ERROR on staging/staging-testing] [also build test ERROR on v4.14-rc2 next-20170927] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Li-Jun/staging-typec-tcpci-move-out-of-staging/20170927-190852 config: i386-allmodconfig (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=i386 Note: the linux-review/Li-Jun/staging-typec-tcpci-move-out-of-staging/20170927-190852 HEAD 9e1467d3603f3cee8f039d52010dfb8d33e2b29c builds fine. It only hurts bisectibility. All errors (new ones prefixed by >>): drivers/staging/typec/tcpci.c: In function 'tcpci_probe': >> drivers/staging/typec/tcpci.c:574:21: error: assignment from incompatible >> pointer type [-Werror=incompatible-pointer-types] tcpci->tcpc.set_cc = tcpci_set_cc; ^ cc1: some warnings being treated as errors vim +574 drivers/staging/typec/tcpci.c 74e656d6 Guenter Roeck 2017-04-27 553 74e656d6 Guenter Roeck 2017-04-27 554 static int tcpci_probe(struct i2c_client *client, 74e656d6 Guenter Roeck 2017-04-27 555 const struct i2c_device_id *i2c_id) 74e656d6 Guenter Roeck 2017-04-27 556 { 74e656d6 Guenter Roeck 2017-04-27 557 struct tcpci *tcpci; 74e656d6 Guenter Roeck 2017-04-27 558 int err; 74e656d6 Guenter Roeck 2017-04-27 559 74e656d6 Guenter Roeck 2017-04-27 560 tcpci = devm_kzalloc(&client->dev, sizeof(*tcpci), GFP_KERNEL); 74e656d6 Guenter Roeck 2017-04-27 561 if (!tcpci) 74e656d6 Guenter Roeck 2017-04-27 562 return -ENOMEM; 74e656d6 Guenter Roeck 2017-04-27 563 74e656d6 Guenter Roeck 2017-04-27 564 tcpci->client = client; 74e656d6 Guenter Roeck 2017-04-27 565 tcpci->dev = &client->dev; 74e656d6 Guenter Roeck 2017-04-27 566 i2c_set_clientdata(client, tcpci); 74e656d6 Guenter Roeck 2017-04-27 567 tcpci->regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config); 74e656d6 Guenter Roeck 2017-04-27 568 if (IS_ERR(tcpci->regmap)) 74e656d6 Guenter Roeck 2017-04-27 569 return PTR_ERR(tcpci->regmap); 74e656d6 Guenter Roeck 2017-04-27 570 74e656d6 Guenter Roeck 2017-04-27 571 tcpci->tcpc.init = tcpci_init; 74e656d6 Guenter Roeck 2017-04-27 572 tcpci->tcpc.get_vbus = tcpci_get_vbus; 74e656d6 Guenter Roeck 2017-04-27 573 tcpci->tcpc.set_vbus = tcpci_set_vbus; 74e656d6 Guenter Roeck 2017-04-27 @574 tcpci->tcpc.set_cc = tcpci_set_cc; 74e656d6 Guenter Roeck 2017-04-27 575 tcpci->tcpc.get_cc = tcpci_get_cc; 74e656d6 Guenter Roeck 2017-04-27 576 tcpci->tcpc.set_polarity = tcpci_set_polarity; 74e656d6 Guenter Roeck 2017-04-27 577 tcpci->tcpc.set_vconn = tcpci_set_vconn; 74e656d6 Guenter Roeck 2017-04-27 578 tcpci->tcpc.start_drp_toggling = tcpci_start_drp_toggling; 74e656d6 Guenter Roeck 2017-04-27 579 74e656d6 Guenter Roeck 2017-04-27 580 tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx; 74e656d6 Guenter Roeck 2017-04-27 581 tcpci->tcpc.set_roles = tcpci_set_roles; 74e656d6 Guenter Roeck 2017-04-27 582 tcpci->tcpc.pd_transmit = tcpci_pd_transmit; 74e656d6 Guenter Roeck 2017-04-27 583 74e656d6 Guenter Roeck 2017-04-27 584 err = tcpci_parse_config(tcpci); 74e656d6 Guenter Roeck 2017-04-27 585 if (err < 0) 74e656d6 Guenter Roeck 2017-04-27 586 return err; 74e656d6 Guenter Roeck 2017-04-27 587 74e656d6 Guenter Roeck 2017-04-27 588 /* Disable chip interrupts */ 74e656d6 Guenter Roeck 2017-04-27 589 tcpci_write16(tcpci, TCPC_ALERT_MASK, 0); 74e656d6 Guenter Roeck 2017-04-27 590 d94372b5 Li Jun2017-09-26 591 tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc); d94372b5 Li Jun2017-09-26 592 if (IS_ERR(tcpci->port)) d94372b5 Li Jun2017-09-26 593 return PTR_ERR(tcpci->port); d94372b5 Li Jun2017-09-26 594 d94372b5 Li Jun2017-09-26 595 return devm_request_threaded_irq(tcpci->dev, client->irq, NULL, 74e656d6 Guenter Roeck 2017-04-27 596 tcpci_irq, 74e656d6 Guenter Roeck 2017-04-27 597 IRQF_ONESHOT | IRQF_TRIGGER_LOW, 74e656d6 Guenter Roeck 2017-04-27 598 dev_name(tcpci->dev), tcpci); 74e656d6 Guenter Roeck 2017-04-27 599 } 74e656d6 Guenter Roeck 2017-04-27 600 :: The code at line 574 was first introduced by commit :: 74e656d6b0551999194b5ab1e45ff8b1e82b898e staging: typec: Type-C Port Con
usb/misc/rio500: double-free or invalid-free in disconnect_rio
Hi! I've got the following report while fuzzing the kernel with syzkaller. On commit e19b205be43d11bff638cad4487008c48d21c103 (4.14-rc2). gadgetfs: bound to dummy_udc driver usb 1-1: new full-speed USB device number 2 using dummy_hcd gadgetfs: connected gadgetfs: disconnected gadgetfs: connected usb 1-1: config 3 has an invalid interface number: 220 but max is 0 usb 1-1: config 3 has an invalid interface number: 199 but max is 0 usb 1-1: config 3 has 2 interfaces, different from the descriptor's value: 1 usb 1-1: config 3 has no interface number 0 usb 1-1: config 3 has no interface number 1 usb 1-1: too many endpoints for config 3 interface 199 altsetting 74: 151, using maximum allowed: 30 usb 1-1: config 3 interface 199 altsetting 74 has 0 endpoint descriptors, different from the interface d escriptor's value: 151 usb 1-1: config 3 interface 199 has no altsetting 0 usb 1-1: New USB device found, idVendor=0841, idProduct=0001 usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0 gadgetfs: configuration #3 rio500 1-1:3.220: USB Rio found at address 2 rio500 1-1:3.199: USB Rio found at address 2 gadgetfs: disconnected usb 1-1: USB disconnect, device number 2 rio500 1-1:3.220: USB Rio disconnected. == BUG: KASAN: double-free or invalid-free in disconnect_rio+0xef/0x200 CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc2-42660-g24b7bd59eec0 #277 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Workqueue: usb_hub_wq hub_event Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_double_free+0x5a/0x80 mm/kasan/report.c:333 kasan_slab_free+0xa4/0xc0 mm/kasan/kasan.c:514 slab_free_hook mm/slub.c:1390 slab_free_freelist_hook mm/slub.c:1412 slab_free mm/slub.c:2988 kfree+0xf6/0x2f0 mm/slub.c:3919 disconnect_rio+0xef/0x200 drivers/usb/misc/rio500.c:519 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423 __device_release_driver drivers/base/dd.c:861 device_release_driver_internal+0x4f4/0x5c0 drivers/base/dd.c:893 device_release_driver+0x1e/0x30 drivers/base/dd.c:918 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565 device_del+0x5c4/0xab0 drivers/base/core.c:1985 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124 hub_port_connect drivers/usb/core/hub.c:4754 hub_port_connect_change drivers/usb/core/hub.c:5009 port_event drivers/usb/core/hub.c:5115 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 Allocated by task 24: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772 kmalloc ./include/linux/slab.h:493 probe_rio+0x100/0x230 drivers/usb/misc/rio500.c:484 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 hub_port_connect drivers/usb/core/hub.c:4903 hub_port_connect_change drivers/usb/core/hub.c:5009 port_event drivers/usb/core/hub.c:5115 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 Freed by task 24: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524 slab_free_hook mm/slub.c:1390 slab_free_freelist_hook mm/slub.c:1412 slab_free m
usb/serial: use-after-free in usb_serial_disconnect/__lock_acquire
Hi! I've got the following report while fuzzing the kernel with syzkaller. On commit e19b205be43d11bff638cad4487008c48d21c103 (4.14-rc2). gadgetfs: bound to dummy_udc driver usb 1-1: new full-speed USB device number 2 using dummy_hcd gadgetfs: connected gadgetfs: disconnected gadgetfs: connected usb 1-1: config 4 has an invalid interface number: 1 but max is 0 usb 1-1: config 4 has an invalid interface number: 153 but max is 0 usb 1-1: config 4 has 2 interfaces, different from the descriptor's value: 1 usb 1-1: config 4 has no interface number 0 usb 1-1: config 4 interface 1 altsetting 255 has an invalid endpoint with address 0x0, skipping usb 1-1: config 4 interface 1 altsetting 255 has an invalid endpoint with address 0xFF, skipping usb 1-1: config 4 interface 1 altsetting 255 has an invalid endpoint with address 0x56, skipping usb 1-1: too many endpoints for config 4 interface 153 altsetting 67: 174, using maximum allowed: 30 usb 1-1: config 4 interface 153 altsetting 67 has 0 endpoint descriptors, different from the interface d escriptor's value: 174 usb 1-1: config 4 interface 1 has no altsetting 0 usb 1-1: config 4 interface 153 has no altsetting 0 usb 1-1: New USB device found, idVendor=1199, idProduct=6832 usb 1-1: New USB device strings: Mfr=4, Product=20, SerialNumber=3 usb 1-1: Product: a usb 1-1: Manufacturer: a usb 1-1: SerialNumber: a gadgetfs: configuration #4 sierra 1-1:4.1: Sierra USB modem converter detected usb 1-1: Sierra USB modem converter now attached to ttyUSB0 sierra 1-1:4.153: Sierra USB modem converter detected gadgetfs: disconnected usb 1-1: USB disconnect, device number 2 sierra ttyUSB0: Sierra USB modem converter now disconnected from ttyUSB0 sierra 1-1:4.1: device disconnected == BUG: KASAN: use-after-free in __lock_acquire+0x4504/0x4550 Read of size 8 at addr 8800674df790 by task kworker/1:2/1846 CPU: 1 PID: 1846 Comm: kworker/1:2 Not tainted 4.14.0-rc2-42660-g24b7bd59eec0 #277 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Workqueue: usb_hub_wq hub_event Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 kasan_report+0x23d/0x350 mm/kasan/report.c:409 __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430 __lock_acquire+0x4504/0x4550 kernel/locking/lockdep.c:3376 lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002 __mutex_lock_common kernel/locking/mutex.c:756 __mutex_lock+0x18e/0x1a50 kernel/locking/mutex.c:893 mutex_lock_nested+0x1b/0x20 kernel/locking/mutex.c:908 usb_serial_disconnect+0x69/0x2e0 drivers/usb/serial/usb-serial.c:1084 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423 __device_release_driver drivers/base/dd.c:861 device_release_driver_internal+0x4f4/0x5c0 drivers/base/dd.c:893 device_release_driver+0x1e/0x30 drivers/base/dd.c:918 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565 device_del+0x5c4/0xab0 drivers/base/core.c:1985 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124 hub_port_connect drivers/usb/core/hub.c:4754 hub_port_connect_change drivers/usb/core/hub.c:5009 port_event drivers/usb/core/hub.c:5115 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 Allocated by task 1846: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772 kmalloc ./include/linux/slab.h:493 kzalloc ./include/linux/slab.h:666 create_serial drivers/usb/serial/usb-serial.c:605 usb_serial_probe+0x36f/0x4090 drivers/usb/serial/usb-serial.c:892 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+
Re: [PATCH v3 4/8] mtd: nand: atmel: Avoid ECC errors when leaving backup mode
On Wed, 27 Sep 2017 10:35:51 +0200 Romain Izard wrote: > During backup mode, the contents of all registers will be cleared as the > SoC will be completely powered down. For a product that boots on NAND > Flash memory, the bootloader will obviously use the related controller > to read the Flash and correct any detected error in the memory, before > handling back control to the kernel's resuming entry point. > > But it does not clean the NAND controller registers after use and on its > side the kernel driver expects the error locator to be powered down and > in a clean state. Add a resume hook for the PMECC error locator, and > reset its registers. > > Signed-off-by: Romain Izard > --- > Change in v3: > * keep the PMECC disabled when not in use, and use atmel_pmecc_resume to > reset the controller after the bootloader has left it enabled. > > drivers/mtd/nand/atmel/nand-controller.c | 3 +++ > drivers/mtd/nand/atmel/pmecc.c | 22 ++ > drivers/mtd/nand/atmel/pmecc.h | 1 + > 3 files changed, 18 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/nand/atmel/nand-controller.c > b/drivers/mtd/nand/atmel/nand-controller.c > index f25eca79f4e5..86c2199380c2 100644 > --- a/drivers/mtd/nand/atmel/nand-controller.c > +++ b/drivers/mtd/nand/atmel/nand-controller.c > @@ -2530,6 +2530,9 @@ static __maybe_unused int > atmel_nand_controller_resume(struct device *dev) > struct atmel_nand_controller *nc = dev_get_drvdata(dev); > struct atmel_nand *nand; > > + if (nand->pmecc) > + atmel_pmecc_resume(nand->pmecc); > + nand is used uninitialized here, and atmel_pmecc_resume() should be passed a atmel_pmecc object not a atmel_pmecc_user. if (nc->pmecc) atmel_pmecc_resume(nc->pmecc); > list_for_each_entry(nand, &nc->chips, node) { > int i; > > diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c > index 146af8218314..ff09c0f25dd4 100644 > --- a/drivers/mtd/nand/atmel/pmecc.c > +++ b/drivers/mtd/nand/atmel/pmecc.c > @@ -765,6 +765,12 @@ void atmel_pmecc_get_generated_eccbytes(struct > atmel_pmecc_user *user, > } > EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes); > > +void atmel_pmecc_reset(struct atmel_pmecc *pmecc) > +{ > + writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); > + writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); > +} It's not used outside of this file, so it should have a static specifier. Anyway, I wonder why you don't expose atmel_pmecc_reset() directly instead of creating this atmel_pmecc_resume() wrapper. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 4/8] mtd: nand: atmel: Avoid ECC errors when leaving backup mode
2017-09-27 17:08 GMT+02:00 Boris Brezillon : > On Wed, 27 Sep 2017 10:35:51 +0200 > Romain Izard wrote: > >> During backup mode, the contents of all registers will be cleared as the >> SoC will be completely powered down. For a product that boots on NAND >> Flash memory, the bootloader will obviously use the related controller >> to read the Flash and correct any detected error in the memory, before >> handling back control to the kernel's resuming entry point. >> >> But it does not clean the NAND controller registers after use and on its >> side the kernel driver expects the error locator to be powered down and >> in a clean state. Add a resume hook for the PMECC error locator, and >> reset its registers. >> >> Signed-off-by: Romain Izard >> --- >> Change in v3: >> * keep the PMECC disabled when not in use, and use atmel_pmecc_resume to >> reset the controller after the bootloader has left it enabled. >> >> drivers/mtd/nand/atmel/nand-controller.c | 3 +++ >> drivers/mtd/nand/atmel/pmecc.c | 22 ++ >> drivers/mtd/nand/atmel/pmecc.h | 1 + >> 3 files changed, 18 insertions(+), 8 deletions(-) >> >> diff --git a/drivers/mtd/nand/atmel/nand-controller.c >> b/drivers/mtd/nand/atmel/nand-controller.c >> index f25eca79f4e5..86c2199380c2 100644 >> --- a/drivers/mtd/nand/atmel/nand-controller.c >> +++ b/drivers/mtd/nand/atmel/nand-controller.c >> @@ -2530,6 +2530,9 @@ static __maybe_unused int >> atmel_nand_controller_resume(struct device *dev) >> struct atmel_nand_controller *nc = dev_get_drvdata(dev); >> struct atmel_nand *nand; >> >> + if (nand->pmecc) >> + atmel_pmecc_resume(nand->pmecc); >> + > > nand is used uninitialized here, and atmel_pmecc_resume() should be > passed a atmel_pmecc object not a atmel_pmecc_user. > > if (nc->pmecc) > atmel_pmecc_resume(nc->pmecc); > And yet I thought I correctly tested this code... :( >> list_for_each_entry(nand, &nc->chips, node) { >> int i; >> >> diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c >> index 146af8218314..ff09c0f25dd4 100644 >> --- a/drivers/mtd/nand/atmel/pmecc.c >> +++ b/drivers/mtd/nand/atmel/pmecc.c >> @@ -765,6 +765,12 @@ void atmel_pmecc_get_generated_eccbytes(struct >> atmel_pmecc_user *user, >> } >> EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes); >> >> +void atmel_pmecc_reset(struct atmel_pmecc *pmecc) >> +{ >> + writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); >> + writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); >> +} > > It's not used outside of this file, so it should have a static > specifier. Anyway, I wonder why you don't expose atmel_pmecc_reset() > directly instead of creating this atmel_pmecc_resume() wrapper. I will fix this... -- Romain Izard -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Continuous reset of USB device with new USB chip "[AMD] Device 43b9" / AMD X370 chipset
On 09/17/2017 at 09:32 AM, Andreas Hartmann wrote: > Hello again! > > I can add now some more information about this problem: > > - I can see it w/ Fedora 26 boot medium, too. > - I added an usb wireshark trace - hopefully this can be used to detect the > problem. It turned out, that the device is broken. It doesn't work anymore with another old USB chipset, too. Sorry for the noise, regards, Andreas -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2] r8152: add Linksys USB3GIGV1 id
On Wed, Sep 27, 2017 at 12:15 AM, Oliver Neukum wrote: > Am Dienstag, den 26.09.2017, 08:19 -0700 schrieb Doug Anderson: >> >> I know that for at least some of the adapters in the CDC Ethernet >> blacklist it was claimed that the CDC Ethernet support in the adapter >> was kinda broken anyway so the blacklist made sense. ...but for the >> Linksys Gigabit adapter the CDC Ethernet driver seems to work OK, it's >> just not quite as full featured / efficient as the R8152 driver. >> >> Is that not a concern? I guess you could tell people in this >> situation that they simply need to enable the R8152 driver to get >> continued support for their Ethernet adapter? > > Hi, > > yes, it is a valid concern. An #ifdef will be needed. Good idea - I will post V3 shortly. I'm assuming you mean to add #ifdef CONFIG_USB_RTL8152 around the blacklist entry in cdc_ether driver. cheers, grant -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: write to a UVC device
On Mon, Sep 25, 2017 at 7:29 PM, Jaejoong Kim wrote: > Hi, > > The below link will help. > > http://git.ideasonboard.org/uvc-gadget.git > https://lwn.net/Articles/203924/ > > Jaejoong > Thanks for the reply. But I need some clarification. Usually when a character device (which as far as I understand what UVC is) is read or written, all the user does is open, read/write, close. The details are taken care by the driver. Am I correct in understanding that this is not a way to do it with UVC, i.e. the sequence of steps is different (open, some different steps, close) ? -- Rail Shafigulin Software Engineer Esencia Technologies -- *ESENCIA TECHNOLOGIES, INC.*3945 Freedom Circle, Suite #360, Santa Clara CA 95054 Phone: +1 408 736 8284 Fax: +1 408 519 3475 http://www.esenciatech.com | http://www.lnttechservices.com -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] usb: gadget: f_uvc: make uvc_v4l2_fops const
Make this const as it is only stored in the const field of a structure video_device in the file referencing it. Make the declaration const too. Done using Coccinelle. Signed-off-by: Bhumika Goyal --- drivers/usb/gadget/function/uvc_v4l2.c | 2 +- drivers/usb/gadget/function/uvc_v4l2.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 3e22b45..6612402 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -354,7 +354,7 @@ static unsigned long uvcg_v4l2_get_unmapped_area(struct file *file, } #endif -struct v4l2_file_operations uvc_v4l2_fops = { +const struct v4l2_file_operations uvc_v4l2_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release= uvc_v4l2_release, diff --git a/drivers/usb/gadget/function/uvc_v4l2.h b/drivers/usb/gadget/function/uvc_v4l2.h index 2683b92..ad6ca06 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.h +++ b/drivers/usb/gadget/function/uvc_v4l2.h @@ -17,6 +17,6 @@ #define __UVC_V4L2_H__ extern const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops; -extern struct v4l2_file_operations uvc_v4l2_fops; +extern const struct v4l2_file_operations uvc_v4l2_fops; #endif /* __UVC_V4L2_H__ */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3] r8152: add Linksys USB3GIGV1 id
This linksys dongle by default comes up in cdc_ether mode. This patch allows r8152 to claim the device: Bus 002 Device 002: ID 13b1:0041 Linksys Signed-off-by: Grant Grundler --- drivers/net/usb/cdc_ether.c | 10 ++ drivers/net/usb/r8152.c | 2 ++ 2 files changed, 12 insertions(+) V3: for backwards compat, add #ifdef CONFIG_USB_RTL8152 around the cdc_ether blacklist entry so the cdc_ether driver can still claim the device if r8152 driver isn't configured. V2: add LINKSYS_VENDOR_ID to cdc_ether blacklist diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 8ab281b478f2..446dcc0f1f70 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -546,6 +546,7 @@ static const struct driver_info wwan_info = { #define DELL_VENDOR_ID 0x413C #define REALTEK_VENDOR_ID 0x0bda #define SAMSUNG_VENDOR_ID 0x04e8 +#define LINKSYS_VENDOR_ID 0x13b1 #define LENOVO_VENDOR_ID 0x17ef #define NVIDIA_VENDOR_ID 0x0955 #define HP_VENDOR_ID 0x03f0 @@ -737,6 +738,15 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +#ifdef CONFIG_USB_RTL8152 +/* Linksys USB3GIGV1 Ethernet Adapter */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, +#endif + /* ThinkPad USB-C Dock (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index ceb78e2ea4f0..941ece08ba78 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -613,6 +613,7 @@ enum rtl8152_flags { #define VENDOR_ID_MICROSOFT0x045e #define VENDOR_ID_SAMSUNG 0x04e8 #define VENDOR_ID_LENOVO 0x17ef +#define VENDOR_ID_LINKSYS 0x13b1 #define VENDOR_ID_NVIDIA 0x0955 #define MCU_TYPE_PLA 0x0100 @@ -5316,6 +5317,7 @@ static const struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {} }; -- 2.14.2.822.g60be5d43e6-goog -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
Hi Manu, On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote: > VBUS signal coming from PHY must be asserted in device for > controller to start operation or assert pull-up. For some > platforms where VBUS line is not connected to PHY there is > HS_PHY_CTRL register in QSCRATCH wrapper that can be used > by software to override VBUS signal going to controller. > > Signed-off-by: Manu Gautam > --- > > +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) > +{ > + struct qusb2_phy *qphy = phy_get_drvdata(phy); > + > + qphy->mode = mode; > + > + /* Update VBUS override in qscratch register */ > + if (qphy->qscratch_base) { > + if (mode == PHY_MODE_USB_DEVICE) > + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, > + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); > + else > + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, > + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); Wouldn't this be better off handled in the controller glue driver? Two reasons I think this patch is unattractive: - qscratch_base is part of the controller's register space. Your later patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in device mode") does a similar thing and hence both drivers have to ioremap() the same register resource while at the same time avoiding request_mem_region() (called by devm_ioremap_resource) to allow it to be mapped in both places. - VBUS override bit becomes asserted simply because the mode is changed to device mode but this is irrespective of the actual VBUS state. This could break some test setups which perform a logical disconnect by switching off/on VBUS while leaving data lines connected. Controller would go merrily along thinking it is still attached to the host. Instead maybe this could be tied to EXTCON_USB handling in the glue driver; though it would need to be an additional notifier on top of dwc3/drd.c which already handles extcon for host/device mode. Jack -- The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY
On Wed, Sep 27, 2017 at 02:29:09PM +0530, Manu Gautam wrote: > QMP V3 USB3 PHY is a DP USB combo PHY with > dual RX/TX lanes to support type-c. There is a > separate block DP_COM for configuration related > to type-c or DP. Add support for dp_com region > and secondary rx/tx lanes initialization. Clarify "DP" as DisplayPort here? Jack -- The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
On Wed, Sep 27, 2017 at 10:57:41AM -0700, Jack Pham wrote: > Hi Manu, > > On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote: > > VBUS signal coming from PHY must be asserted in device for > > controller to start operation or assert pull-up. For some > > platforms where VBUS line is not connected to PHY there is > > HS_PHY_CTRL register in QSCRATCH wrapper that can be used > > by software to override VBUS signal going to controller. > > > > Signed-off-by: Manu Gautam > > --- > > > > +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) > > +{ > > + struct qusb2_phy *qphy = phy_get_drvdata(phy); > > + > > + qphy->mode = mode; > > + > > + /* Update VBUS override in qscratch register */ > > + if (qphy->qscratch_base) { > > + if (mode == PHY_MODE_USB_DEVICE) > > + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, > > + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); > > + else > > + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, > > + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); > > Wouldn't this be better off handled in the controller glue driver? Two > reasons I think this patch is unattractive: > > - qscratch_base is part of the controller's register space. Your later > patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in > device mode") does a similar thing and hence both drivers have to > ioremap() the same register resource while at the same time avoiding > request_mem_region() (called by devm_ioremap_resource) to allow it to > be mapped in both places. > > - VBUS override bit becomes asserted simply because the mode is changed > to device mode but this is irrespective of the actual VBUS state. This > could break some test setups which perform a logical disconnect by > switching off/on VBUS while leaving data lines connected. Controller > would go merrily along thinking it is still attached to the host. > > Instead maybe this could be tied to EXTCON_USB handling in the glue > driver; though it would need to be an additional notifier on top of > dwc3/drd.c which already handles extcon for host/device mode. That is to say, we'd probably need to split out dwc3-qcom from dwc3-of-simple.c into its own driver (again) in order to add this. Jack -- The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Type-C port on the Asmedia ASM1142
On Wed, 27 Sep 2017 11:03:41 +0300 Mathias Nyman wrote: > Ok, please let me know which register you refer to, I'd like to get this > fixed as soon as possible. > Based on what you say I suspect that you talk about the SBRN (Serial bus > release number). > > The early xhci 1.1 spec that was used to write USB3.1 SSP support stated that > SBRN contain > the serial bus specification release, (in hex) with examples of 30h for USB > 3.0 and 31h for USB 3.1 > > Driver uses this to determine if hosts supports USB 3.0 or usb 3.1 > > I see that the current public xhci spec only mention 30h (USB 3.0), and in a > way that it can be > interpreted as 30 being the only option. > If this is the case then SBRN itself would be completely useless. > Why have a register with the purpose of telling which serial bus release > number the hardware > supports always forced to 30h? > > Yes, the first Intel Alpine ridge based USB 3.1 SSP 10Gbps xHCI hosts had > this as 30, > Newer Intel USB 3.1 SSP capable 10Gbps xHCI hosts have it set to 31h > > If vendors have interpreted it as "SBRN must equal 30h" then we need to work > around that in the driver. > > We can check if the host supports USB 3.1 from the ports supported protocol > capability, > see xhci 7.2 xHCI supported protocol capability, major and minor revision > fields. These > should at least contain major=3 and minor=1 for USB 3.1 capable ports. > > That at least is unambiguous in all xhci specs (early, and current public) Yes, indeed, your guess is correct. I was writing about SBRN. In the function "xhci_pci_setup", from the file "drivers/usb/host/xhci-pci.c", SBRN is read and stored in "xhci->sbrn". Then, in the function "xhci_gen_setup", from the file "drivers/usb/host/xhci.c", the value of "xhci->sbrn" is checked. If it is 0x31, then support for 10 Gb/s is assumed. This check was introduced in a patch from the 1st October 2015. It must have worked once, because I have seen some Linux screen shots with the output of lsusb showing some xHCI controller with 10 Gb/s support. I am not aware of any USB 3.1 controllers that existed in 2015 and that could have SBRN equal to 0x31, except for some earlier ASMedia controllers. AFAIK, there were at least 2 versions before ASM 1142, so one or both of them must have had SBRN equal to 0x31. I have verified on many motherboards that both Alpine Ridge and ASM 1142 have SBRN equal to 0x30. Moreover, the ASM 1142 datasheet says clearly that SBRN is 0x30. Therefore, I believe that ASMedia has understood the xHCI specification exactly as it is written, i.e. that SBRN must be 0x30, and they have reverted its value from the earlier 0x31 to 0x30. There are at least 2 newer ASMedia USB 3.1 controllers (2142 & 3142). I do not know what value they use for SBRN, but 0x30 is likely. Nevertheless, even if we ignore this history of unpredictable SBRN values, it is wrong to believe that any USB 3.1 controller supports 10 Gb/s operation. The evidence for this is all the b*s*t advertising about "USB 3.1 Gen 1", i.e. 5 Gb/s (4 Gb/s actually) speed. Moreover, very soon USB 3.2 devices will appear. USB 3.2 introduces 2 more speeds, so a USB 3.2 xHCI controller will support some or all of 4 speeds: 1 * 5 Gb/s (actually 4 Gb/s), 2 * 5 Gb/s (actually 8 Gb/s), 1 * 10 Gb/s (i.e. 10 Gb/s) and 2 * 10 Gb/s (i.e. 20 Gb/s). It is very likely that some USB 3.2 xHCI controllers will not support all speeds, especially because the 2-lane speeds are possible only over Type C connectors, so the same controller will support all speeds on some motherboards but only some of them when used with Type A connectors. In conclusion, the supported speeds must be detected independently of the USB release number. The xHCI Specification describes an appropriate source for this information, at the "xHCI Supported Protocol Capability", in the "Protocol Speed ID" Dwords. There are chances that I might have time during this weekend to test some USB 3.1 xHCI controllers to see how this works. If you can work on this sooner, you are welcome. While reading the extra capability registers should be easy, what should be thought carefully is how to change the existing structures which store information about the xHCI controller, to accomodate the extra speeds that will be available soon and the fact that the set of supported speeds is not necessarily determined by the USB version number. Like I said, while I patched my kernel and now my xHCI controllers are recognized as supporting 10 Gb/s, the SSDs with USB-SATA bridges that I have connected are still not recognized as also supporting 10 Gb/s. I believe that the problem is caused by other parts of the xHCI specification that are not implemented, but I did not have time yet to identify them. Best regards ! -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo
[PATCH] rndis_host: support Novatel Verizon USB730L
Treat the ef/04/01 interface class/subclass/protocol combination used by the Novatel Verizon USB730L (1410:9030) as a possible RNDIS interface. T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 17 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 3 P: Vendor=1410 ProdID=9030 Rev=03.10 S: Manufacturer=Novatel Wireless S: Product=MiFi USB730L S: SerialNumber=0123456789ABCDEF C: #Ifs= 3 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=ef(misc ) Sub=04 Prot=01 Driver=rndis_host I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host I: If#= 2 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid Once the network interface is brought up, the user just needs to run a DHCP client to get IP address and routing setup. As a side note, other Novatel Verizon USB730L models with the same vid:pid end up exposing a standard ECM interface which doesn't require any other kernel update to make it work. Signed-off-by: Aleksander Morgado --- Hey, I'm not sure if binding this logic to a specific vid:pid (1410:9030) would be more appropriate here, or if it's ok to just bind class/subclass/protocol (as in the activesync case). Let me know what you think. --- drivers/net/usb/cdc_ether.c | 11 ++- drivers/net/usb/rndis_host.c | 4 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 8ab281b478f2..2df0bcc6d30b 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -54,11 +54,19 @@ static int is_wireless_rndis(struct usb_interface_descriptor *desc) desc->bInterfaceProtocol == 3); } +static int is_novatel_rndis(struct usb_interface_descriptor *desc) +{ + return (desc->bInterfaceClass == USB_CLASS_MISC && + desc->bInterfaceSubClass == 4 && + desc->bInterfaceProtocol == 1); +} + #else #define is_rndis(desc) 0 #define is_activesync(desc)0 #define is_wireless_rndis(desc)0 +#define is_novatel_rndis(desc) 0 #endif @@ -150,7 +158,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) */ rndis = (is_rndis(&intf->cur_altsetting->desc) || is_activesync(&intf->cur_altsetting->desc) || -is_wireless_rndis(&intf->cur_altsetting->desc)); +is_wireless_rndis(&intf->cur_altsetting->desc) || +is_novatel_rndis(&intf->cur_altsetting->desc)); memset(info, 0, sizeof(*info)); info->control = intf; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index a151f267aebb..b807c91abe1d 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -632,6 +632,10 @@ static const struct usb_device_id products [] = { /* RNDIS for tethering */ USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), .driver_info = (unsigned long) &rndis_info, +}, { + /* Novatel Verizon USB730L */ + USB_INTERFACE_INFO(USB_CLASS_MISC, 4, 1), + .driver_info = (unsigned long) &rndis_info, }, { },// END }; -- 2.14.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V3] r8152: add Linksys USB3GIGV1 id
Hi, On Wed, Sep 27, 2017 at 10:28 AM, Grant Grundler wrote: > This linksys dongle by default comes up in cdc_ether mode. > This patch allows r8152 to claim the device: >Bus 002 Device 002: ID 13b1:0041 Linksys > > Signed-off-by: Grant Grundler > --- > drivers/net/usb/cdc_ether.c | 10 ++ > drivers/net/usb/r8152.c | 2 ++ > 2 files changed, 12 insertions(+) > > V3: for backwards compat, add #ifdef CONFIG_USB_RTL8152 around > the cdc_ether blacklist entry so the cdc_ether driver can > still claim the device if r8152 driver isn't configured. > > V2: add LINKSYS_VENDOR_ID to cdc_ether blacklist > > diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c > index 8ab281b478f2..446dcc0f1f70 100644 > --- a/drivers/net/usb/cdc_ether.c > +++ b/drivers/net/usb/cdc_ether.c > @@ -546,6 +546,7 @@ static const struct driver_info wwan_info = { > #define DELL_VENDOR_ID 0x413C > #define REALTEK_VENDOR_ID 0x0bda > #define SAMSUNG_VENDOR_ID 0x04e8 > +#define LINKSYS_VENDOR_ID 0x13b1 > #define LENOVO_VENDOR_ID 0x17ef Slight nit that "LI" sorts after "LE". You got it right in the other case... > #define NVIDIA_VENDOR_ID 0x0955 > #define HP_VENDOR_ID 0x03f0 > @@ -737,6 +738,15 @@ static const struct usb_device_id products[] = { > .driver_info = 0, > }, > > +#ifdef CONFIG_USB_RTL8152 > +/* Linksys USB3GIGV1 Ethernet Adapter */ > +{ > + USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, > USB_CLASS_COMM, > + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), > + .driver_info = 0, > +}, > +#endif I believe you want to use IS_ENABLED(), don't you? There's still a weird esoteric side case where kernel modules don't all need to be included in the filesystem just because they were built at the same time. ...but IMHO that seems like enough of a nit that we can probably ignore it unless someone has a better idea. -Doug -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V3] r8152: add Linksys USB3GIGV1 id
Hi Doug! On Wed, Sep 27, 2017 at 4:47 PM, Doug Anderson wrote: > Hi, > > On Wed, Sep 27, 2017 at 10:28 AM, Grant Grundler > wrote: >> This linksys dongle by default comes up in cdc_ether mode. >> This patch allows r8152 to claim the device: >>Bus 002 Device 002: ID 13b1:0041 Linksys >> >> Signed-off-by: Grant Grundler >> --- >> drivers/net/usb/cdc_ether.c | 10 ++ >> drivers/net/usb/r8152.c | 2 ++ >> 2 files changed, 12 insertions(+) >> >> V3: for backwards compat, add #ifdef CONFIG_USB_RTL8152 around >> the cdc_ether blacklist entry so the cdc_ether driver can >> still claim the device if r8152 driver isn't configured. >> >> V2: add LINKSYS_VENDOR_ID to cdc_ether blacklist >> >> diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c >> index 8ab281b478f2..446dcc0f1f70 100644 >> --- a/drivers/net/usb/cdc_ether.c >> +++ b/drivers/net/usb/cdc_ether.c >> @@ -546,6 +546,7 @@ static const struct driver_info wwan_info = { >> #define DELL_VENDOR_ID 0x413C >> #define REALTEK_VENDOR_ID 0x0bda >> #define SAMSUNG_VENDOR_ID 0x04e8 >> +#define LINKSYS_VENDOR_ID 0x13b1 >> #define LENOVO_VENDOR_ID 0x17ef > > Slight nit that "LI" sorts after "LE". You got it right in the other case... The list isn't sorted by any rational thing I can see. I managed to check my OCD reaction to sort the list numerically. :) >> #define NVIDIA_VENDOR_ID 0x0955 >> #define HP_VENDOR_ID 0x03f0 >> @@ -737,6 +738,15 @@ static const struct usb_device_id products[] = { >> .driver_info = 0, >> }, >> >> +#ifdef CONFIG_USB_RTL8152 >> +/* Linksys USB3GIGV1 Ethernet Adapter */ >> +{ >> + USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, >> USB_CLASS_COMM, >> + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), >> + .driver_info = 0, >> +}, >> +#endif > > I believe you want to use IS_ENABLED(), don't you? Ah yes - I wasn't aware IS_ENABLED existed. Will respin V4 with this if there isn't any other feedback. > There's still a weird esoteric side case where kernel modules don't > all need to be included in the filesystem just because they were built > at the same time. ...but IMHO that seems like enough of a nit that we > can probably ignore it unless someone has a better idea. I think that would require a run time check. I'm perfectly willing to ignore that case. :) thanks! grant > > > -Doug -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 11/12] dt-bindings: usb: mtu3: remove dummy clocks and add optional ones
Remove dummy clocks for usb wakeup and add optional ones for mcu_bus and dma_bus bus. Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 7c611d1..49c982b 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -14,9 +14,9 @@ Required properties: - vusb33-supply : regulator of USB avdd3.3v - clocks : a list of phandle + clock-specifier pairs, one for each entry in clock-names - - clock-names : must contain "sys_ck" and "ref_ck" for clock of controller; - "wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are - depends on "mediatek,enable-wakeup" + - clock-names : must contain "sys_ck" for clock of controller, + the following clocks are optional: + "ref_ck", "mcu_ck" and "dam_ck"; - phys : a list of phandle + phy specifier pairs - dr_mode : should be one of "host", "peripheral" or "otg", refer to usb/generic.txt @@ -65,9 +65,7 @@ ssusb: usb@11271000 { clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>, <&pericfg CLK_PERI_USB0>, <&pericfg CLK_PERI_USB1>; - clock-names = "sys_ck", "ref_ck", - "wakeup_deb_p0", - "wakeup_deb_p1"; + clock-names = "sys_ck", "ref_ck"; vusb33-supply = <&mt6397_vusb_reg>; vbus-supply = <&usb_p0_vbus>; extcon = <&extcon_usb>; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/12] dt-bindings: usb: mtu3: remove optional pinctrls
Remove optional pinctrls due to using FORCE/RG_IDDIG to implement manual switch function. Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/usb/mediatek,mtu3.txt |7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 49c982b..b2271d8 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -30,9 +30,10 @@ Optional properties: when supports dual-role mode. - vbus-supply : reference to the VBUS regulator, needed when supports dual-role mode. - - pinctl-names : a pinctrl state named "default" must be defined, - "id_float" and "id_ground" are optinal which depends on - "mediatek,enable-manual-drd" + - pinctrl-names : a pinctrl state named "default" is optional, and need be + defined if auto drd switch is enabled, that means the property dr_mode + is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" + is not set. - pinctrl-0 : pin control group See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/12] dt-bindings: usb: mtu3: add a optional property to disable u3ports
Add a new optional property to disable u3ports Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/usb/mediatek,mtu3.txt |2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 49f5476..7c611d1 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -44,6 +44,8 @@ Optional properties: - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup control register, it depends on "mediatek,enable-wakeup". + - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, + bit1 for u3port1, ... etc; Sub-nodes: The xhci should be added as subnode to mtu3 as shown in the following example -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: write to a UVC device
2017-09-28 2:07 GMT+09:00 Rail Shafigulin : > On Mon, Sep 25, 2017 at 7:29 PM, Jaejoong Kim wrote: >> Hi, >> >> The below link will help. >> >> http://git.ideasonboard.org/uvc-gadget.git >> https://lwn.net/Articles/203924/ >> >> Jaejoong >> > > Thanks for the reply. But I need some clarification. Usually when a > character device (which as far as I understand what UVC is) is read or > written, all the user does is open, read/write, close. All of the character devices is not working properly with low level I/O. The details are > taken care by the driver. Am I correct in understanding that this is > not a way to do it with UVC, i.e. the sequence of steps is different > (open, some different steps, close) ? yes. you need to know how to talk with UVC. This article will be help. https://lwn.net/Articles/203924/ Jaejoong > > -- > Rail Shafigulin > Software Engineer > Esencia Technologies > > -- > > > > > *ESENCIA TECHNOLOGIES, INC.*3945 Freedom Circle, Suite #360, > Santa Clara CA 95054 > > > Phone: +1 408 736 8284 Fax: +1 408 519 3475 > http://www.esenciatech.com | http://www.lnttechservices.com > > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
Hi Jack, On 9/28/2017 12:46 AM, Jack Pham wrote: > On Wed, Sep 27, 2017 at 10:57:41AM -0700, Jack Pham wrote: >> Hi Manu, >> >> On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote: >>> VBUS signal coming from PHY must be asserted in device for >>> controller to start operation or assert pull-up. For some >>> platforms where VBUS line is not connected to PHY there is >>> HS_PHY_CTRL register in QSCRATCH wrapper that can be used >>> by software to override VBUS signal going to controller. >>> >>> Signed-off-by: Manu Gautam >>> --- >>> >>> +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) >>> +{ >>> + struct qusb2_phy *qphy = phy_get_drvdata(phy); >>> + >>> + qphy->mode = mode; >>> + >>> + /* Update VBUS override in qscratch register */ >>> + if (qphy->qscratch_base) { >>> + if (mode == PHY_MODE_USB_DEVICE) >>> + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, >>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); >>> + else >>> + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL, >>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); >> Wouldn't this be better off handled in the controller glue driver? Two >> reasons I think this patch is unattractive: >> >> - qscratch_base is part of the controller's register space. Your later >> patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in >> device mode") does a similar thing and hence both drivers have to >> ioremap() the same register resource while at the same time avoiding >> request_mem_region() (called by devm_ioremap_resource) to allow it to >> be mapped in both places. Right. There is one more reason why qusb2 driver needs qscratch: - During runtime suspend, it has to check linestate to set correct polarity for dp/dm wakeup interrupt in order to detect disconnect/resume ion LS and FS/HS modes. >> - VBUS override bit becomes asserted simply because the mode is changed >> to device mode but this is irrespective of the actual VBUS state. This >> could break some test setups which perform a logical disconnect by >> switching off/on VBUS while leaving data lines connected. Controller >> would go merrily along thinking it is still attached to the host. >> >> Instead maybe this could be tied to EXTCON_USB handling in the glue >> driver; though it would need to be an additional notifier on top of >> dwc3/drd.c which already handles extcon for host/device mode. Yes, dwc3/drd.c currently deals with only EXTCON_USB_HOST. So, for platforms where role swap happens using only Vbus or single GPIO this should take care of. > That is to say, we'd probably need to split out dwc3-qcom from > dwc3-of-simple.c into its own driver (again) in order to add this. > > Jack However, I agree that more appropriate place for lane0-pwr-present and vbus override update is dwc3 glue driver. Since we don't have one right now, IMO once we have dwc3-qcom driver in place, this handling can be moved from PHY to glue driver. Until then we can use this approach to get USB device mode working on qcom platforms which are using dwc3-of-simple.c e.g. sdm820 dragonboard. -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Mouse freezes on button depression
Am Mittwoch, den 27.09.2017, 20:49 +1000 schrieb Christian Bullow: > Hi Oliver thank you for your reply. > > Apologies for now replying from gmail. I'm being told my crjb.net > address is failing SPF and that I have to shoehorn this email into > plain-text for you. Here we go :) > > I must correct/clarify that the browser forward and back buttons seem to > work in chrome and that in testing this evening, they have not frozen or > crashed anything. The output I provided before was simply the dmesg > record of the mouse being detected on boot or plugin, not any dmesg > records produced on the depression of the buttons of concern (which are > primarily the DPI+ and DPI- buttons). > > *Relevant output from usbmon (cat /sys/kernel/debug/usb/usbmon/0u)* > > I was able to capture my pressing the dpi+ button twice before the mouse > driver crashed. > > a0b1fca52240 1143494193 C Ii:1:015:2 0:1 8 = > a0b1fca52240 1143494212 S Ii:1:015:2 -115:1 8 < > a0b1fca52240 1144099217 C Ii:1:015:2 0:1 8 = > a0b1fca52240 1144099233 S Ii:1:015:2 -115:1 8 < > > *From lsusb* > > Bus 001 Device 015: ID 1044:7a13 Chu Yuen Enterprise Co., Ltd > > *From cat /sys/kernel/debug/usb/devices* > > T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 15 Spd=12 MxCh= 0 > D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 > P: Vendor=1044 ProdID=7a13 Rev= 2.00 > S: Manufacturer=Texas Instruments > S: Product=MSP430-USB Mouse > S: SerialNumber=8C2F0C5132000C00 > C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA > I:* If#= 0 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=01 Driver=usbhid > E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=15ms > E: Ad=01(O) Atr=03(Int.) MxPS= 8 Ivl=15ms > I:* If#= 1 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid > E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=1ms > E: Ad=02(O) Atr=03(Int.) MxPS= 8 Ivl=1ms > I:* If#= 2 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid > E: Ad=83(I) Atr=03(Int.) MxPS= 8 Ivl=20ms > E: Ad=03(O) Atr=03(Int.) MxPS= 8 Ivl=20ms > I:* If#= 3 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid > E: Ad=84(I) Atr=03(Int.) MxPS= 64 Ivl=1ms > E: Ad=04(O) Atr=03(Int.) MxPS= 64 Ivl=1ms > > Unplugging and re-plugging the mouse in, it moves to Bus 01, Device 16 > and I captured the following: > > *usbmon output from the DPI - button* > > a0b20247ab40 1348549098 C Ii:1:016:2 0:1 8 = > a0b20247ab40 1348549123 S Ii:1:016:2 -115:1 8 <* > * That tells us practically nothing. If you press any button nothing happens? Anything in dmesg? Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html