Re: [PATCH] usb: chipidea: udc: first start device on pullup
On Tue, Nov 12, 2013 at 08:36:47AM +0100, Michael Grzeschik wrote: Hi Peter, On Tue, Nov 12, 2013 at 10:59:09AM +0800, Peter Chen wrote: On Mon, Nov 11, 2013 at 04:37:26PM +0100, Michael Grzeschik wrote: On Mon, Nov 11, 2013 at 09:42:35PM +0800, Peter Chen wrote: On Mon, Nov 11, 2013 at 12:39:30PM +0100, Michael Grzeschik wrote: Don't pullup the resistors on hw_device_state. The gadget framework has the prepared callback for this. This is necessary if we use gadgets which need to be enabled after an userspace application got prepared, or other delayed conditiions have passed. Signed-off-by: Michael Grzeschik m.grzesc...@pengutronix.de --- drivers/usb/chipidea/udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b34c819..976153f 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -84,10 +84,8 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma) /* interrupt, error, port change, reset, sleep/suspend */ hw_write(ci, OP_USBINTR, ~0, USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); - hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); } else { hw_write(ci, OP_USBINTR, ~0, 0); - hw_write(ci, OP_USBCMD, USBCMD_RS, 0); } return 0; } Hi Michael, you submitted a similar patch before to fix uvc problem, but you can't simply delete it, it will cause the udc can't work if we load gadget first, then plug in the usb cable. Yes, you also mentioned this the last time. But here, when the gadget was loaded first and plugged in afterwarts works as well. It can't work at my place, how it can work? There is no place to set usbcmd.rs, you can read the register usbcmd after load gadget module. Did you see when the pullup function get called? I did also send a patch that is changing the pullup call inside the gadget drivers. Current, usbcmd.rs is only set by two places at udc.c - hw_device_state - ci_duc_pullup (if vbus is there) If you delete it at hw_device_state, the usb_gadget_connect can't set it without vbus. I don't know why it can work at your place since there is no place to set USBCMD_RS if we load gadget first, then plug in usb cable. Besides, if the port support dual role switch, if the gadget is loaded first, then do peripheral-host and host-peripheral,(the usbcmd.rs is cleared at that time), then connect vbus, no place to pull up dp. I checked it again. Yes we miss the RS toggle in vbus_session with that patch. Sorry for the confusion. But we somehow need to miss the first RS toggle in ci_udc_start. How about givin hw_device_state an parameter for that. Yes, In fact, there are two places you need to modify: - hw_device_state at chipidea/udc.c - udc_bind_to_driver at gadget/udc-core.c (it will call .pullup, if vbus is there, the usbcmd.rs will still be set) Peter To fix it, it is better mark that gadget as defer_connect, and introduce such condition at udc driver. No, I don't see why this needs to be specially handled inside this driver. We have the framework for this. USBCMD_RS does pullup the DP resistor. The datasheet says, that we have to ensure that the device needs to be properly setup before touching this bit. As the framework does call usb_gadget_connect after the gadget has started and connected to the udc this should be the case. We all hope all things can be done at udc core, but it still has lots of work to do, we had a discussion it before, see below thread: http://marc.info/?l=linux-usbm=136335043303602w=2 I did miss that thread. Thanks, Michael -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0| Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917- | -- Best Regards, Peter Chen -- 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 v4 1/3] usb: ehci: add freescale imx28 special write register method
On Tue, Nov 12, 2013 at 12:02:26AM -0800, Greg KH wrote: On Tue, Nov 12, 2013 at 09:15:18AM +0800, Peter Chen wrote: On Mon, Nov 11, 2013 at 10:32:51PM +0100, Marc Kleine-Budde wrote: On 10/30/2013 04:06 AM, Peter Chen wrote: According to Freescale imx28 Errata, ENGR119653 USB: ARM to USB register error issue, All USB register write operations must use the ARM SWP instruction. So, we implement a special ehci_write for imx28. Discussion for it at below: http://marc.info/?l=linux-usbm=137996395529294w=2 Signed-off-by: Peter Chen peter.c...@freescale.com Acked-by: Alan Stern st...@rowland.harvard.edu --- drivers/usb/host/ehci.h | 13 + 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index e8f41c5..535aa8b 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -225,6 +225,7 @@ struct ehci_hcd { /* one per controller */ unsignedhas_synopsys_hc_bug:1; /* Synopsys HC */ unsignedframe_index_bug:1; /* MosChip (AKA NetMos) */ unsignedneed_oc_pp_cycle:1; /* MPC834X port power */ + unsignedimx28_write_fix:1; /* For Freescale i.MX28 */ /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 6) @@ -728,6 +729,13 @@ static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, #endif } +#ifdef CONFIG_SOC_IMX28 +static inline void imx28_ehci_writel(u32 val32, volatile u32 *addr) You should annotate the addr pointer with __iomem, or better use the signature of ehci_writel(): static inline void imx28_ehci_writel(const unsinged int val32, __u32 __iomem *addr) I agree, but volatile is needed as it needs to read/write from io address. Then the code is wrong, please fix it. Yes, please omit v4, I will send v5 patchset. -- Best Regards, Peter Chen -- 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: xhci: Link TRB must not occur with a USB payload burst.
You're right. I do wish the spec had been written more clearly. I've read a lot of hardware specs in my time ... Reading it all again makes me think that a LINK trb is only allowed on the burst boundary (which might be 16k bytes). The only real way to implement that is to ensure that TD never contain LINK TRB. That's one way to do it. Or you could allow a Link TRB at an intermediate MBP boundary. If all the fragments are larger than the MBP (assume 16k) then that would be relatively easy. However that is very dependant on the source of the data. It might be true for disk data, but is unlikely to be true for ethernet data. For bulk data the link TRB can be forced at a packet boundary by splitting the TD up - the receiving end won't know the difference. It comes down to a question of how often you want the controller to issue an interrupt. If a ring segment is 4 KB (one page), then it can hold 256 TRBs. With scatter-gather transfers, each SG element typically refers to something like a 2-page buffer (depends on how fragmented the memory is). Therefore a ring segment will describe somewhere around 512 pages of data, i.e., something like 2 MB. Since SuperSpeed is 500 MB/s, you'd end up getting in the vicinity of 250 interrupts every second just because of ring segment crossings. 250 interrupts/sec is noise. Send/receive 13000 ethernet packets/sec and then look at the interrupt rate! There is no necessity for taking an interrupt from every link segment. OTOH an interrupt is requested for every bulk TD. I'm sending ethernet data (with TSO) and each TD is just under 64k mostly made up of 3 or 4 fragments. The receive side is interrupting for every receive packet. Using larger ring segments would help. The current ring segments contain 64 entries, a strange choice since they are created with 2 segments. (The ring expansion code soon doubles that for my ethernet traffic.) I would change the code to use a single segment (for coding simplicity) and queue bulk URB when there isn't enough ring space. URB with too many fragments could either be rejected, sent in sections, or partially linearised (and probably still sent in sections). David -- 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: chipidea: udc: first start device on pullup
Don't start hw_device_state on udc_start. The gadget framework has the prepared pullup callback for this. This is necessary if we use gadgets which need to be enabled after an userspace application got prepared, or other delayed conditiions have passed. Signed-off-by: Michael Grzeschik m.grzesc...@pengutronix.de --- Hi Peter, I checked ci_udc_start again and realized that one problem is that we ignore the pullup call and start the device on udc_start. What do you think of the following patch? Any objections? drivers/usb/chipidea/udc.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b34c819..e673263 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1647,11 +1647,6 @@ static int ci_udc_start(struct usb_gadget *gadget, return retval; } - retval = hw_device_state(ci, ci-ep0out-qh.dma); - spin_unlock_irqrestore(ci-lock, flags); - if (retval) - pm_runtime_put_sync(ci-gadget.dev); - return retval; } -- 1.8.4.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: [PATCH] usb: chipidea: udc: first start device on pullup
On Tue, Nov 12, 2013 at 7:50 PM, Michael Grzeschik m.grzesc...@pengutronix.de wrote: Don't start hw_device_state on udc_start. The gadget framework has the prepared pullup callback for this. This is necessary if we use gadgets which need to be enabled after an userspace application got prepared, or other delayed conditiions have passed. Signed-off-by: Michael Grzeschik m.grzesc...@pengutronix.de --- Hi Peter, I checked ci_udc_start again and realized that one problem is that we ignore the pullup call and start the device on udc_start. What do you think of the following patch? Any objections? drivers/usb/chipidea/udc.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b34c819..e673263 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1647,11 +1647,6 @@ static int ci_udc_start(struct usb_gadget *gadget, return retval; } - retval = hw_device_state(ci, ci-ep0out-qh.dma); - spin_unlock_irqrestore(ci-lock, flags); - if (retval) - pm_runtime_put_sync(ci-gadget.dev); - return retval; } Hi Michael, Your code base seems out of date. The reason why we need start controller(call hw_device_state) at ci_udc_start: - For vbus is already there before modprobe gadget, in that case, there is no vbus interrupt due to vbus has not changed during the initialization. - For the platforms which have no vbus interrupt, it needs to start controller before connection otherwise the enumeration can't be started due to usbcmd.rs is 0. -- BR, Peter Chen -- 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: [PATCHv5.1 4/5] check quirk to pad epout buf size when not aligned to maxpacketsize
On Tue, Nov 12 2013, David Cohen wrote: You need to update req-length otherwise it's going to crash DWC3. I'd rather to keep your previous version. That's unfortunate. Do you want me to resend it or will you just send a v6 of your whole series? -- Best regards, _ _ .o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michał “mina86” Nazarewicz(o o) ooo +--m...@google.com--xmpp:min...@jabber.org--ooO--(_)--Ooo-- signature.asc Description: PGP signature
[PATCH] usb: xhci: Add 2nd memory barrier to giveback_first_trb()
There needs to be a wmb() barrier between the write to the cycle bit in the first TRB and the write to the doorbell register. Since it isn't needed in the other places the doobell is rung (because the ring contents haven't been changed) add it to giveback_first_trb() rather than somewhere later. Signed-off-by: David Laight david.lai...@aculab.com --- This patch will only apply cleanly if my earlier patch that affects the previous line has also been applied. drivers/usb/host/xhci-ring.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 35dfed0..8bce4c3 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3136,6 +3136,7 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, */ wmb(); start_trb-field[3] ^= cpu_to_le32(TRB_CYCLE); + wmb(); xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } -- 1.8.1.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
[PATCH v4 15/15] usb: phy: msm: Vote for corner of VDD CX instead of voltage of VDD CX
From: Ivan T. Ivanov iiva...@mm-sol.com New platform uses RBCPR hardware feature, with that voting for absolute voltage of VDD CX is not required. Hence vote for corner of VDD CX which uses nominal corner voltage on VDD CX. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Cc: Mayank Rana mr...@codeaurora.org Cc: devicet...@vger.kernel.org --- .../devicetree/bindings/usb/msm-hsusb.txt |6 drivers/usb/phy/phy-msm-usb.c | 35 +++- include/linux/usb/msm_hsusb.h |1 + 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt index d105ba9..7b46395 100644 --- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt @@ -78,6 +78,11 @@ Optional properties: Some platforms may have configuration to allow USB controller work with any of the two HSPHYs present. +- qcom,vdd-levels: This property must be a list of three integer + values (no, min, max) where each value represents + either a voltage in microvolts or a value corresponding + to voltage corner. + Example HSUSB OTG controller device node: usb@f9a55000 { @@ -100,4 +105,5 @@ Example HSUSB OTG controller device node: qcom,otg-control = 1; qcom,phy-init-sequence = 0x01 0x90 0x; + qcom,vdd-levels = 1 5 7; }; diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 970f96b..b6e18b6 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -62,6 +62,13 @@ #define USB_PHY_VDD_DIG_VOL_MIN100 /* uV */ #define USB_PHY_VDD_DIG_VOL_MAX132 /* uV */ +#define USB_PHY_SUSP_DIG_VOL 50 /* uV */ + +enum vdd_levels { + VDD_LEVEL_NONE = 0, + VDD_LEVEL_MIN, + VDD_LEVEL_MAX, +}; static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) { @@ -69,8 +76,8 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) if (init) { ret = regulator_set_voltage(motg-vddcx, - USB_PHY_VDD_DIG_VOL_MIN, - USB_PHY_VDD_DIG_VOL_MAX); + motg-vdd_levels[VDD_LEVEL_MIN], + motg-vdd_levels[VDD_LEVEL_MAX]); if (ret) { dev_err(motg-phy.dev, Cannot set vddcx voltage\n); return ret; @@ -81,7 +88,7 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) dev_err(motg-phy.dev, unable to enable hsusb vddcx\n); } else { ret = regulator_set_voltage(motg-vddcx, 0, - USB_PHY_VDD_DIG_VOL_MAX); + motg-vdd_levels[VDD_LEVEL_MAX]); if (ret) dev_err(motg-phy.dev, Cannot set vddcx voltage\n); ret = regulator_disable(motg-vddcx); @@ -131,17 +138,16 @@ exit: } #ifdef CONFIG_PM_SLEEP -#define USB_PHY_SUSP_DIG_VOL 50 static int msm_hsusb_config_vddcx(struct msm_otg *motg, int high) { - int max_vol = USB_PHY_VDD_DIG_VOL_MAX; + int max_vol = motg-vdd_levels[VDD_LEVEL_MAX]; int min_vol; int ret; if (high) - min_vol = USB_PHY_VDD_DIG_VOL_MIN; + min_vol = motg-vdd_levels[VDD_LEVEL_MIN]; else - min_vol = USB_PHY_SUSP_DIG_VOL; + min_vol = motg-vdd_levels[VDD_LEVEL_NONE]; ret = regulator_set_voltage(motg-vddcx, min_vol, max_vol); if (ret) { @@ -1437,7 +1443,7 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) const struct of_device_id *id; struct device_node *node = pdev-dev.of_node; int len = 0; - u32 val; + u32 val, tmp[3]; pdata = devm_kzalloc(pdev-dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -1467,6 +1473,19 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) if (!of_property_read_u32(node, qcom,phy-num, val)) motg-phy_number = val; + motg-vdd_levels[VDD_LEVEL_NONE] = USB_PHY_SUSP_DIG_VOL; + motg-vdd_levels[VDD_LEVEL_MIN] = USB_PHY_VDD_DIG_VOL_MIN; + motg-vdd_levels[VDD_LEVEL_MAX] = USB_PHY_VDD_DIG_VOL_MAX; + + if (of_get_property(node, qcom,vdd-levels, len) + len == sizeof(tmp)) { + of_property_read_u32_array(node, qcom,vdd-levels, + tmp, len / sizeof(*tmp)); + motg-vdd_levels[VDD_LEVEL_NONE] = tmp[VDD_LEVEL_NONE]; + motg-vdd_levels[VDD_LEVEL_MIN] = tmp[VDD_LEVEL_MIN]; +
[PATCH v4 09/15] usb: phy: msm: Properly check result from platform_get_irq()
From: Ivan T. Ivanov iiva...@mm-sol.com Function return negative code on error. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 258bca2..fa8e672d 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1412,7 +1412,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) dev_info(pdev-dev, OTG regs = %p\n, motg-regs); motg-irq = platform_get_irq(pdev, 0); - if (!motg-irq) { + if (motg-irq 0) { dev_err(pdev-dev, platform_get_irq failed\n); return motg-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 v4 12/15] usb: phy: msm: Add support for secondary PHY control
From: Ivan T. Ivanov iiva...@mm-sol.com Allow support to use 2nd HSPHY with USB2 Core. Some platforms may have configuration to allow USB controller work with any of the two HSPHYs present. By default driver configures USB core to use primary HSPHY. Add support to allow user select 2nd HSPHY using DT parameter. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Cc: Manu Gautam mgau...@codeaurora.org Cc: devicet...@vger.kernel.org --- .../devicetree/bindings/usb/msm-hsusb.txt |6 + drivers/usb/phy/phy-msm-usb.c | 24 ++-- include/linux/usb/msm_hsusb.h |1 + include/linux/usb/msm_hsusb_hw.h |1 + 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt index 3f21204..d105ba9 100644 --- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt @@ -72,6 +72,12 @@ Optional properties: - qcom,phy-init-sequence: PHY configuration sequence. val, reg pairs terminate with -1 +- qcom,phy-num:Select number of pyco-phy to use, can be one of + 0 - PHY one, default + 1 - Second PHY + Some platforms may have configuration to allow USB + controller work with any of the two HSPHYs present. + Example HSUSB OTG controller device node: usb@f9a55000 { diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 53fc645..01b571ff 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -340,6 +340,9 @@ static int msm_otg_phy_reset(struct msm_otg *motg) if (!retries) return -ETIMEDOUT; + if (motg-phy_number) + writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); + dev_info(motg-phy.dev, phy_reset: success\n); return 0; } @@ -394,6 +397,9 @@ static int msm_otg_reset(struct usb_phy *phy) ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL); } + if (motg-phy_number) + writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); + return 0; } @@ -406,6 +412,7 @@ static int msm_otg_suspend(struct msm_otg *motg) struct usb_phy *phy = motg-phy; struct usb_bus *bus = phy-otg-host; struct msm_otg_platform_data *pdata = motg-pdata; + void __iomem *addr; int cnt = 0; if (atomic_read(motg-in_lpm)) @@ -465,9 +472,13 @@ static int msm_otg_suspend(struct msm_otg *motg) */ writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); + addr = USB_PHY_CTRL; + if (motg-phy_number) + addr = USB_PHY_CTRL2; + if (motg-pdata-phy_type == SNPS_28NM_INTEGRATED_PHY motg-pdata-otg_control == OTG_PMIC_CONTROL) - writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL); + writel(readl(addr) | PHY_RETEN, addr); clk_disable_unprepare(motg-pclk); clk_disable_unprepare(motg-clk); @@ -497,6 +508,7 @@ static int msm_otg_resume(struct msm_otg *motg) { struct usb_phy *phy = motg-phy; struct usb_bus *bus = phy-otg-host; + void __iomem *addr; int cnt = 0; unsigned temp; @@ -510,9 +522,14 @@ static int msm_otg_resume(struct msm_otg *motg) if (motg-pdata-phy_type == SNPS_28NM_INTEGRATED_PHY motg-pdata-otg_control == OTG_PMIC_CONTROL) { + + addr = USB_PHY_CTRL; + if (motg-phy_number) + addr = USB_PHY_CTRL2; + msm_hsusb_ldo_set_mode(motg, 1); msm_hsusb_config_vddcx(motg, 1); - writel(readl(USB_PHY_CTRL) ~PHY_RETEN, USB_PHY_CTRL); + writel(readl(addr) ~PHY_RETEN, addr); } temp = readl(USB_USBCMD); @@ -1395,6 +1412,9 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) if (!of_property_read_u32(node, qcom,otg-control, val)) pdata-otg_control = val; + if (!of_property_read_u32(node, qcom,phy-num, val)) + motg-phy_number = val; + if (!of_get_property(node, qcom,phy-init-sequence, len) || !len) return 0; diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 9bf8943..da3a974 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -156,6 +156,7 @@ struct msm_otg { atomic_t in_lpm; int async_int; unsigned cur_power; + int phy_number; struct delayed_work chg_work; enum usb_chg_state chg_state; enum usb_chg_type chg_type; diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
[PATCH v4 01/15] usb: phy: msm: Move mach dependent code to platform data
From: Ivan T. Ivanov iiva...@mm-sol.com This patch fix compilation error when driver is compiled in multi-platform builds. drivers/built-in.o: In function `msm_otg_link_clk_reset': ./drivers/usb/phy/phy-msm-usb.c:314: undefined reference to `clk_reset' ./drivers/usb/phy/phy-msm-usb.c:318: undefined reference to `clk_reset' Use platform data supplied reset handlers and adjust error messages reported when reset sequence fail. This is an intermediate step before adding support for reset framework and newer targets. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Acked-by: David Brown dav...@codeaurora.org Cc: Daniel Walker dwal...@fifo99.com Cc: Felipe Balbi ba...@ti.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org --- arch/arm/mach-msm/board-msm7x30.c | 35 +++ arch/arm/mach-msm/board-qsd8x50.c | 35 +++ drivers/usb/phy/phy-msm-usb.c | 35 +++ include/linux/usb/msm_hsusb.h |3 +++ 4 files changed, 88 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index f9af5a4..46de789 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -30,6 +30,7 @@ #include asm/memory.h #include asm/setup.h +#include mach/clk.h #include mach/msm_iomap.h #include mach/dma.h @@ -60,10 +61,44 @@ static int hsusb_phy_init_seq[] = { -1 }; +static int hsusb_link_clk_reset(struct clk *link_clk, bool assert) +{ + int ret; + + if (assert) { + ret = clk_reset(link_clk, CLK_RESET_ASSERT); + if (ret) + pr_err(usb hs_clk assert failed\n); + } else { + ret = clk_reset(link_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb hs_clk deassert failed\n); + } + return ret; +} + +static int hsusb_phy_clk_reset(struct clk *phy_clk) +{ + int ret; + + ret = clk_reset(phy_clk, CLK_RESET_ASSERT); + if (ret) { + pr_err(usb phy clk assert failed\n); + return ret; + } + usleep_range(1, 12000); + ret = clk_reset(phy_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb phy clk deassert failed\n); + return ret; +} + static struct msm_otg_platform_data msm_otg_pdata = { .phy_init_seq = hsusb_phy_init_seq, .mode = USB_PERIPHERAL, .otg_control= OTG_PHY_CONTROL, + .link_clk_reset = hsusb_link_clk_reset, + .phy_clk_reset = hsusb_phy_clk_reset, }; struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 5f933bc..9169ec3 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -31,6 +31,7 @@ #include mach/irqs.h #include mach/sirc.h #include mach/vreg.h +#include mach/clk.h #include linux/platform_data/mmc-msm_sdcc.h #include devices.h @@ -81,10 +82,44 @@ static int hsusb_phy_init_seq[] = { -1 }; +static int hsusb_link_clk_reset(struct clk *link_clk, bool assert) +{ + int ret; + + if (assert) { + ret = clk_reset(link_clk, CLK_RESET_ASSERT); + if (ret) + pr_err(usb hs_clk assert failed\n); + } else { + ret = clk_reset(link_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb hs_clk deassert failed\n); + } + return ret; +} + +static int hsusb_phy_clk_reset(struct clk *phy_clk) +{ + int ret; + + ret = clk_reset(phy_clk, CLK_RESET_ASSERT); + if (ret) { + pr_err(usb phy clk assert failed\n); + return ret; + } + usleep_range(1, 12000); + ret = clk_reset(phy_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb phy clk deassert failed\n); + return ret; +} + static struct msm_otg_platform_data msm_otg_pdata = { .phy_init_seq = hsusb_phy_init_seq, .mode = USB_PERIPHERAL, .otg_control= OTG_PHY_CONTROL, + .link_clk_reset = hsusb_link_clk_reset, + .phy_clk_reset = hsusb_phy_clk_reset, }; static struct platform_device *devices[] __initdata = { diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index e9d4cd9..9a47d44 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -40,8 +40,6 @@ #include linux/usb/msm_hsusb_hw.h #include linux/regulator/consumer.h -#include mach/clk.h - #define MSM_USB_BASE (motg-regs) #define DRIVER_NAMEmsm_otg @@ -308,33 +306,30 @@ static void ulpi_init(struct msm_otg *motg) static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) { - int ret; + int ret = 0;
[PATCH v4 05/15] usb: phy: msm: Fix checkpatch.pl warnings
From: Ivan T. Ivanov iiva...@mm-sol.com This fixes following: WARNING: quoted string split across lines WARNING: Prefer seq_puts to seq_printf Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c | 39 ++- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 0bd9614..8f148a6 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -67,8 +67,7 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) USB_PHY_VDD_DIG_VOL_MIN, USB_PHY_VDD_DIG_VOL_MAX); if (ret) { - dev_err(motg-phy.dev, unable to set the voltage - for hsusb vddcx\n); + dev_err(motg-phy.dev, Cannot set vddcx voltage\n); return ret; } @@ -79,8 +78,7 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) ret = regulator_set_voltage(motg-vddcx, 0, USB_PHY_VDD_DIG_VOL_MAX); if (ret) - dev_err(motg-phy.dev, unable to set the voltage - for hsusb vddcx\n); + dev_err(motg-phy.dev, Cannot set vddcx voltage\n); ret = regulator_disable(motg-vddcx); if (ret) dev_err(motg-phy.dev, unable to disable hsusb vddcx\n); @@ -97,8 +95,7 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) rc = regulator_set_voltage(motg-v3p3, USB_PHY_3P3_VOL_MIN, USB_PHY_3P3_VOL_MAX); if (rc) { - dev_err(motg-phy.dev, unable to set voltage level - for hsusb 3p3\n); + dev_err(motg-phy.dev, Cannot set v3p3 voltage\n); goto exit; } rc = regulator_enable(motg-v3p3); @@ -109,8 +106,7 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) rc = regulator_set_voltage(motg-v1p8, USB_PHY_1P8_VOL_MIN, USB_PHY_1P8_VOL_MAX); if (rc) { - dev_err(motg-phy.dev, unable to set voltage level - for hsusb 1p8\n); + dev_err(motg-phy.dev, Cannot set v1p8 voltage\n); goto disable_3p3; } rc = regulator_enable(motg-v1p8); @@ -144,8 +140,7 @@ static int msm_hsusb_config_vddcx(struct msm_otg *motg, int high) ret = regulator_set_voltage(motg-vddcx, min_vol, max_vol); if (ret) { - pr_err(%s: unable to set the voltage for regulator - HSUSB_VDDCX\n, __func__); + dev_err(motg-phy.dev, Cannot set vddcx voltage\n); return ret; } @@ -163,15 +158,13 @@ static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on) ret = regulator_set_optimum_mode(motg-v1p8, USB_PHY_1P8_HPM_LOAD); if (ret 0) { - pr_err(%s: Unable to set HPM of the regulator - HSUSB_1p8\n, __func__); + pr_err(Could not set HPM for v1p8\n); return ret; } ret = regulator_set_optimum_mode(motg-v3p3, USB_PHY_3P3_HPM_LOAD); if (ret 0) { - pr_err(%s: Unable to set HPM of the regulator - HSUSB_3p3\n, __func__); + pr_err(Could not set HPM for v3p3\n); regulator_set_optimum_mode(motg-v1p8, USB_PHY_1P8_LPM_LOAD); return ret; @@ -180,13 +173,11 @@ static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on) ret = regulator_set_optimum_mode(motg-v1p8, USB_PHY_1P8_LPM_LOAD); if (ret 0) - pr_err(%s: Unable to set LPM of the regulator - HSUSB_1p8\n, __func__); + pr_err(Could not set LPM for v1p8\n); ret = regulator_set_optimum_mode(motg-v3p3, USB_PHY_3P3_LPM_LOAD); if (ret 0) - pr_err(%s: Unable to set LPM of the regulator - HSUSB_3p3\n, __func__); + pr_err(Could not set LPM for v3p3\n); } pr_debug(reg (%s)\n, on ? HPM : LPM); @@ -547,8 +538,7 @@ static int msm_otg_resume(struct msm_otg *motg) * PHY. USB state can not be restored. Re-insertion
[PATCH v4 14/15] usb: phy: msm: Handle disconnect events
From: Ivan T. Ivanov iiva...@mm-sol.com Put the transceiver in non-driving mode. Otherwise host may not detect soft-disconnection. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Cc: Pavankumar Kondeti pkond...@codeaurora.org --- drivers/usb/phy/phy-msm-usb.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 1d88ff8..970f96b 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -260,6 +260,23 @@ static void ulpi_init(struct msm_otg *motg) } } +static int msm_phy_notify_disconnect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + int val; + + /* +* Put the transceiver in non-driving mode. Otherwise host +* may not detect soft-disconnection. +*/ + val = ulpi_read(phy, ULPI_FUNC_CTRL); + val = ~ULPI_FUNC_CTRL_OPMODE_MASK; + val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; + ulpi_write(phy, val, ULPI_FUNC_CTRL); + + return 0; +} + static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) { int ret; @@ -1597,6 +1614,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) phy-init = msm_phy_init; phy-set_power = msm_otg_set_power; + phy-notify_disconnect = msm_phy_notify_disconnect; phy-io_ops = msm_otg_io_ops; -- 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 v4 11/15] usb: phy: msm: Use reset framework for LINK and PHY resets
From: Ivan T. Ivanov iiva...@mm-sol.com Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Cc: devicet...@vger.kernel.org --- .../devicetree/bindings/usb/msm-hsusb.txt |9 ++ drivers/usb/phy/phy-msm-usb.c | 30 ++-- include/linux/usb/msm_hsusb.h |3 ++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt index f1045e3..3f21204 100644 --- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt @@ -57,6 +57,12 @@ Required properties: - v1p8-supply: phandle to the regulator for the 1.8V supply - v3p3-supply: phandle to the regulator for the 3.3V supply +- resets: A list of phandle + reset-specifier pairs for the + resets listed in reset-names +- reset-names: Should contain the following: + phyUSB PHY controller reset + link USB LINK controller reset + - qcom,otg-control: OTG control (VBUS and ID notifications) can be one of 1 - PHY control 2 - PMIC control @@ -83,6 +89,9 @@ Example HSUSB OTG controller device node: v1p8-supply = pm8941_l6; v3p3-supply = pm8941_l24; + resets = gcc GCC_USB2A_PHY_BCR, gcc GCC_USB_HS_BCR; + reset-names = phy, link; + qcom,otg-control = 1; qcom,phy-init-sequence = 0x01 0x90 0x; }; diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index cc230c8..53fc645 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -32,6 +32,7 @@ #include linux/pm_runtime.h #include linux/of.h #include linux/of_device.h +#include linux/reset.h #include linux/usb.h #include linux/usb/otg.h @@ -260,12 +261,16 @@ static void ulpi_init(struct msm_otg *motg) static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) { - int ret = 0; + int ret; - if (!motg-pdata-link_clk_reset) - return ret; + if (motg-pdata-link_clk_reset) + ret = motg-pdata-link_clk_reset(motg-clk, assert); + else + if (assert) + ret = reset_control_assert(motg-link_rst); + else + ret = reset_control_deassert(motg-link_rst); - ret = motg-pdata-link_clk_reset(motg-clk, assert); if (ret) dev_err(motg-phy.dev, usb link clk reset %s failed\n, assert ? assert : deassert); @@ -275,12 +280,13 @@ static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) static int msm_otg_phy_clk_reset(struct msm_otg *motg) { - int ret = 0; + int ret; - if (!motg-pdata-phy_clk_reset) - return ret; + if (motg-pdata-phy_clk_reset) + ret = motg-pdata-phy_clk_reset(motg-phy_reset_clk); + else + ret = reset_control_reset(motg-phy_rst); - ret = motg-pdata-phy_clk_reset(motg-phy_reset_clk); if (ret) dev_err(motg-phy.dev, usb phy clk reset failed\n); @@ -1373,6 +1379,14 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) id = of_match_device(msm_otg_dt_match, pdev-dev); pdata-phy_type = (int) id-data; + motg-link_rst = devm_reset_control_get(pdev-dev, link); + if (IS_ERR(motg-link_rst)) + return PTR_ERR(motg-link_rst); + + motg-phy_rst = devm_reset_control_get(pdev-dev, phy); + if (IS_ERR(motg-phy_rst)) + return PTR_ERR(motg-phy_rst); + pdata-mode = of_usb_get_dr_mode(node); if (pdata-mode == USB_DR_MODE_UNKNOWN) pdata-mode = USB_DR_MODE_OTG; diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 262ed80..9bf8943 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -163,6 +163,9 @@ struct msm_otg { struct regulator *v3p3; struct regulator *v1p8; struct regulator *vddcx; + + struct reset_control *phy_rst; + struct reset_control *link_rst; }; #endif -- 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 v4 02/15] usb: phy: msm: Move global regulators variables to driver state
From: Ivan T. Ivanov iiva...@mm-sol.com Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c | 82 - include/linux/usb/msm_hsusb.h |3 ++ 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 9a47d44..c22cbd8 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -58,47 +58,43 @@ #define USB_PHY_VDD_DIG_VOL_MIN100 /* uV */ #define USB_PHY_VDD_DIG_VOL_MAX132 /* uV */ -static struct regulator *hsusb_3p3; -static struct regulator *hsusb_1p8; -static struct regulator *hsusb_vddcx; - static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) { int ret = 0; if (init) { - hsusb_vddcx = regulator_get(motg-phy.dev, HSUSB_VDDCX); - if (IS_ERR(hsusb_vddcx)) { + motg-vddcx = regulator_get(motg-phy.dev, HSUSB_VDDCX); + if (IS_ERR(motg-vddcx)) { dev_err(motg-phy.dev, unable to get hsusb vddcx\n); - return PTR_ERR(hsusb_vddcx); + return PTR_ERR(motg-vddcx); } - ret = regulator_set_voltage(hsusb_vddcx, + ret = regulator_set_voltage(motg-vddcx, USB_PHY_VDD_DIG_VOL_MIN, USB_PHY_VDD_DIG_VOL_MAX); if (ret) { dev_err(motg-phy.dev, unable to set the voltage for hsusb vddcx\n); - regulator_put(hsusb_vddcx); + regulator_put(motg-vddcx); return ret; } - ret = regulator_enable(hsusb_vddcx); + ret = regulator_enable(motg-vddcx); if (ret) { dev_err(motg-phy.dev, unable to enable hsusb vddcx\n); - regulator_put(hsusb_vddcx); + regulator_put(motg-vddcx); } } else { - ret = regulator_set_voltage(hsusb_vddcx, 0, + ret = regulator_set_voltage(motg-vddcx, 0, USB_PHY_VDD_DIG_VOL_MAX); if (ret) dev_err(motg-phy.dev, unable to set the voltage for hsusb vddcx\n); - ret = regulator_disable(hsusb_vddcx); + ret = regulator_disable(motg-vddcx); if (ret) dev_err(motg-phy.dev, unable to disable hsusb vddcx\n); - regulator_put(hsusb_vddcx); + regulator_put(motg-vddcx); } return ret; @@ -109,38 +105,38 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) int rc = 0; if (init) { - hsusb_3p3 = regulator_get(motg-phy.dev, HSUSB_3p3); - if (IS_ERR(hsusb_3p3)) { + motg-v3p3 = regulator_get(motg-phy.dev, HSUSB_3p3); + if (IS_ERR(motg-v3p3)) { dev_err(motg-phy.dev, unable to get hsusb 3p3\n); - return PTR_ERR(hsusb_3p3); + return PTR_ERR(motg-v3p3); } - rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN, + rc = regulator_set_voltage(motg-v3p3, USB_PHY_3P3_VOL_MIN, USB_PHY_3P3_VOL_MAX); if (rc) { dev_err(motg-phy.dev, unable to set voltage level for hsusb 3p3\n); goto put_3p3; } - rc = regulator_enable(hsusb_3p3); + rc = regulator_enable(motg-v3p3); if (rc) { dev_err(motg-phy.dev, unable to enable the hsusb 3p3\n); goto put_3p3; } - hsusb_1p8 = regulator_get(motg-phy.dev, HSUSB_1p8); - if (IS_ERR(hsusb_1p8)) { + motg-v1p8 = regulator_get(motg-phy.dev, HSUSB_1p8); + if (IS_ERR(motg-v1p8)) { dev_err(motg-phy.dev, unable to get hsusb 1p8\n); - rc = PTR_ERR(hsusb_1p8); + rc = PTR_ERR(motg-v1p8); goto disable_3p3; } - rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN, + rc = regulator_set_voltage(motg-v1p8, USB_PHY_1P8_VOL_MIN, USB_PHY_1P8_VOL_MAX); if (rc) { dev_err(motg-phy.dev, unable to set voltage level for hsusb 1p8\n); goto put_1p8; } - rc = regulator_enable(hsusb_1p8); + rc = regulator_enable(motg-v1p8);
[PATCH v4 00/15] usb: phy: msm: Fixes, cleanups and DT support
From: Ivan T. Ivanov iiva...@mm-sol.com Hi, Patches have been tested on top of Stephen's clock controller patches[1] and recent fixes for chipidea msm glue layer driver posted here[2]. Hardware platform AP8074 DragonBoard. Only gadget mode utilized for now. CV Test Suite engine Chapter 9 tests are passing except Halt Endpoint Test. usbtest driver report following failure: test 13 -- 32 (Broken pipe)ep 81 couldn't set halt, -32 This will be investigated further. Patches could be applied cleanly on top of the usb-3.13-rc1. Regards, Ivan [1] http://comments.gmane.org/gmane.linux.ports.arm.msm/5375 [2] https://lkml.org/lkml/2013/11/11/310 v4 -- * Squashed checkpatch.pl warning fixes patches * Squashed dr_mode refactoring with default mode removal * Dropped patch 10 - usb: phy: msm: Switch clock consumer strings * Fixed comments from review. * Utilize reset-framework for LINK and PHY resets if DT is used. * Added support from second PHY device control. * Ported reset procedure from codeaurora tree for new chipsets v3 -- * In patch 1 - functions for reseting PHY and LINK controller just call platform code if available. * New stuff is: cleaning up unneeded/unused driver state variables * Simplified regulator names. There is no references to these names in tree, so there should not be a problem with this. * Replace the USB specific clock names with the more standard 'core' and 'iface' ... names. * Added devicetree support v2 -- * Fix compilation issue in patch 1 * Separate regulator changes * Merge devm_ related changes to one commit * Drop Lindent patch v1 -- Following patches make initial cleanup of usb phy found in the Qualcomm chipsets. Changes include: * Build time error fix. * Move driver to Managed Device Resource allocation. * Checkpatch warnings and error fixes * Removed usage of global regulators variables. Ivan T. Ivanov (15): usb: phy: msm: Move mach dependent code to platform data usb: phy: msm: Move global regulators variables to driver state usb: phy: msm: Migrate to Managed Device Resource allocation usb: phy: msm: Remove unnecessarily check for valid regulators. usb: phy: msm: Fix checkpatch.pl warnings usb: phy: msm: Replace custom enum usb_mode_type with enum usb_dr_mode usb: phy: msm: Remove unused pclk_src_name usb: phy: msm: Remove HSUSB prefix from regulator names usb: phy: msm: Properly check result from platform_get_irq() usb: phy: msm: Add device tree support and binding information usb: phy: msm: Use reset framework for LINK and PHY resets usb: phy: msm: Add support for secondary PHY control usb: phy: msm: Correct USB PHY Reset sequence for newer platform usb: phy: msm: Handle disconnect events usb: phy: msm: Vote for corner of VDD CX instead of voltage of VDD CX .../devicetree/bindings/usb/msm-hsusb.txt | 78 ++- arch/arm/mach-msm/board-msm7x30.c | 37 +- arch/arm/mach-msm/board-qsd8x50.c | 37 +- drivers/usb/phy/phy-msm-usb.c | 664 +++- include/linux/usb/msm_hsusb.h | 36 +- include/linux/usb/msm_hsusb_hw.h |6 + 6 files changed, 529 insertions(+), 329 deletions(-) -- 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 v4 08/15] usb: phy: msm: Remove HSUSB prefix from regulator names
From: Ivan T. Ivanov iiva...@mm-sol.com Prefix did not bring any useful information. Currently none of the MSM platforms define these regulators, so it is safe to rename them. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c |6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 9e9d4a3..258bca2 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1417,19 +1417,19 @@ static int __init msm_otg_probe(struct platform_device *pdev) return motg-irq; } - motg-vddcx = devm_regulator_get(motg-phy.dev, HSUSB_VDDCX); + motg-vddcx = devm_regulator_get(motg-phy.dev, vddcx); if (IS_ERR(motg-vddcx)) { dev_err(motg-phy.dev, unable to get hsusb vddcx\n); return PTR_ERR(motg-vddcx); } - motg-v3p3 = devm_regulator_get(motg-phy.dev, HSUSB_3p3); + motg-v3p3 = devm_regulator_get(motg-phy.dev, v3p3); if (IS_ERR(motg-v3p3)) { dev_err(motg-phy.dev, unable to get hsusb 3p3\n); return PTR_ERR(motg-v3p3); } - motg-v1p8 = devm_regulator_get(motg-phy.dev, HSUSB_1p8); + motg-v1p8 = devm_regulator_get(motg-phy.dev, v1p8); if (IS_ERR(motg-v1p8)) { dev_err(motg-phy.dev, unable to get hsusb 1p8\n); return PTR_ERR(motg-v1p8); -- 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 v4 04/15] usb: phy: msm: Remove unnecessarily check for valid regulators.
From: Ivan T. Ivanov iiva...@mm-sol.com Whether regulators are available or not is checked at driver probe. If they are not available driver will refuse to load, so no need to check them again. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c | 10 -- 1 file changed, 10 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index dac2b22..0bd9614 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -159,16 +159,6 @@ static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on) { int ret = 0; - if (!motg-v1p8 || IS_ERR(motg-v1p8)) { - pr_err(%s: HSUSB_1p8 is not initialized\n, __func__); - return -ENODEV; - } - - if (!motg-v3p3 || IS_ERR(motg-v3p3)) { - pr_err(%s: HSUSB_3p3 is not initialized\n, __func__); - return -ENODEV; - } - if (on) { ret = regulator_set_optimum_mode(motg-v1p8, USB_PHY_1P8_HPM_LOAD); -- 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 v4 10/15] usb: phy: msm: Add device tree support and binding information
From: Ivan T. Ivanov iiva...@mm-sol.com Allows MSM OTG controller to be specified via device tree. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Cc: devicet...@vger.kernel.org --- .../devicetree/bindings/usb/msm-hsusb.txt | 57 +- drivers/usb/phy/phy-msm-usb.c | 79 +--- 2 files changed, 124 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt index 0a85eba..f1045e3 100644 --- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt @@ -30,4 +30,59 @@ Required properties: dr_mode = peripheral; interrupts = 0 134 0; usb-phy = usb_otg; - }; \ No newline at end of file + }; + +USB PHY with optional OTG: + +Required properties: +- compatible: should contain qcom,usb-otg-ci for chipsets with + Chipidea 45nm PHY or qcom,usb-otg-snps for chipsets + with Synopsys 28nm PHY +- regs:offset and length of the register set in the memory map +- interrupts: interrupt-specifier for the OTG interrupt. + +- clocks: A list of phandle + clock-specifier pairs for the + clocks listed in clock-names +- clock-names: Should contain the following: + phyUSB PHY reference clock + core Protocol engine clock + iface Interface bus clock + alt_core Optional: Protocol engine clock for targets with asynchronous + reset methodology. + +- dr_mode: One of host, peripheral or otg. Defaults to otg + +- vdccx-supply:phandle to the regulator for the vdd supply for + digital circuit operation. +- v1p8-supply: phandle to the regulator for the 1.8V supply +- v3p3-supply: phandle to the regulator for the 3.3V supply + +- qcom,otg-control: OTG control (VBUS and ID notifications) can be one of + 1 - PHY control + 2 - PMIC control + 3 - User control (via debugfs) + +Optional properties: +- qcom,phy-init-sequence: PHY configuration sequence. val, reg pairs + terminate with -1 + +Example HSUSB OTG controller device node: + + usb@f9a55000 { + compatible = qcom,usb-otg-snps; + reg = 0xf9a55000 0x400; + interrupts = 0 134 0;; + dr_mode = peripheral; + + clocks = gcc GCC_XO_CLK, gcc GCC_USB_HS_SYSTEM_CLK, + gcc GCC_USB_HS_AHB_CLK; + + clock-names = phy, core, iface; + + vddcx-supply = pm8841_s2_corner; + v1p8-supply = pm8941_l6; + v3p3-supply = pm8941_l24; + + qcom,otg-control = 1; + qcom,phy-init-sequence = 0x01 0x90 0x; + }; diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index fa8e672d..cc230c8 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -30,9 +30,12 @@ #include linux/debugfs.h #include linux/seq_file.h #include linux/pm_runtime.h +#include linux/of.h +#include linux/of_device.h #include linux/usb.h #include linux/usb/otg.h +#include linux/usb/of.h #include linux/usb/ulpi.h #include linux/usb/gadget.h #include linux/usb/hcd.h @@ -1343,25 +1346,75 @@ static void msm_otg_debugfs_cleanup(void) debugfs_remove(msm_otg_dbg_root); } +static struct of_device_id msm_otg_dt_match[] = { + { + .compatible = qcom,usb-otg-ci, + .data = (void *) CI_45NM_INTEGRATED_PHY + }, { + .compatible = qcom,usb-otg-snps, + .data = (void *) SNPS_28NM_INTEGRATED_PHY + }, {} +}; + +static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) +{ + struct msm_otg_platform_data *pdata; + const struct of_device_id *id; + struct device_node *node = pdev-dev.of_node; + int len = 0; + u32 val; + + pdata = devm_kzalloc(pdev-dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + motg-pdata = pdata; + + id = of_match_device(msm_otg_dt_match, pdev-dev); + pdata-phy_type = (int) id-data; + + pdata-mode = of_usb_get_dr_mode(node); + if (pdata-mode == USB_DR_MODE_UNKNOWN) + pdata-mode = USB_DR_MODE_OTG; + + pdata-otg_control = OTG_PHY_CONTROL; + if (!of_property_read_u32(node, qcom,otg-control, val)) + pdata-otg_control = val; + + if (!of_get_property(node, qcom,phy-init-sequence, len) || !len) + return 0; + + pdata-phy_init_seq = devm_kzalloc(pdev-dev, len, GFP_KERNEL); + if (!pdata-phy_init_seq)
[PATCH v4 06/15] usb: phy: msm: Replace custom enum usb_mode_type with enum usb_dr_mode
From: Ivan T. Ivanov iiva...@mm-sol.com Use enum usb_dr_mode and drop default usb_dr_mode from platform data. USB DT bindings states: dr_mode: ...In case this attribute isn't passed via DT, USB DRD controllers should default to OTG..., so remove redundand field. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- arch/arm/mach-msm/board-msm7x30.c |2 +- arch/arm/mach-msm/board-qsd8x50.c |2 +- drivers/usb/phy/phy-msm-usb.c | 41 +++-- include/linux/usb/msm_hsusb.h | 20 +- 4 files changed, 20 insertions(+), 45 deletions(-) diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index 46de789..0c4c200 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -95,7 +95,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk) static struct msm_otg_platform_data msm_otg_pdata = { .phy_init_seq = hsusb_phy_init_seq, - .mode = USB_PERIPHERAL, + .mode = USB_DR_MODE_PERIPHERAL, .otg_control= OTG_PHY_CONTROL, .link_clk_reset = hsusb_link_clk_reset, .phy_clk_reset = hsusb_phy_clk_reset, diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 9169ec3..4c74861 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -116,7 +116,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk) static struct msm_otg_platform_data msm_otg_pdata = { .phy_init_seq = hsusb_phy_init_seq, - .mode = USB_PERIPHERAL, + .mode = USB_DR_MODE_PERIPHERAL, .otg_control= OTG_PHY_CONTROL, .link_clk_reset = hsusb_link_clk_reset, .phy_clk_reset = hsusb_phy_clk_reset, diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 8f148a6..00ee7b3 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -373,10 +373,10 @@ static int msm_otg_reset(struct usb_phy *phy) if (pdata-otg_control == OTG_PHY_CONTROL) { val = readl(USB_OTGSC); - if (pdata-mode == USB_OTG) { + if (pdata-mode == USB_DR_MODE_OTG) { ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; val |= OTGSC_IDIE | OTGSC_BSVIE; - } else if (pdata-mode == USB_PERIPHERAL) { + } else if (pdata-mode == USB_DR_MODE_PERIPHERAL) { ulpi_val = ULPI_INT_SESS_VALID; val |= OTGSC_BSVIE; } @@ -637,7 +637,7 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) * Fail host registration if this board can support * only peripheral configuration. */ - if (motg-pdata-mode == USB_PERIPHERAL) { + if (motg-pdata-mode == USB_DR_MODE_PERIPHERAL) { dev_info(otg-phy-dev, Host mode is not supported\n); return -ENODEV; } @@ -666,7 +666,7 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) * Kick the state machine work, if peripheral is not supported * or peripheral is already registered with us. */ - if (motg-pdata-mode == USB_HOST || otg-gadget) { + if (motg-pdata-mode == USB_DR_MODE_HOST || otg-gadget) { pm_runtime_get_sync(otg-phy-dev); schedule_work(motg-sm_work); } @@ -710,7 +710,7 @@ static int msm_otg_set_peripheral(struct usb_otg *otg, * Fail peripheral registration if this board can support * only host configuration. */ - if (motg-pdata-mode == USB_HOST) { + if (motg-pdata-mode == USB_DR_MODE_HOST) { dev_info(otg-phy-dev, Peripheral mode is not supported\n); return -ENODEV; } @@ -735,7 +735,7 @@ static int msm_otg_set_peripheral(struct usb_otg *otg, * Kick the state machine work, if host is not supported * or host is already registered with us. */ - if (motg-pdata-mode == USB_PERIPHERAL || otg-host) { + if (motg-pdata-mode == USB_DR_MODE_PERIPHERAL || otg-host) { pm_runtime_get_sync(otg-phy-dev); schedule_work(motg-sm_work); } @@ -1056,7 +1056,7 @@ static void msm_otg_init_sm(struct msm_otg *motg) u32 otgsc = readl(USB_OTGSC); switch (pdata-mode) { - case USB_OTG: + case USB_DR_MODE_OTG: if (pdata-otg_control == OTG_PHY_CONTROL) { if (otgsc OTGSC_ID) set_bit(ID, motg-inputs); @@ -1068,21 +1068,14 @@ static void msm_otg_init_sm(struct msm_otg *motg) else clear_bit(B_SESS_VLD, motg-inputs); } else if (pdata-otg_control
[PATCH v4 03/15] usb: phy: msm: Migrate to Managed Device Resource allocation
From: Ivan T. Ivanov iiva...@mm-sol.com Move memory, regulators, clocks and irq allocation to devm_* variants. Properly check for valid clk handles. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c | 192 - 1 file changed, 74 insertions(+), 118 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index c22cbd8..dac2b22 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -63,27 +63,18 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) int ret = 0; if (init) { - motg-vddcx = regulator_get(motg-phy.dev, HSUSB_VDDCX); - if (IS_ERR(motg-vddcx)) { - dev_err(motg-phy.dev, unable to get hsusb vddcx\n); - return PTR_ERR(motg-vddcx); - } - ret = regulator_set_voltage(motg-vddcx, USB_PHY_VDD_DIG_VOL_MIN, USB_PHY_VDD_DIG_VOL_MAX); if (ret) { dev_err(motg-phy.dev, unable to set the voltage for hsusb vddcx\n); - regulator_put(motg-vddcx); return ret; } ret = regulator_enable(motg-vddcx); - if (ret) { + if (ret) dev_err(motg-phy.dev, unable to enable hsusb vddcx\n); - regulator_put(motg-vddcx); - } } else { ret = regulator_set_voltage(motg-vddcx, 0, USB_PHY_VDD_DIG_VOL_MAX); @@ -93,8 +84,6 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) ret = regulator_disable(motg-vddcx); if (ret) dev_err(motg-phy.dev, unable to disable hsusb vddcx\n); - - regulator_put(motg-vddcx); } return ret; @@ -105,53 +94,38 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) int rc = 0; if (init) { - motg-v3p3 = regulator_get(motg-phy.dev, HSUSB_3p3); - if (IS_ERR(motg-v3p3)) { - dev_err(motg-phy.dev, unable to get hsusb 3p3\n); - return PTR_ERR(motg-v3p3); - } - rc = regulator_set_voltage(motg-v3p3, USB_PHY_3P3_VOL_MIN, USB_PHY_3P3_VOL_MAX); if (rc) { dev_err(motg-phy.dev, unable to set voltage level for hsusb 3p3\n); - goto put_3p3; + goto exit; } rc = regulator_enable(motg-v3p3); if (rc) { dev_err(motg-phy.dev, unable to enable the hsusb 3p3\n); - goto put_3p3; - } - motg-v1p8 = regulator_get(motg-phy.dev, HSUSB_1p8); - if (IS_ERR(motg-v1p8)) { - dev_err(motg-phy.dev, unable to get hsusb 1p8\n); - rc = PTR_ERR(motg-v1p8); - goto disable_3p3; + goto exit; } rc = regulator_set_voltage(motg-v1p8, USB_PHY_1P8_VOL_MIN, USB_PHY_1P8_VOL_MAX); if (rc) { dev_err(motg-phy.dev, unable to set voltage level for hsusb 1p8\n); - goto put_1p8; + goto disable_3p3; } rc = regulator_enable(motg-v1p8); if (rc) { dev_err(motg-phy.dev, unable to enable the hsusb 1p8\n); - goto put_1p8; + goto disable_3p3; } return 0; } regulator_disable(motg-v1p8); -put_1p8: - regulator_put(motg-v1p8); disable_3p3: regulator_disable(motg-v3p3); -put_3p3: - regulator_put(motg-v3p3); +exit: return rc; } @@ -507,7 +481,7 @@ static int msm_otg_suspend(struct msm_otg *motg) clk_disable_unprepare(motg-pclk); clk_disable_unprepare(motg-clk); - if (motg-core_clk) + if (!IS_ERR(motg-core_clk)) clk_disable_unprepare(motg-core_clk); if (!IS_ERR(motg-pclk_src)) @@ -547,7 +521,7 @@ static int msm_otg_resume(struct msm_otg *motg) clk_prepare_enable(motg-pclk); clk_prepare_enable(motg-clk); - if (motg-core_clk) + if (!IS_ERR(motg-core_clk)) clk_prepare_enable(motg-core_clk); if (motg-pdata-phy_type == SNPS_28NM_INTEGRATED_PHY @@ -1415,13 +1389,14 @@ static int __init msm_otg_probe(struct platform_device *pdev) return -ENODEV; } -
[PATCH v4 07/15] usb: phy: msm: Remove unused pclk_src_name
From: Ivan T. Ivanov iiva...@mm-sol.com There are no references to 'pclk_src_name' in plaform code, so it is unused. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com --- drivers/usb/phy/phy-msm-usb.c | 26 +- include/linux/usb/msm_hsusb.h |5 - 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 00ee7b3..9e9d4a3 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -465,9 +465,6 @@ static int msm_otg_suspend(struct msm_otg *motg) if (!IS_ERR(motg-core_clk)) clk_disable_unprepare(motg-core_clk); - if (!IS_ERR(motg-pclk_src)) - clk_disable_unprepare(motg-pclk_src); - if (motg-pdata-phy_type == SNPS_28NM_INTEGRATED_PHY motg-pdata-otg_control == OTG_PMIC_CONTROL) { msm_hsusb_ldo_set_mode(motg, 0); @@ -497,9 +494,6 @@ static int msm_otg_resume(struct msm_otg *motg) if (!atomic_read(motg-in_lpm)) return 0; - if (!IS_ERR(motg-pclk_src)) - clk_prepare_enable(motg-pclk_src); - clk_prepare_enable(motg-pclk); clk_prepare_enable(motg-clk); if (!IS_ERR(motg-core_clk)) @@ -1395,17 +1389,8 @@ static int __init msm_otg_probe(struct platform_device *pdev) * If USB Core is running its protocol engine based on CORE CLK, * CORE CLK must be running at 55Mhz for correct HSUSB * operation and USB core cannot tolerate frequency changes on -* CORE CLK. For such USB cores, vote for maximum clk frequency -* on pclk source +* CORE CLK. */ -motg-pclk_src = ERR_PTR(-ENOENT); -if (motg-pdata-pclk_src_name) { - motg-pclk_src = devm_clk_get(pdev-dev, - motg-pdata-pclk_src_name); - if (IS_ERR(motg-pclk_src)) - return PTR_ERR(motg-pclk_src); - } - motg-pclk = devm_clk_get(pdev-dev, usb_hs_pclk); if (IS_ERR(motg-pclk)) { dev_err(pdev-dev, failed to get usb_hs_pclk\n); @@ -1451,10 +1436,6 @@ static int __init msm_otg_probe(struct platform_device *pdev) } clk_set_rate(motg-clk, 6000); - if (!IS_ERR(motg-pclk_src)) { - clk_set_rate(motg-pclk_src, INT_MAX); - clk_prepare_enable(motg-pclk_src); - } clk_prepare_enable(motg-clk); clk_prepare_enable(motg-pclk); @@ -1530,8 +1511,6 @@ disable_clks: clk_disable_unprepare(motg-clk); if (!IS_ERR(motg-core_clk)) clk_disable_unprepare(motg-core_clk); - if (!IS_ERR(motg-pclk_src)) - clk_disable_unprepare(motg-pclk_src); return ret; } @@ -1576,9 +1555,6 @@ static int msm_otg_remove(struct platform_device *pdev) clk_disable_unprepare(motg-clk); if (!IS_ERR(motg-core_clk)) clk_disable_unprepare(motg-core_clk); - if (!IS_ERR(motg-pclk_src)) - clk_disable_unprepare(motg-pclk_src); - msm_hsusb_ldo_init(motg, 0); pm_runtime_set_suspended(pdev-dev); diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 72c5830..262ed80 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -106,8 +106,6 @@ enum usb_chg_type { * @power_budget: VBUS power budget in mA (0 will be treated as 500mA). * @mode: Supported mode (OTG/peripheral/host). * @otg_control: OTG switch controlled by user/Id pin - * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k - * dfab_usb_hs_clk in case of 8660 and 8960. */ struct msm_otg_platform_data { int *phy_init_seq; @@ -117,7 +115,6 @@ struct msm_otg_platform_data { enum otg_control_type otg_control; enum msm_usb_phy_type phy_type; void (*setup_gpio)(enum usb_otg_state state); - char *pclk_src_name; int (*link_clk_reset)(struct clk *link_clk, bool assert); int (*phy_clk_reset)(struct clk *phy_clk); }; @@ -129,7 +126,6 @@ struct msm_otg_platform_data { * @irq: IRQ number assigned for HSUSB controller. * @clk: clock struct of usb_hs_clk. * @pclk: clock struct of usb_hs_pclk. - * @pclk_src: pclk source for voting. * @phy_reset_clk: clock struct of usb_phy_clk. * @core_clk: clock struct of usb_hs_core_clk. * @regs: ioremapped register base address. @@ -150,7 +146,6 @@ struct msm_otg { int irq; struct clk *clk; struct clk *pclk; - struct clk *pclk_src; struct clk *phy_reset_clk; struct clk *core_clk; void __iomem *regs; -- 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] usb: phy: generic: re-factor the way we find out about our resources
instead of having each user of generic phy find out about its own resources and pass it to the core layer, have th core layer itself figure that out. It's as simple as moving a piece of code around. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/phy/phy-am335x.c | 3 +-- drivers/usb/phy/phy-generic.c | 61 +-- drivers/usb/phy/phy-generic.h | 4 ++- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 48d41ab..0e3c60c 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev) return am_phy-id; } - ret = usb_phy_gen_create_phy(dev, am_phy-usb_phy_gen, - USB_PHY_TYPE_USB2, 0, false); + ret = usb_phy_gen_create_phy(dev, am_phy-usb_phy_gen, NULL); if (ret) return ret; diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index db4fc22..0c3b241 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -150,10 +150,38 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) } int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, - enum usb_phy_type type, u32 clk_rate, bool needs_vcc) + struct usb_phy_gen_xceiv_platform_data *pdata) { + enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; + u32 clk_rate = 0; + bool needs_vcc = false; + + nop-reset_active_low = true; /* default behaviour */ + + if (dev-of_node) { + struct device_node *node = dev-of_node; + enum of_gpio_flags flags; + + if (of_property_read_u32(node, clock-frequency, clk_rate)) + clk_rate = 0; + + needs_vcc = of_property_read_bool(node, vcc-supply); + nop-gpio_reset = of_get_named_gpio_flags(node, reset-gpios, + 0, flags); + if (nop-gpio_reset == -EPROBE_DEFER) + return -EPROBE_DEFER; + + nop-reset_active_low = flags OF_GPIO_ACTIVE_LOW; + + } else if (pdata) { + type = pdata-type; + clk_rate = pdata-clk_rate; + needs_vcc = pdata-needs_vcc; + nop-gpio_reset = pdata-gpio_reset; + } + nop-phy.otg = devm_kzalloc(dev, sizeof(*nop-phy.otg), GFP_KERNEL); if (!nop-phy.otg) @@ -218,43 +246,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) { struct device *dev = pdev-dev; - struct usb_phy_gen_xceiv_platform_data *pdata = - dev_get_platdata(pdev-dev); struct usb_phy_gen_xceiv*nop; - enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; - u32 clk_rate = 0; - bool needs_vcc = false; nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL); if (!nop) return -ENOMEM; - nop-reset_active_low = true; /* default behaviour */ - - if (dev-of_node) { - struct device_node *node = dev-of_node; - enum of_gpio_flags flags; - - if (of_property_read_u32(node, clock-frequency, clk_rate)) - clk_rate = 0; - - needs_vcc = of_property_read_bool(node, vcc-supply); - nop-gpio_reset = of_get_named_gpio_flags(node, reset-gpios, - 0, flags); - if (nop-gpio_reset == -EPROBE_DEFER) - return -EPROBE_DEFER; - - nop-reset_active_low = flags OF_GPIO_ACTIVE_LOW; - - } else if (pdata) { - type = pdata-type; - clk_rate = pdata-clk_rate; - needs_vcc = pdata-needs_vcc; - nop-gpio_reset = pdata-gpio_reset; - } - - err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc); + err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(pdev-dev)); if (err) return err; diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h index d2a220d..38a81f3 100644 --- a/drivers/usb/phy/phy-generic.h +++ b/drivers/usb/phy/phy-generic.h @@ -1,6 +1,8 @@ #ifndef _PHY_GENERIC_H_ #define _PHY_GENERIC_H_ +#include linux/usb/usb_phy_gen_xceiv.h + struct usb_phy_gen_xceiv { struct usb_phy phy; struct device *dev; @@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy); void usb_gen_phy_shutdown(struct usb_phy *phy); int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, - enum usb_phy_type type, u32 clk_rate, bool needs_vcc); + struct
Re: [PATCH] usb: phy: remove dead code
On Sun, Nov 10, 2013 at 07:37:37PM +0100, Michal Nazarewicz wrote: From: Michal Nazarewicz min...@mina86.com no SoB, cannot apply. I already had this patch in my tree but didn't send it. I'm fine with using yours but I need SoB and commit log. -- balbi signature.asc Description: Digital signature
[PATCH 1/2] usb: musb: musb_cppi41: factor most of cppi41_dma_callback() into cppi41_trans_done()
This patch moves most of the logic in cppi41_dma_callback() into cppi41_trans_done() where it can be called from another function. Instead of computing transferred (the number of bytes transferred in the last transaction) in cppi41_trans_done() the member cppi41_channel-prog_len is now set to 0 if the transfer as a whole can be considered as done. If it is != 0 then the next iteration is assumed. This is a preparation for a workaround. Cc: sta...@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de --- drivers/usb/musb/musb_cppi41.c | 59 ++ 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index ff9d6de..83a8a1d 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -96,31 +96,15 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel) cppi41_channel-usb_toggle = toggle; } -static void cppi41_dma_callback(void *private_data) +static void cppi41_dma_callback(void *private_data); + +static void cppi41_trans_done(struct dma_channel *channel) { - struct dma_channel *channel = private_data; struct cppi41_dma_channel *cppi41_channel = channel-private_data; struct musb_hw_ep *hw_ep = cppi41_channel-hw_ep; struct musb *musb = hw_ep-musb; - unsigned long flags; - struct dma_tx_state txstate; - u32 transferred; - spin_lock_irqsave(musb-lock, flags); - - dmaengine_tx_status(cppi41_channel-dc, cppi41_channel-cookie, - txstate); - transferred = cppi41_channel-prog_len - txstate.residue; - cppi41_channel-transferred += transferred; - - dev_dbg(musb-controller, DMA transfer done on hw_ep=%d bytes=%d/%d\n, - hw_ep-epnum, cppi41_channel-transferred, - cppi41_channel-total_len); - - update_rx_toggle(cppi41_channel); - - if (cppi41_channel-transferred == cppi41_channel-total_len || - transferred cppi41_channel-packet_sz) { + if (!cppi41_channel-prog_len) { /* done, complete */ cppi41_channel-channel.actual_len = @@ -150,10 +134,8 @@ static void cppi41_dma_callback(void *private_data) remain_bytes, direction, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (WARN_ON(!dma_desc)) { - spin_unlock_irqrestore(musb-lock, flags); + if (WARN_ON(!dma_desc)) return; - } dma_desc-callback = cppi41_dma_callback; dma_desc-callback_param = channel; @@ -166,6 +148,37 @@ static void cppi41_dma_callback(void *private_data) musb_writew(epio, MUSB_RXCSR, csr); } } +} + +static void cppi41_dma_callback(void *private_data) +{ + struct dma_channel *channel = private_data; + struct cppi41_dma_channel *cppi41_channel = channel-private_data; + struct musb_hw_ep *hw_ep = cppi41_channel-hw_ep; + struct musb *musb = hw_ep-musb; + unsigned long flags; + struct dma_tx_state txstate; + u32 transferred; + + spin_lock_irqsave(musb-lock, flags); + + dmaengine_tx_status(cppi41_channel-dc, cppi41_channel-cookie, + txstate); + transferred = cppi41_channel-prog_len - txstate.residue; + cppi41_channel-transferred += transferred; + + dev_dbg(musb-controller, DMA transfer done on hw_ep=%d bytes=%d/%d\n, + hw_ep-epnum, cppi41_channel-transferred, + cppi41_channel-total_len); + + update_rx_toggle(cppi41_channel); + + if (cppi41_channel-transferred == cppi41_channel-total_len || + transferred cppi41_channel-packet_sz) + cppi41_channel-prog_len = 0; + + cppi41_trans_done(channel); + spin_unlock_irqrestore(musb-lock, flags); } -- 1.8.4.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
[PATCH 2/2] usb: musb: musb_cppi41: handle pre-mature TX complete interrupt
The TX-complete interrupt of the CPPI41 on AM335x fires too early. Adding a loop and counting how long it takes until the MUSB_TXCSR_TXPKTRDY bit is cleared I see FS: |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadc54002, len=1514 is_tx=1 |cppi41_dma_callback() 74 loops |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadcd8802, len=1514 is_tx=1 |cppi41_dma_callback() 66 loops |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadcd8002, len=1514 is_tx=1 |cppi41_dma_callback() 136 loops |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadf55802, len=1514 is_tx=1 |cppi41_dma_callback() 136 loops avg: 110 - 150us HS: |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=512, mode=0, dma_addr=0xaca6f002, len=1514 is_tx=1 |cppi41_dma_callback() 0 loops |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=512, mode=0, dma_addr=0xadd6f802, len=1514 is_tx=1 |cppi41_dma_callback() 2 loops |musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=512, mode=0, dma_addr=0xadd6f002, len=1514 is_tx=1 |cppi41_dma_callback() 13 loops avg: 2us for the same test case. One loop means a udelay(1). The delay seems to depend on the packet size. On HS the bit is always cleared for small packet sizes while on FS it is never the case, it mostly around 110us. This testing has been performed with g_ether (musb as device) and using BULK transfers. INTR transfers are way more fun: during init the gadget sends a INT packet to the host and cppi41 says transfer done shortly after. The MUSB_TXCSR_TXPKTRDY bit is set even seconds later. The reason is that the host did not try to receive it, it does so after the interface (on host side) has been configured. Until this happens, that packet remains in musb's FIFO. To fix this, two things are done: - No DMA transfers for INT based endpoints. These transfer are usually very small and rare so it is likely better to skip the DMA engine and stuff the four bytes directly into the FIFO - on HS we poll up to 25us and hope that bit goes away. If not we setup a hrtimer to poll for it. The 140us delay is a rule of thumb. In FS the command | ping 10.10.10.10 -c1 -s65130 creates about 44 1514bytes transfers. About 19 of them need a second timer to complete. Reported-by: Bin Liu b-...@ti.com Cc: sta...@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de --- drivers/usb/musb/musb_cppi41.c | 113 +++-- 1 file changed, 108 insertions(+), 5 deletions(-) diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index 83a8a1d..a12bd30 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -38,6 +38,7 @@ struct cppi41_dma_channel { u32 prog_len; u32 transferred; u32 packet_sz; + struct list_head tx_check; }; #define MUSB_DMA_NUM_CHANNELS 15 @@ -47,6 +48,8 @@ struct cppi41_dma_controller { struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS]; struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS]; struct musb *musb; + struct hrtimer early_tx; + struct list_head early_tx_list; u32 rx_mode; u32 tx_mode; u32 auto_req; @@ -96,11 +99,23 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel) cppi41_channel-usb_toggle = toggle; } +static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep) +{ + u8 epnum = hw_ep-epnum; + struct musb *musb = hw_ep-musb; + void __iomem*epio = musb-endpoints[epnum].regs; + u16 csr; + + csr = musb_readw(epio, MUSB_TXCSR); + if (csr MUSB_TXCSR_TXPKTRDY) + return false; + return true; +} + static void cppi41_dma_callback(void *private_data); -static void cppi41_trans_done(struct dma_channel *channel) +static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) { - struct cppi41_dma_channel *cppi41_channel = channel-private_data; struct musb_hw_ep *hw_ep = cppi41_channel-hw_ep; struct musb *musb = hw_ep-musb; @@ -138,7 +153,7 @@ static void cppi41_trans_done(struct dma_channel *channel) return; dma_desc-callback = cppi41_dma_callback; - dma_desc-callback_param = channel; + dma_desc-callback_param = cppi41_channel-channel; cppi41_channel-cookie = dma_desc-tx_submit(dma_desc); dma_async_issue_pending(dc); @@ -150,6 +165,41 @@ static void cppi41_trans_done(struct dma_channel *channel) } } +static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) +{ + struct cppi41_dma_controller *controller; + struct cppi41_dma_channel *cppi41_channel, *n; + struct musb *musb; + unsigned long flags; + enum hrtimer_restart ret =
Re: [PATCHv2 2/2] check quirk to pad epout buf size when not aligned to maxpacketsize
On Mon, 11 Nov 2013, David Cohen wrote: Hi Alan, Michal, On 11/11/2013 01:09 PM, Michal Nazarewicz wrote: On Mon, Nov 11 2013, Alan Stern wrote: On Mon, 11 Nov 2013, Michal Nazarewicz wrote: Check gadget.quirk_ep_out_aligned_size to decide if buffer size requires to be aligned to maxpacketsize of an out endpoint. ffs_epfile_io() needs to pad epout buffer to match above condition if quirk is found. Signed-off-by: Michal Nazarewicz min...@mina86.com I think this is still wrong. @@ -824,7 +832,7 @@ static ssize_t ffs_epfile_io(struct file *file, req-context = done; req-complete = ffs_epfile_io_complete; req-buf = data; - req-length = len; + req-length = data_len; IIUC, req-length should still be set to len, not to data_len. I misunderstood the first time I read it: In order to avoid DWC3 to stall, we need to update req-length (this is the most important fix). kmalloc() is updated too to prevent USB controller to overflow buffer boundaries. Here I disagree. If the DWC3 hardware stalls, it is up to the DWC3 UDC driver to fix it. Gadget drivers should not have to worry. Most especially, gadget drivers should not lie about a request length. If the UDC driver decides to round up req-length before sending it to the hardware, that's okay. But req-length should be set to len, not data_len. And if the hardware receives more than len bytes of data, the UDC driver should set req-status to -EOVERFLOW. 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
[RFC 1/3] ohci: convert printk to dev_dbg
From: Oliver Neukum oneu...@suse.de This converts the DEBUG level printk to dynamic debugging Signed-off-by: Oliver Neukum oneu...@suse.de --- drivers/usb/host/ohci-dbg.c | 104 ++-- drivers/usb/host/ohci-hcd.c | 4 -- drivers/usb/host/ohci-q.c | 2 - 3 files changed, 51 insertions(+), 59 deletions(-) diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 3fca52e..f0523c8 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -9,8 +9,6 @@ /*-*/ -#ifdef DEBUG - #define edstring(ed_type) ({ char *temp; \ switch (ed_type) { \ case PIPE_CONTROL: temp = ctrl; break; \ @@ -20,57 +18,6 @@ } temp;}) #define pipestring(pipe) edstring(usb_pipetype(pipe)) -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header - */ -static void __maybe_unused -urb_print(struct urb * urb, char * str, int small, int status) -{ - unsigned int pipe= urb-pipe; - - if (!urb-dev || !urb-dev-bus) { - printk(KERN_DEBUG %s URB: no dev\n, str); - return; - } - -#ifndefOHCI_VERBOSE_DEBUG - if (status != 0) -#endif - printk(KERN_DEBUG %s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d\n, - str, - urb, - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? out : in, - pipestring (pipe), - urb-transfer_flags, - urb-actual_length, - urb-transfer_buffer_length, - status); - -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol (pipe)) { - printk (KERN_DEBUG %s: setup(8):, __FILE__); - for (i = 0; i 8 ; i++) - printk ( %02x, ((__u8 *) urb-setup_packet) [i]); - printk (\n); - } - if (urb-transfer_buffer_length 0 urb-transfer_buffer) { - printk (KERN_DEBUG %s: data(%d/%d):, __FILE__, - urb-actual_length, - urb-transfer_buffer_length); - len = usb_pipeout (pipe)? - urb-transfer_buffer_length: urb-actual_length; - for (i = 0; i 16 i len; i++) - printk ( %02x, ((__u8 *) urb-transfer_buffer) [i]); - printk (%s stat:%d\n, i len? ...: , status); - } - } -#endif -} #define ohci_dbg_sw(ohci, next, size, format, arg...) \ do { \ @@ -91,6 +38,7 @@ urb_print(struct urb * urb, char * str, int small, int status) } while (0); +#ifdef DEBUG static void ohci_dump_intr_mask ( struct ohci_hcd *ohci, char *label, @@ -873,5 +821,55 @@ static inline void remove_debug_files (struct ohci_hcd *ohci) #endif +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header + */ +static void __maybe_unused +urb_print(struct urb * urb, char * str, int small, int status) +{ + unsigned int pipe= urb-pipe; + struct device *ddev; + + if (!urb-dev || !urb-dev-bus) { + pr_debug(%s URB: no dev\n, str); + return; + } + + ddev = urb-dev-dev; + + dev_dbg(ddev, %s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d\n, + str, + urb, + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? out : in, + pipestring (pipe), + urb-transfer_flags, + urb-actual_length, + urb-transfer_buffer_length, + status); + + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + dev_dbg(ddev, %s: setup(8):, __FILE__); + for (i = 0; i 8 ; i++) + dev_dbg(ddev, %02x, ((__u8 *) urb-setup_packet) [i]); + dev_dbg(ddev,\n); + } + if (urb-transfer_buffer_length 0 urb-transfer_buffer) { + dev_dbg(ddev, %s: data(%d/%d):, __FILE__, + urb-actual_length, + urb-transfer_buffer_length); + len = usb_pipeout (pipe)? + urb-transfer_buffer_length: urb-actual_length; + for (i = 0; i 16 i len; i++) + dev_dbg(ddev, %02x, ((__u8 *) urb-transfer_buffer) [i]); + dev_dbg(ddev,%s
[RFC 2/3] ohci: compile all debug stuff always
From: Oliver Neukum oneu...@suse.de There's no reason to leave out the debugfs files under normal conditions. Signed-off-by: Oliver Neukum oneu...@suse.de --- drivers/usb/host/ohci-dbg.c | 10 +- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index f0523c8..5592c2b 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -1,3 +1,4 @@ + /* * OHCI HCD (Host Controller Driver) for USB. * @@ -37,8 +38,6 @@ *size -= s_len; *next += s_len; \ } while (0); - -#ifdef DEBUG static void ohci_dump_intr_mask ( struct ohci_hcd *ohci, char *label, @@ -355,13 +354,6 @@ ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, } } -#else -static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {} - -#undef OHCI_VERBOSE_DEBUG - -#endif /* DEBUG */ - /*-*/ #ifdef STUB_DEBUG_FILES -- 1.8.3.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
[RFC 3/3] ohci: rewrite ohci_dump() for dynamic debug
From: Oliver Neukum oneu...@suse.de As this function is called from interrupt care must be taken that as little as possible overhead is used if dynamic debbuging is not enabled. Signed-off-by: Oliver Neukum oneu...@suse.de --- drivers/usb/host/ohci-dbg.c | 91 - 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 5592c2b..2a67971 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -38,6 +38,8 @@ *size -= s_len; *next += s_len; \ } while (0); +static void ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size); + static void ohci_dump_intr_mask ( struct ohci_hcd *ohci, char *label, @@ -60,6 +62,25 @@ static void ohci_dump_intr_mask ( ); } +static void ohci_print_intr_mask(struct ohci_hcd *ohci, +char *label, +u32 mask) +{ + ohci_dbg(ohci, %s 0x%08x%s%s%s%s%s%s%s%s%s\n, + label, + mask, + (mask OHCI_INTR_MIE) ? MIE : , + (mask OHCI_INTR_OC) ? OC : , + (mask OHCI_INTR_RHSC) ? RHSC : , + (mask OHCI_INTR_FNO) ? FNO : , + (mask OHCI_INTR_UE) ? UE : , + (mask OHCI_INTR_RD) ? RD : , + (mask OHCI_INTR_SF) ? SF : , + (mask OHCI_INTR_WDH) ? WDH : , + (mask OHCI_INTR_SO) ? SO : + ); +} + static void maybe_print_eds ( struct ohci_hcd *ohci, char *label, @@ -71,6 +92,15 @@ static void maybe_print_eds ( ohci_dbg_sw (ohci, next, size, %s %08x\n, label, value); } +static inline void dbg_eds( + struct ohci_hcd *ohci, + char *label, + u32 value) +{ + if (value) + ohci_dbg(ohci, %s %08x\n, label, value); +} + static char *hcfs2string (int state) { switch (state) { @@ -97,6 +127,65 @@ static const char *rh_state_string(struct ohci_hcd *ohci) // dump control and status registers static void +ohci_print_status(struct ohci_hcd *controller) +{ + struct ohci_regs __iomem *regs = controller-regs; + struct device *ddev = ohci_to_hcd(controller)-self.controller; + u32 temp = 0x; + + dev_dbg(ddev, OHCI %d., 0x03 ((temp = ohci_readl(controller, regs-revision) 0xff) 4)); + dev_dbg(ddev, %d, %s legacy support registers, rh state %s\n, + (temp 0x0f), + (temp 0x0100) ? with : NO, + rh_state_string(controller)); + + dev_dbg(ddev, control 0x%03x, temp = ohci_readl(controller, regs-control)); + dev_dbg(ddev, %s%s%s HCFS=%s%s%s%s%s CBSR=%d\n, + (temp OHCI_CTRL_RWE) ? RWE : , + (temp OHCI_CTRL_RWC) ? RWC : , + (temp OHCI_CTRL_IR) ? IR : , + hcfs2string (temp OHCI_CTRL_HCFS), + (temp OHCI_CTRL_BLE) ? BLE : , + (temp OHCI_CTRL_CLE) ? CLE : , + (temp OHCI_CTRL_IE) ? IE : , + (temp OHCI_CTRL_PLE) ? PLE : , + temp OHCI_CTRL_CBSR + ); + + dev_dbg(ddev, cmdstatus 0x%05x , temp = ohci_readl(controller, regs-cmdstatus)); + dev_dbg(ddev, SOC=%d%s%s%s%s\n, + (temp OHCI_SOC) 16, + (temp OHCI_OCR) ? OCR : , + (temp OHCI_BLF) ? BLF : , + (temp OHCI_CLF) ? CLF : , + (temp OHCI_HCR) ? HCR : + ); + + ohci_print_intr_mask(controller, intrstatus, + ohci_readl(controller, regs-intrstatus)); + ohci_print_intr_mask(controller, intrenable, + ohci_readl(controller, regs-intrenable)); + // intrdisable always same as intrenable + + dbg_eds(controller, ed_periodcurrent, + ohci_readl(controller, regs-ed_periodcurrent)); + + dbg_eds(controller, ed_controlhead, + ohci_readl(controller, regs-ed_controlhead)); + dbg_eds(controller, ed_controlcurrent, + ohci_readl(controller, regs-ed_controlcurrent)); + + dbg_eds(controller, ed_bulkhead, + ohci_readl(controller, regs-ed_bulkhead)); + dbg_eds(controller, ed_bulkcurrent, + ohci_readl(controller, regs-ed_bulkcurrent)); + + dbg_eds(controller, donehead, + ohci_readl(controller, regs-donehead)); +} + +// dump control and status registers +static void ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) { struct ohci_regs __iomem *regs = controller-regs; @@ -241,7 +330,7 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose) ohci_dbg (controller, OHCI controller state\n); // dumps some of the state we know about -
Re: [PATCH] usb: phy: remove dead code
Commit [4d175f34: usb: phy: nop: Defer clock prepare until PHY init] removed a goto reaching behind a “return ret” at the end of the function thus removing the only possible way that statement could be reached, and so rendering it a dead code. This commit cleans it up by removing said dead code. Signed-off-by: Michal Nazarewicz min...@mina86.com --- drivers/usb/phy/phy-am335x.c | 2 -- drivers/usb/phy/phy-generic.c | 2 -- 2 files changed, 4 deletions(-) On Tue, Nov 12 2013, Felipe Balbi wrote: no SoB, cannot apply. Sorry about that. I already had this patch in my tree but didn't send it. I'm fine with using yours but I need SoB and commit log. I don't mind either way as long as the code gets deleted. ;) diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 6370e50..48d41ab 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -66,8 +66,6 @@ static int am335x_phy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, am_phy); return 0; - - return ret; } static int am335x_phy_remove(struct platform_device *pdev) diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index fce3a9e..db4fc22 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -271,8 +271,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); return 0; - - return err; } static int usb_phy_gen_xceiv_remove(struct platform_device *pdev) -- 1.8.3.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: [PATCH] usb: xhci: Link TRB must not occur with a USB payload burst.
On Tue, 12 Nov 2013, David Laight wrote: You're right. I do wish the spec had been written more clearly. I've read a lot of hardware specs in my time ... Reading it all again makes me think that a LINK trb is only allowed on the burst boundary (which might be 16k bytes). The only real way to implement that is to ensure that TD never contain LINK TRB. That's one way to do it. Or you could allow a Link TRB at an intermediate MBP boundary. If all the fragments are larger than the MBP (assume 16k) then that would be relatively easy. However that is very dependant on the source of the data. It might be true for disk data, but is unlikely to be true for ethernet data. I don't quite understand your point. Are you saying that if all the TRBs are very short, you might need more than 64 TRBs to reach a 16-KB boundary? For bulk data the link TRB can be forced at a packet boundary by splitting the TD up - the receiving end won't know the difference. That won't work. What happens if you split a TD up into two pieces and the first piece receives a short packet? The host controller will automatically move to the start of the second piece. That's not what we want. It comes down to a question of how often you want the controller to issue an interrupt. If a ring segment is 4 KB (one page), then it can hold 256 TRBs. With scatter-gather transfers, each SG element typically refers to something like a 2-page buffer (depends on how fragmented the memory is). Therefore a ring segment will describe somewhere around 512 pages of data, i.e., something like 2 MB. Since SuperSpeed is 500 MB/s, you'd end up getting in the vicinity of 250 interrupts every second just because of ring segment crossings. 250 interrupts/sec is noise. Send/receive 13000 ethernet packets/sec and then look at the interrupt rate! There is no necessity for taking an interrupt from every link segment. Yes, there is. The HCD needs to know when the dequeue pointer has moved beyond the end of the ring segment, so that it can start reusing the TRB slots in that segment. Suppose you have queued a bulk URB because there weren't enough free TRB slots. How else would you know when the occupied slots became available? The current ring segments contain 64 entries, a strange choice since they are created with 2 segments. (The ring expansion code soon doubles that for my ethernet traffic.) I would change the code to use a single segment (for coding simplicity) and queue bulk URB when there isn't enough ring space. URB with too many fragments could either be rejected, sent in sections, or partially linearised (and probably still sent in sections). Rejecting an URB is not feasible. Splitting it up into multiple TDs is not acceptable, as explained above. Sending it in sections (i.e., queueing only some of the TRBs at any time) would work, provided you got at least two interrupts every time the queue wrapped around (which suggests you might want at least two ring segments). 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: [RFC 1/3] ohci: convert printk to dev_dbg
On Tue, 12 Nov 2013 oli...@neukum.org wrote: From: Oliver Neukum oneu...@suse.de This converts the DEBUG level printk to dynamic debugging I would prefer to get rid of the urb_print() function entirely. As far as I know, nobody has used it in years. 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: [RFC 2/3] ohci: compile all debug stuff always
On Tue, 12 Nov 2013 oli...@neukum.org wrote: From: Oliver Neukum oneu...@suse.de There's no reason to leave out the debugfs files under normal conditions. Signed-off-by: Oliver Neukum oneu...@suse.de --- drivers/usb/host/ohci-dbg.c | 10 +- 1 file changed, 1 insertion(+), 9 deletions(-) This patch should also get rid of the definition of STUB_DEBUG_FILES in ohci.h and the corresponding test in ohci-dbg.c. Otherwise you might end up building all the code to populate the debugfs files but leaving out the code to register them! 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] usb: xhci: Link TRB must not occur with a USB payload burst.
If all the fragments are larger than the MBP (assume 16k) then that would be relatively easy. However that is very dependant on the source of the data. It might be true for disk data, but is unlikely to be true for ethernet data. I don't quite understand your point. Are you saying that if all the TRBs are very short, you might need more than 64 TRBs to reach a 16-KB boundary? Since you don't really want to do all the work twice, the sensible way is to add each input fragment to the ring one a time. If you need to cross a link TRB and the last MBP boundary is within the previous data TRB then you can split the previous data TRB at the MBP boundary and continue. If the previous TRB is short then you'd need to go back through the earlier TRB until you found the one that contains a TRB boundary, split it, and write a link TRB in the following slot. If you are within the first MBP then you'd need to replace the first TRB of the message with a link TRB. And yes, if the data is really fragmented you might need a lot of TRB for even 1k of data. For bulk data the link TRB can be forced at a packet boundary by splitting the TD up - the receiving end won't know the difference. That won't work. What happens if you split a TD up into two pieces and the first piece receives a short packet? The host controller will automatically move to the start of the second piece. That's not what we want. You can split a bulk TD on a 1k boundary and the target won't know the difference. There is no necessity for taking an interrupt from every link segment. Yes, there is. The HCD needs to know when the dequeue pointer has moved beyond the end of the ring segment, so that it can start reusing the TRB slots in that segment. You already know that because of the interrupts for the data packets themselves. I would change the code to use a single segment (for coding simplicity) and queue bulk URB when there isn't enough ring space. URB with too many fragments could either be rejected, sent in sections, or partially linearised (and probably still sent in sections). Rejecting an URB is not feasible. Splitting it up into multiple TDs is not acceptable, as explained above. Sending it in sections (i.e., queueing only some of the TRBs at any time) would work, provided you got at least two interrupts every time the queue wrapped around (which suggests you might want at least two ring segments). Rejecting badly fragmented URB is almost certainly ok. You really don't want the hardware overhead of processing a TRB every few bytes. This would be especially bad on iommu systems. Before the ring expansion code was added there was an implicit limit of (probably) 125 fragments for a URB. Exceeding this limit wasn't the reason for adding the ring expansion code. And, as I've pointed out, both bulk and isoc URB can be split unless they are using too many fragments for a short piece of data. The current code refuses to write into a TRB segment until it is empty - I think that restriction is only there so that it can add another segment when the space runs out. David -- 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: [RFC 3/3] ohci: rewrite ohci_dump() for dynamic debug
On Tue, 12 Nov 2013 oli...@neukum.org wrote: From: Oliver Neukum oneu...@suse.de As this function is called from interrupt care must be taken that as little as possible overhead is used if dynamic debbuging is not enabled. Firstly, the function is called in interrupt context only when an Unrecoverable Error occurs. I think we can afford a little extra overhead in that case. Secondly, this patch creates a duplicate copy of ohci_dump_status(), which is a rather lengthy debugging function. This is hardly elegant. 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] usb: xhci: Link TRB must not occur with a USB payload burst.
On Mon, Nov 11, 2013 at 03:34:53PM -0500, Alan Stern wrote: On Mon, 11 Nov 2013, David Laight wrote: Suppose, for example, the MBP is 1024. If you have a TD with length 1500, and if it had only one fragment, the last (and only) fragment's length would not less than the MBP and it would not be an exact multiple of the MBP. That doesn't matter - eg example 2 in figure 25 You're right. I do wish the spec had been written more clearly. Reading it all again makes me think that a LINK trb is only allowed on the burst boundary (which might be 16k bytes). The only real way to implement that is to ensure that TD never contain LINK TRB. That's one way to do it. Or you could allow a Link TRB at an intermediate MBP boundary. I like this idea instead. The xHCI driver should be modified to be able to handle link TRBs in the middle of the segments (the cancellation code would have to be touched as well). We would keep a running count of the number of bytes left in a TD fragment, as we fill in the TRBs. If we find the TD fragment would span a link TRB, we backtrack to the end of the last TD fragment, put in a link TRB, and then continue on the next segment. It comes down to a question of how often you want the controller to issue an interrupt. If a ring segment is 4 KB (one page), then it can hold 256 TRBs. With scatter-gather transfers, each SG element typically refers to something like a 2-page buffer (depends on how fragmented the memory is). Therefore a ring segment will describe somewhere around 512 pages of data, i.e., something like 2 MB. Since SuperSpeed is 500 MB/s, you'd end up getting in the vicinity of 250 interrupts every second just because of ring segment crossings. The driver is currently defined to have 64 TRBs per ring segment. But that doesn't matter; we don't get an interrupt when a ring segment is crossed. Instead we set the interrupt-on-completion flag on the last TRB of the TD, not on any earlier fragment or link TRB. Using larger ring segments would help. Ring segments have to be physically contiguous, so I'm not sure if we want to ask for segments that are bigger than a page. I've already got a report from someone else about the ring expansion getting out of control, so I would like to figure that out before we talk about using even bigger segments. Finally, it's interesting to note that the USB mass storage driver is using scatter gather lists just fine without the driver following the TD fragment rules. Or at least no one has reported any issues. I wonder why it works? Sarah Sharp -- 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: huawei_cdc_ncm driver
If that still does not change anything, then I'd really appreciate it if you could run through (assuming the v3.11 driver was OK): git bisect start 9fea037de5f3 v3.11 -- drivers/net/usb/cdc_ncm.c That failed too. (switching was ok, compiling was ok, booting, recognizing the devices ok, but dhcp / RA not ok) So problem seems to be somewhere but not in you driver. Thomas -- 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: [Pull Request] xhci: Bug fixes, now with more tags!
On Mon, Nov 11, 2013 at 11:27:13AM +0100, Vincent Thiele wrote: This Bug is still not completely solved (Ubuntu 13.10 newest kernel 3.11) Have you tried compiling 3.12 instead? I don't have any control over when Ubuntu picks up bug fixes for their kernel. Syslog: Nov 2 18:44:29 Arbeits-PC whoopsie[961]: online Nov 2 18:45:41 whoopsie[961]: last message repeated 2 times Nov 2 18:56:27 Arbeits-PC kernel: [ 8411.030685] usb 3-2: USB disconnect, device number 21 Nov 2 18:56:27 Arbeits-PC colord: device removed: sysfs-LGE-Nexus_4 Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.253950] usb 3-2: new high-speed USB device number 25 using xhci_hcd Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.270843] usb 3-2: New USB device found, idVendor=18d1, idProduct=4ee1 Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.270848] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.270851] usb 3-2: Product: Nexus 4 Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.270854] usb 3-2: Manufacturer: LGE Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.270856] usb 3-2: SerialNumber: 00294807ce91f316 Nov 2 18:56:28 Arbeits-PC colord: Device added: sysfs-LGE-Nexus_4 Nov 2 18:56:28 Arbeits-PC dbus[651]: [system] Activating service name='org.freedesktop.hostname1' (using servicehelper) Nov 2 18:56:28 Arbeits-PC dbus[651]: [system] Successfully activated service 'org.freedesktop.hostname1' Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.451541] usb 3-2: USB disconnect, device number 25 Nov 2 18:56:28 Arbeits-PC colord: device removed: sysfs-LGE-Nexus_4 Nov 2 18:56:29 Arbeits-PC kernel: [ 8413.735802] usb 3-2: new high-speed USB device number 30 using xhci_hcd Nov 2 18:56:45 Arbeits-PC kernel: [ 8418.728670] xhci_hcd :03:00.0: Timeout while waiting for address device command Nov 2 18:56:45 Arbeits-PC kernel: [ 8429.521172] [sched_delayed] sched: RT throttling activated Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: The canary thread is apparently starving. Taking action. Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: Demoting known real-time threads. Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: Successfully demoted thread 2186 of process 2142 (n/a). Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: Successfully demoted thread 2185 of process 2142 (n/a). Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: Successfully demoted thread 2184 of process 2142 (n/a). Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: Successfully demoted thread 2142 of process 2142 (n/a). Nov 2 18:56:45 Arbeits-PC rtkit-daemon[1321]: Demoted 4 threads. Nov 2 18:56:45 Arbeits-PC kernel: [ 8429.720909] usb 3-2: Device not responding to set address. Nov 2 18:56:45 Arbeits-PC kernel: [ 8429.924616] usb 3-2: device not accepting address 30, error -71 Nov 2 18:57:05 Arbeits-PC kernel: [ 8434.917500] xhci_hcd :03:00.0: Timeout while waiting for a slot Nov 2 18:57:05 Arbeits-PC kernel: [ 8449.102462] xhci_hcd :03:00.0: Stopped the command ring failed, maybe the host is dead Nov 2 18:57:05 Arbeits-PC kernel: [ 8449.102479] xhci_hcd :03:00.0: Abort command ring failed Nov 2 18:57:05 Arbeits-PC kernel: [ 8449.102677] xhci_hcd :03:00.0: HC died; cleaning up Nov 2 18:57:05 Arbeits-PC kernel: [ 8449.104659] xHCI xhci_free_dev called with unaddressed device Nov 2 18:57:10 Arbeits-PC kernel: [ 8454.094047] xhci_hcd :03:00.0: Timeout while waiting for a slot Nov 2 18:57:10 Arbeits-PC kernel: [ 8454.094051] xhci_hcd :03:00.0: Abort the command ring, but the xHCI is dead. Nov 2 18:57:10 Arbeits-PC kernel: [ 8454.094060] xHCI xhci_free_dev called with unaddressed device Nov 2 18:57:15 Arbeits-PC kernel: [ 8459.086911] xhci_hcd :03:00.0: Timeout while waiting for a slot Nov 2 18:57:15 Arbeits-PC kernel: [ 8459.086917] xhci_hcd :03:00.0: Abort the command ring, but the xHCI is dead. Nov 2 18:57:15 Arbeits-PC kernel: [ 8459.086930] xHCI xhci_free_dev called with unaddressed device Nov 2 18:57:15 Arbeits-PC kernel: [ 8459.086940] usb 3-1: USB disconnect, device number 2 Nov 2 18:57:15 Arbeits-PC udisksd[2260]: Cleaning up mount point /media/vincent/Elements (device 8:33 no longer exist) Nov 2 18:57:15 Arbeits-PC ntfs-3g[2477]: Unmounting /dev/sdc1 (Elements) Short system hang with looping audio after that every usb-device which is connected with this usb-controller is disconnected until i reboot the system. 2013/11/3 Vincent Thiele vincentthi...@gmail.com: This Bug is still not completely solved (Ubuntu 13.10 newest kernel 3.11) Syslog: Nov 2 18:44:29 Arbeits-PC whoopsie[961]: online Nov 2 18:45:41 whoopsie[961]: last message repeated 2 times Nov 2 18:56:27 Arbeits-PC kernel: [ 8411.030685] usb 3-2: USB disconnect, device number 21 Nov 2 18:56:27 Arbeits-PC colord: device removed: sysfs-LGE-Nexus_4 Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.253950] usb 3-2: new high-speed USB device number 25 using xhci_hcd Nov 2 18:56:28 Arbeits-PC kernel: [ 8412.270843]
RE: [PATCH] usb: xhci: Link TRB must not occur with a USB payload burst.
On Fri, Nov 08, 2013 at 11:07:41AM -, David Laight wrote: While this change improves things a lot (it runs for 20 minutes rather than a few seconds), there is still something else wrong. Almost certainly caused by an unrelated local change. Ok, good, I was concerned there was another issue we were missing. My modified code wasn't setting the td_size properly. That is fixed and verified in the later patch I sent. David -- 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: [RFC] Revert sierra_net: keep status interrupt URB active
On Tue, 2013-11-12 at 10:25 -0600, Dan Williams wrote: On Fri, 2013-11-08 at 15:29 -0600, Dan Williams wrote: On Fri, 2013-11-08 at 21:44 +0100, Bjørn Mork wrote: Dan Williams d...@redhat.com writes: On Mon, 2013-11-04 at 14:27 -0600, Dan Williams wrote: On Fri, 2013-11-01 at 13:53 +0100, Bjørn Mork wrote: This reverts commit 7b0c5f21f348a66de495868b8df0284e8dfd6bbf. It's not easy to create a driver for all the various firmware bugs out there. This change caused regressions for a number of devices, which started to fail link detection and therefore became completely non-functional. The exact reason is yet unknown, it looks like the affected firmwares might actually need all or some of the additional SYNC messages the patch got rid of. Reverting is not optimal, as it will re-introduce the original problem, but it is currently the only alternative known to fix this issue. Instead, how does the following patch work for you? Bjorn, did you have a chance to try this patch out on your devices? The only DirectIP device I have is the MC7710, which never had any of the firmware issues you are trying to fix. I only tried to forward Johns issue. When this patch worked for John, then I am pretty confident that you have solved the problem here. Well, solved, since I still have no idea why the original patch would cause the device behavior based on what I know and have read about the expected firmware/host handshaking sequence. But the patch there appears to fix the problem *and* not blindly send tons of SYNCs forever. So I'll go ahead and submit a proper version of it. Actually, is [PATCH] usbnet: fix status interrupt urb handling the real fix for this problem? John, any chance you could revert my RFC patch and try Felix's patch in that mail? It fixes the problem for me without requiring the revert or my RFC patch Dan -- 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: xhci: Link TRB must not occur with a USB payload burst.
That's one way to do it. Or you could allow a Link TRB at an intermediate MBP boundary. I like this idea instead. The xHCI driver should be modified to be able to handle link TRBs in the middle of the segments (the cancellation code would have to be touched as well). We would keep a running count of the number of bytes left in a TD fragment, as we fill in the TRBs. If we find the TD fragment would span a link TRB, we backtrack to the end of the last TD fragment, put in a link TRB, and then continue on the next segment. I'd do that as a later change. It needs a fair amount of other stuff fixing first and the current code is rather broken - and needs a fix for stable. It comes down to a question of how often you want the controller to issue an interrupt. If a ring segment is 4 KB (one page), then it can hold 256 TRBs. With scatter-gather transfers, each SG element typically refers to something like a 2-page buffer (depends on how fragmented the memory is). Therefore a ring segment will describe somewhere around 512 pages of data, i.e., something like 2 MB. Since SuperSpeed is 500 MB/s, you'd end up getting in the vicinity of 250 interrupts every second just because of ring segment crossings. The driver is currently defined to have 64 TRBs per ring segment. But that doesn't matter; we don't get an interrupt when a ring segment is crossed. Instead we set the interrupt-on-completion flag on the last TRB of the TD, not on any earlier fragment or link TRB. Using larger ring segments would help. Ring segments have to be physically contiguous, so I'm not sure if we want to ask for segments that are bigger than a page. I've already got a report from someone else about the ring expansion getting out of control, so I would like to figure that out before we talk about using even bigger segments. I'd vote for a single segment containing either 128 or 256 TRBs. That is less than a single page. Finally, it's interesting to note that the USB mass storage driver is using scatter gather lists just fine without the driver following the TD fragment rules. Or at least no one has reported any issues. I wonder why it works? I suspect that breaking the rules just generates two TD. The mass storage driver is probably almost always presenting buffer fragments that are page sized and page aligned. In which case the split is invisible at the target. David -- 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 2/4] usb: usbtest: support usb2 extension descriptor test
On Mon, Oct 28, 2013 at 11:31:33PM +0800, Huang Rui wrote: In Test 9 of usbtest module, it is used for performing chapter 9 tests N times. USB2.0 Extension descriptor is one of the generic device-level capbility descriptors which added in section 9.6.2.1 of USB 3.0 spec. This patch adds to support getting usb2.0 extension descriptor test scenario for USB 3.0. Why not check the USB 2.0 extension BOS descriptor for USB 2.1 devices as well? Just change you check to be bcdUSB = 0x0210. You would have to make sure you fail a USB 2.1 device with a the USB 3.0 BOS extension descriptor or the Container ID BOS extension. More comments below. Signed-off-by: Huang Rui ray.hu...@amd.com --- drivers/usb/misc/usbtest.c | 77 ++ 1 file changed, 77 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 38ebe1d..d9ac215 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -606,6 +606,28 @@ static int is_good_config(struct usbtest_dev *tdev, int len) return 0; } +static int is_good_ext(struct usbtest_dev *tdev, char *buf) +{ + struct usb_ext_cap_descriptor *ext; + u32 attr; + + ext = (struct usb_ext_cap_descriptor *) buf; + + if (ext-bLength != USB_DT_USB_EXT_CAP_SIZE) { + ERROR(tdev, bogus usb 2.0 extension descriptor length\n); + return 0; + } + + attr = le32_to_cpu(ext-bmAttributes); + /* bits[1:4] is used and others are reserved */ + if (attr ~0x1e) { /* reserved == 0 */ + ERROR(tdev, reserved bits set\n); + return 0; + } New errata for USB 2.1 Link PM that adds support for the BESL and DBESL encoding uses bits[1:15]. See the USB2-LPM-Errata-final.pdf file in the latest download of the USB 2.0 spec. This code should be fixed to reflect those changes (bitmask should be 0xfffe rather than 0x1e). + + return 1; +} + /* sanity test for standard requests working with usb_control_mesg() and some * of the utility functions which use it. * @@ -694,12 +716,67 @@ static int ch9_postconfig(struct usbtest_dev *dev) * 3.0 spec */ if (le16_to_cpu(udev-descriptor.bcdUSB) = 0x0300) { + struct usb_bos_descriptor *bos = NULL; + struct usb_dev_cap_header *header = NULL; + unsigned total, num, length; + char *buf; + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev-buf, sizeof(*udev-bos-desc)); if (retval != sizeof(*udev-bos-desc)) { dev_err(iface-dev, bos descriptor -- %d\n, retval); return (retval 0) ? retval : -EDOM; } + + bos = (struct usb_bos_descriptor *)dev-buf; + total = le16_to_cpu(bos-wTotalLength); + num = bos-bNumDeviceCaps; + + if (total TBUF_SIZE) + total = TBUF_SIZE; + + /* + * get generic device-level capability descriptors [9.6.2] + * in USB 3.0 spec + */ + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev-buf, + total); + if (retval != total) { + dev_err(iface-dev, bos descriptor set -- %d\n, + retval); + return (retval 0) ? retval : -EDOM; + } + + length = sizeof(*udev-bos-desc); + buf = (char *)dev-buf; + for (i = 0; i num; i++) { + buf += length; + if (buf + sizeof(struct usb_dev_cap_header) + dev-buf + total) + break; + + header = (struct usb_dev_cap_header *)buf; + length = header-bLength; + + if (header-bDescriptorType != + USB_DT_DEVICE_CAPABILITY) { + dev_warn(udev-dev, not device capability descriptor, skip\n); + continue; + } + + switch (header-bDevCapabilityType) { + case USB_CAP_TYPE_EXT: + if (buf + USB_DT_USB_EXT_CAP_SIZE + dev-buf + total || + !is_good_ext(dev, buf)) { + dev_err(iface-dev, bogus usb 2.0 extension descriptor\n); + return -EDOM; + } + break; + default: + break; + } + } } /* there's always [9.4.3] at least one config descriptor
Re: [PATCH v4 2/4] usb: usbtest: support usb2 extension descriptor test
On Wed, Oct 30, 2013 at 11:27:38AM +0800, Huang Rui wrote: In Test 9 of usbtest module, it is used for performing chapter 9 tests N times. USB2.0 Extension descriptor is one of the generic device-level capbility descriptors which added in section 9.6.2.1 of USB 3.0 spec. This patch adds to support getting usb2.0 extension descriptor test scenario for USB 3.0. I accidentally replied to the last patch revision, but my comments are still true for this revision. You need to: - Also check USB 2.1 devices for the USB 2.0 extension BOS descriptor - Change the bit mask check on bmAttributes to be 0xFFFE rather than 0x1e. Sarah Sharp Signed-off-by: Huang Rui ray.hu...@amd.com Acked-by: Alan Stern st...@rowland.harvard.edu --- drivers/usb/misc/usbtest.c | 77 ++ 1 file changed, 77 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 38ebe1d..84d491d 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -606,6 +606,28 @@ static int is_good_config(struct usbtest_dev *tdev, int len) return 0; } +static int is_good_ext(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ext_cap_descriptor *ext; + u32 attr; + + ext = (struct usb_ext_cap_descriptor *) buf; + + if (ext-bLength != USB_DT_USB_EXT_CAP_SIZE) { + ERROR(tdev, bogus usb 2.0 extension descriptor length\n); + return 0; + } + + attr = le32_to_cpu(ext-bmAttributes); + /* bits[1:4] is used and others are reserved */ + if (attr ~0x1e) { /* reserved == 0 */ + ERROR(tdev, reserved bits set\n); + return 0; + } + + return 1; +} + /* sanity test for standard requests working with usb_control_mesg() and some * of the utility functions which use it. * @@ -694,12 +716,67 @@ static int ch9_postconfig(struct usbtest_dev *dev) * 3.0 spec */ if (le16_to_cpu(udev-descriptor.bcdUSB) = 0x0300) { + struct usb_bos_descriptor *bos = NULL; + struct usb_dev_cap_header *header = NULL; + unsigned total, num, length; + u8 *buf; + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev-buf, sizeof(*udev-bos-desc)); if (retval != sizeof(*udev-bos-desc)) { dev_err(iface-dev, bos descriptor -- %d\n, retval); return (retval 0) ? retval : -EDOM; } + + bos = (struct usb_bos_descriptor *)dev-buf; + total = le16_to_cpu(bos-wTotalLength); + num = bos-bNumDeviceCaps; + + if (total TBUF_SIZE) + total = TBUF_SIZE; + + /* + * get generic device-level capability descriptors [9.6.2] + * in USB 3.0 spec + */ + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev-buf, + total); + if (retval != total) { + dev_err(iface-dev, bos descriptor set -- %d\n, + retval); + return (retval 0) ? retval : -EDOM; + } + + length = sizeof(*udev-bos-desc); + buf = dev-buf; + for (i = 0; i num; i++) { + buf += length; + if (buf + sizeof(struct usb_dev_cap_header) + dev-buf + total) + break; + + header = (struct usb_dev_cap_header *)buf; + length = header-bLength; + + if (header-bDescriptorType != + USB_DT_DEVICE_CAPABILITY) { + dev_warn(udev-dev, not device capability descriptor, skip\n); + continue; + } + + switch (header-bDevCapabilityType) { + case USB_CAP_TYPE_EXT: + if (buf + USB_DT_USB_EXT_CAP_SIZE + dev-buf + total || + !is_good_ext(dev, buf)) { + dev_err(iface-dev, bogus usb 2.0 extension descriptor\n); + return -EDOM; + } + break; + default: + break; + } + } } /* there's always [9.4.3] at least one config descriptor [9.6.3] */ -- 1.7.11.7 -- 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 v4 2/4] usb: usbtest: support usb2 extension descriptor test
On Tue, Nov 12, 2013 at 09:59:13AM -0800, Sarah Sharp wrote: On Wed, Oct 30, 2013 at 11:27:38AM +0800, Huang Rui wrote: In Test 9 of usbtest module, it is used for performing chapter 9 tests N times. USB2.0 Extension descriptor is one of the generic device-level capbility descriptors which added in section 9.6.2.1 of USB 3.0 spec. This patch adds to support getting usb2.0 extension descriptor test scenario for USB 3.0. I accidentally replied to the last patch revision, but my comments are still true for this revision. You need to: - Also check USB 2.1 devices for the USB 2.0 extension BOS descriptor - Change the bit mask check on bmAttributes to be 0xFFFE rather than 0x1e. Since it looks like Greg already has this patch in usb-next, can you send a bug fix patch to fix the bit mask? Thanks, Sarah Sharp Signed-off-by: Huang Rui ray.hu...@amd.com Acked-by: Alan Stern st...@rowland.harvard.edu --- drivers/usb/misc/usbtest.c | 77 ++ 1 file changed, 77 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 38ebe1d..84d491d 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -606,6 +606,28 @@ static int is_good_config(struct usbtest_dev *tdev, int len) return 0; } +static int is_good_ext(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ext_cap_descriptor *ext; + u32 attr; + + ext = (struct usb_ext_cap_descriptor *) buf; + + if (ext-bLength != USB_DT_USB_EXT_CAP_SIZE) { + ERROR(tdev, bogus usb 2.0 extension descriptor length\n); + return 0; + } + + attr = le32_to_cpu(ext-bmAttributes); + /* bits[1:4] is used and others are reserved */ + if (attr ~0x1e) { /* reserved == 0 */ + ERROR(tdev, reserved bits set\n); + return 0; + } + + return 1; +} + /* sanity test for standard requests working with usb_control_mesg() and some * of the utility functions which use it. * @@ -694,12 +716,67 @@ static int ch9_postconfig(struct usbtest_dev *dev) * 3.0 spec */ if (le16_to_cpu(udev-descriptor.bcdUSB) = 0x0300) { + struct usb_bos_descriptor *bos = NULL; + struct usb_dev_cap_header *header = NULL; + unsigned total, num, length; + u8 *buf; + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev-buf, sizeof(*udev-bos-desc)); if (retval != sizeof(*udev-bos-desc)) { dev_err(iface-dev, bos descriptor -- %d\n, retval); return (retval 0) ? retval : -EDOM; } + + bos = (struct usb_bos_descriptor *)dev-buf; + total = le16_to_cpu(bos-wTotalLength); + num = bos-bNumDeviceCaps; + + if (total TBUF_SIZE) + total = TBUF_SIZE; + + /* +* get generic device-level capability descriptors [9.6.2] +* in USB 3.0 spec +*/ + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev-buf, + total); + if (retval != total) { + dev_err(iface-dev, bos descriptor set -- %d\n, + retval); + return (retval 0) ? retval : -EDOM; + } + + length = sizeof(*udev-bos-desc); + buf = dev-buf; + for (i = 0; i num; i++) { + buf += length; + if (buf + sizeof(struct usb_dev_cap_header) + dev-buf + total) + break; + + header = (struct usb_dev_cap_header *)buf; + length = header-bLength; + + if (header-bDescriptorType != + USB_DT_DEVICE_CAPABILITY) { + dev_warn(udev-dev, not device capability descriptor, skip\n); + continue; + } + + switch (header-bDevCapabilityType) { + case USB_CAP_TYPE_EXT: + if (buf + USB_DT_USB_EXT_CAP_SIZE + dev-buf + total || + !is_good_ext(dev, buf)) { + dev_err(iface-dev, bogus usb 2.0 extension descriptor\n); + return -EDOM; + } + break; + default: + break; + } + } } /* there's always [9.4.3] at least one config descriptor [9.6.3] */ -- 1.7.11.7 -- To unsubscribe from this list: send the line
Re: [PATCHv2 2/2] check quirk to pad epout buf size when not aligned to maxpacketsize
IIUC, req-length should still be set to len, not to data_len. I misunderstood the first time I read it: In order to avoid DWC3 to stall, we need to update req-length (this is the most important fix). kmalloc() is updated too to prevent USB controller to overflow buffer boundaries. Here I disagree. If the DWC3 hardware stalls, it is up to the DWC3 UDC driver to fix it. Gadget drivers should not have to worry. Most especially, gadget drivers should not lie about a request length. If the UDC driver decides to round up req-length before sending it to the hardware, that's okay. But req-length should be set to len, not data_len. And if the hardware receives more than len bytes of data, the UDC driver should set req-status to -EOVERFLOW. Got your point. As long as buffer allocation has enough size, DWC3 is able to fix itself. I'm fine with this approach too. But in this case I will need to redo my DWC3 patch and my validation. Br, David 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: [PATCHv5.1 4/5] check quirk to pad epout buf size when not aligned to maxpacketsize
On 11/12/2013 04:59 AM, Michal Nazarewicz wrote: On Tue, Nov 12 2013, David Cohen wrote: You need to update req-length otherwise it's going to crash DWC3. I'd rather to keep your previous version. That's unfortunate. Do you want me to resend it or will you just send a v6 of your whole series? Alan disagreed and proposed a good approach to fix req-length inside DWC3. We can keep this patch of yours but I'll need to change mine to DWC3. I'll send a v6 with update on my patch. Br, David -- 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] usb: host: Remove superfluous name casts
device_driver.name is const char * Signed-off-by: Geert Uytterhoeven ge...@linux-m68k.org Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: linux-usb@vger.kernel.org --- drivers/usb/host/imx21-hcd.c|2 +- drivers/usb/host/isp116x-hcd.c |2 +- drivers/usb/host/isp1362-hcd.c |2 +- drivers/usb/host/r8a66597-hcd.c |2 +- drivers/usb/host/u132-hcd.c |2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index adb01d950a16..3fb2315dcb47 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1926,7 +1926,7 @@ failed_request_mem: static struct platform_driver imx21_hcd_driver = { .driver = { - .name = (char *)hcd_name, + .name = hcd_name, }, .probe = imx21_probe, .remove = imx21_remove, diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index c06739705d24..ab536637842d 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1775,7 +1775,7 @@ static struct platform_driver isp116x_driver = { .suspend = isp116x_suspend, .resume = isp116x_resume, .driver = { - .name = (char *)hcd_name, + .name = hcd_name, .owner = THIS_MODULE, }, }; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 935a2dd367a8..cd94b108b57f 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2829,7 +2829,7 @@ static struct platform_driver isp1362_driver = { .suspend = isp1362_suspend, .resume = isp1362_resume, .driver = { - .name = (char *)hcd_name, + .name = hcd_name, .owner = THIS_MODULE, }, }; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 2ad004ae747c..3bddfcfafb79 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2534,7 +2534,7 @@ static struct platform_driver r8a66597_driver = { .probe =r8a66597_probe, .remove = r8a66597_remove, .driver = { - .name = (char *) hcd_name, + .name = hcd_name, .owner = THIS_MODULE, .pm = R8A66597_DEV_PM_OPS, }, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index e402beb5a069..46236e9fc87f 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3217,7 +3217,7 @@ static struct platform_driver u132_platform_driver = { .suspend = u132_suspend, .resume = u132_resume, .driver = { - .name = (char *)hcd_name, + .name = hcd_name, .owner = THIS_MODULE, }, }; -- 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: [PATCH v4 01/15] usb: phy: msm: Move mach dependent code to platform data
Hi Christopher, On Tue, 2013-11-12 at 13:27 -0500, Christopher Covington wrote: Hi Ivan, On 11/12/2013 09:51 AM, Ivan T. Ivanov wrote: From: Ivan T. Ivanov iiva...@mm-sol.com This patch fix compilation error when driver is compiled in multi-platform builds. drivers/built-in.o: In function `msm_otg_link_clk_reset': ./drivers/usb/phy/phy-msm-usb.c:314: undefined reference to `clk_reset' ./drivers/usb/phy/phy-msm-usb.c:318: undefined reference to `clk_reset' Use platform data supplied reset handlers and adjust error messages reported when reset sequence fail. This is an intermediate step before adding support for reset framework and newer targets. Signed-off-by: Ivan T. Ivanov iiva...@mm-sol.com Acked-by: David Brown dav...@codeaurora.org Cc: Daniel Walker dwal...@fifo99.com Cc: Felipe Balbi ba...@ti.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org --- arch/arm/mach-msm/board-msm7x30.c | 35 +++ arch/arm/mach-msm/board-qsd8x50.c | 35 +++ drivers/usb/phy/phy-msm-usb.c | 35 +++ include/linux/usb/msm_hsusb.h |3 +++ 4 files changed, 88 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index f9af5a4..46de789 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -30,6 +30,7 @@ #include asm/memory.h #include asm/setup.h +#include mach/clk.h #include mach/msm_iomap.h #include mach/dma.h @@ -60,10 +61,44 @@ static int hsusb_phy_init_seq[] = { -1 }; +static int hsusb_link_clk_reset(struct clk *link_clk, bool assert) +{ + int ret; + + if (assert) { + ret = clk_reset(link_clk, CLK_RESET_ASSERT); + if (ret) + pr_err(usb hs_clk assert failed\n); + } else { + ret = clk_reset(link_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb hs_clk deassert failed\n); + } + return ret; +} + +static int hsusb_phy_clk_reset(struct clk *phy_clk) +{ + int ret; + + ret = clk_reset(phy_clk, CLK_RESET_ASSERT); + if (ret) { + pr_err(usb phy clk assert failed\n); + return ret; + } + usleep_range(1, 12000); + ret = clk_reset(phy_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb phy clk deassert failed\n); + return ret; +} + static struct msm_otg_platform_data msm_otg_pdata = { .phy_init_seq = hsusb_phy_init_seq, .mode = USB_PERIPHERAL, .otg_control= OTG_PHY_CONTROL, + .link_clk_reset = hsusb_link_clk_reset, + .phy_clk_reset = hsusb_phy_clk_reset, }; struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 5f933bc..9169ec3 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -31,6 +31,7 @@ #include mach/irqs.h #include mach/sirc.h #include mach/vreg.h +#include mach/clk.h #include linux/platform_data/mmc-msm_sdcc.h #include devices.h @@ -81,10 +82,44 @@ static int hsusb_phy_init_seq[] = { -1 }; +static int hsusb_link_clk_reset(struct clk *link_clk, bool assert) +{ + int ret; + + if (assert) { + ret = clk_reset(link_clk, CLK_RESET_ASSERT); + if (ret) + pr_err(usb hs_clk assert failed\n); + } else { + ret = clk_reset(link_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb hs_clk deassert failed\n); + } + return ret; +} + +static int hsusb_phy_clk_reset(struct clk *phy_clk) +{ + int ret; + + ret = clk_reset(phy_clk, CLK_RESET_ASSERT); + if (ret) { + pr_err(usb phy clk assert failed\n); + return ret; + } + usleep_range(1, 12000); + ret = clk_reset(phy_clk, CLK_RESET_DEASSERT); + if (ret) + pr_err(usb phy clk deassert failed\n); + return ret; +} Why are there identical, static definitions of hsusb_link_clk_reset and hsusb_phy_clk_reset across the two board files? Why not share a single non-static set of definitions? One file which is used by both boards and is compiled unconditionally is clock.c, but I don't think that it will be appropriate to put USB specific functions there. Creating new file for just these functions also do not sound good to me. Regards, Ivan Thanks, Christopher -- 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: xhci: Link TRB must not occur with a USB payload burst.
On Tue, 12 Nov 2013, Sarah Sharp wrote: It comes down to a question of how often you want the controller to issue an interrupt. If a ring segment is 4 KB (one page), then it can hold 256 TRBs. With scatter-gather transfers, each SG element typically refers to something like a 2-page buffer (depends on how fragmented the memory is). Therefore a ring segment will describe somewhere around 512 pages of data, i.e., something like 2 MB. Since SuperSpeed is 500 MB/s, you'd end up getting in the vicinity of 250 interrupts every second just because of ring segment crossings. The driver is currently defined to have 64 TRBs per ring segment. But A TRB is 16 bytes, right? So a page can hold 256 TRBs. Why use only 64 per segment? that doesn't matter; we don't get an interrupt when a ring segment is crossed. Instead we set the interrupt-on-completion flag on the last TRB of the TD, not on any earlier fragment or link TRB. That's because you don't worry about handling URBs which require too many TRBs (i.e., more than are available). You just add more ring segments. Instead, you could re-use segments on the fly. For example, suppose you have only two ring segments and you get an URB which requires enough TRBs to fill up four segments. You could fill in the first two segments worth, and get an interrupt when the controller traverses the Link TRB between them. At that point you store the third set of TRBs in the first segment, which is now vacant. Similarly, when the second Link TRB is traversed, you fill in the fourth set of TRBs. Using larger ring segments would help. Ring segments have to be physically contiguous, so I'm not sure if we want to ask for segments that are bigger than a page. I've already got a report from someone else about the ring expansion getting out of control, so I would like to figure that out before we talk about using even bigger segments. Maybe you can get away with fewer segments, if they are bigger. Finally, it's interesting to note that the USB mass storage driver is using scatter gather lists just fine without the driver following the TD fragment rules. Or at least no one has reported any issues. I wonder why it works? I'd guess this is because the hardware is actually a lot more flexible than the No Link TRBs in the middle of a TD fragment rule. The whole idea of TD fragments makes no sense to begin with. What point is there in grouping packets into MaxBurst-sized collections? The hardware does not have to finish one burst before beginning the next one. For example, suppose the MaxBurst size is 8. The host starts by bursting packets 1-8. When it receives the ACK for packet 4, the host could then burst packets 9-12. It doesn't have to wait for the ACK to packet 8. (Unless I have misunderstood the USB-3 spec.) If the host does this, the burst boundaries won't occur on MBP boundaries, and hence won't occur on TD fragment boundaries. The fragment boundaries will be essentially meaningless. 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: [RFC] Revert sierra_net: keep status interrupt URB active
Dan Williams d...@redhat.com wrote: Actually, is [PATCH] usbnet: fix status interrupt urb handling the real fix for this problem? John, any chance you could revert my RFC patch and try Felix's patch in that mail? It fixes the problem for me without requiring the revert or my RFC patch Yes, this looks like a reasonable explanation. Good timing. Bjørn -- 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: huawei_cdc_ncm driver
Thomas Schäfer tschae...@t-online.de wrote: So problem seems to be somewhere but not in you driver. Let's hope so. I always worry when making changes, no matter how insignificant they are. I often feel like my bug to line ratio is a two digit number... Thanks for checking. Bjørn -- 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 v6 0/5] add gadget quirk to adapt f_fs for DWC3
Hi, These patches are a proposal to add gadget quirks in an immediate objective to adapt f_fs when using DWC3 controller. But the quirk solution is generic and can be used by other controllers to adapt gadget functions to their non-standard restrictions. This change is necessary to make Android's adbd service to work on Intel Merrifield with f_fs instead of out-of-tree android gadget. This new patch set was tested and validated in my environment: - Intel Merrifield was able to use DWC3/f_fs with adbd service (it wasn't before). Changes from v45 to v6: - Updated patches from Michal Nazarewicz to address comments from Alan Stern and mine. - Modified patch 5/5 to apply request-length's pad internally to DWC3. --- David Cohen (3): usb: gadget: move bitflags to the end of usb_gadget struct usb: gadget: add quirk_ep_out_aligned_size field to struct usb_gadget usb: dwc3: implement gadget's quirk ep_out_align_size Michal Nazarewicz (2): usb: gadget: f_fs: remove loop from I/O function check quirk to pad epout buf size when not aligned to maxpacketsize drivers/usb/dwc3/core.h| 6 +++ drivers/usb/dwc3/gadget.c | 23 ++ drivers/usb/gadget/f_fs.c | 102 + include/linux/usb/gadget.h | 35 4 files changed, 103 insertions(+), 63 deletions(-) -- 1.8.4.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
[PATCH v6 1/5] usb: gadget: move bitflags to the end of usb_gadget struct
This patch moves all bitflags to the end of usb_gadget struct in order to improve readability. Signed-off-by: David Cohen david.a.co...@linux.intel.com Acked-by: Michal Nazarewicz min...@mina86.com --- include/linux/usb/gadget.h | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 942ef5e053bf..23b3bfd0a842 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -485,6 +485,11 @@ struct usb_gadget_ops { * @max_speed: Maximal speed the UDC can handle. UDC must support this * and all slower speeds. * @state: the state we are now (attached, suspended, configured, etc) + * @name: Identifies the controller hardware type. Used in diagnostics + * and sometimes configuration. + * @dev: Driver model state for this abstract device. + * @out_epnum: last used out ep number + * @in_epnum: last used in ep number * @sg_supported: true if we can handle scatter-gather * @is_otg: True if the USB device port uses a Mini-AB jack, so that the * gadget driver must provide a USB OTG descriptor. @@ -497,11 +502,6 @@ struct usb_gadget_ops { * only supports HNP on a different root port. * @b_hnp_enable: OTG device feature flag, indicating that the A-Host * enabled HNP support. - * @name: Identifies the controller hardware type. Used in diagnostics - * and sometimes configuration. - * @dev: Driver model state for this abstract device. - * @out_epnum: last used out ep number - * @in_epnum: last used in ep number * * Gadgets have a mostly-portable gadget driver implementing device * functions, handling all usb configurations and interfaces. Gadget @@ -530,16 +530,17 @@ struct usb_gadget { enum usb_device_speed speed; enum usb_device_speed max_speed; enum usb_device_state state; + const char *name; + struct device dev; + unsignedout_epnum; + unsignedin_epnum; + unsignedsg_supported:1; unsignedis_otg:1; unsignedis_a_peripheral:1; unsignedb_hnp_enable:1; unsigneda_hnp_support:1; unsigneda_alt_hnp_support:1; - const char *name; - struct device dev; - unsignedout_epnum; - unsignedin_epnum; }; #define work_to_gadget(w) (container_of((w), struct usb_gadget, work)) -- 1.8.4.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
[PATCH v6 3/5] usb: gadget: f_fs: remove loop from I/O function
From: Michal Nazarewicz min...@mina86.com When endpoint changes (due to it being disabled or alt setting changed), mimic the action as if the change happened after the request has been queued, instead of retrying with the new endpoint. Signed-off-by: Michal Nazarewicz min...@mina86.com Cc: David Cohen david.a.co...@linux.intel.com --- drivers/usb/gadget/f_fs.c | 94 --- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 75e4b7846a8d..efa1152a4c15 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -760,73 +760,59 @@ static ssize_t ffs_epfile_io(struct file *file, ssize_t ret; int halt; - goto first_try; - do { - spin_unlock_irq(epfile-ffs-eps_lock); - mutex_unlock(epfile-mutex); + /* Are we still active? */ + if (WARN_ON(epfile-ffs-state != FFS_ACTIVE)) { + ret = -ENODEV; + goto error; + } -first_try: - /* Are we still active? */ - if (WARN_ON(epfile-ffs-state != FFS_ACTIVE)) { - ret = -ENODEV; + /* Wait for endpoint to be enabled */ + ep = epfile-ep; + if (!ep) { + if (file-f_flags O_NONBLOCK) { + ret = -EAGAIN; goto error; } - /* Wait for endpoint to be enabled */ - ep = epfile-ep; - if (!ep) { - if (file-f_flags O_NONBLOCK) { - ret = -EAGAIN; - goto error; - } - - if (wait_event_interruptible(epfile-wait, -(ep = epfile-ep))) { - ret = -EINTR; - goto error; - } - } - - /* Do we halt? */ - halt = !read == !epfile-in; - if (halt epfile-isoc) { - ret = -EINVAL; + ret = wait_event_interruptible(epfile-wait, (ep = epfile-ep)); + if (ret) { + ret = -EINTR; goto error; } + } - /* Allocate copy */ - if (!halt !data) { - data = kzalloc(len, GFP_KERNEL); - if (unlikely(!data)) - return -ENOMEM; + /* Do we halt? */ + halt = !read == !epfile-in; + if (halt epfile-isoc) { + ret = -EINVAL; + goto error; + } - if (!read - unlikely(__copy_from_user(data, buf, len))) { - ret = -EFAULT; - goto error; - } - } + /* Allocate copy */ + if (!halt) { + data = kmalloc(len, GFP_KERNEL); + if (unlikely(!data)) + return -ENOMEM; - /* We will be using request */ - ret = ffs_mutex_lock(epfile-mutex, -file-f_flags O_NONBLOCK); - if (unlikely(ret)) + if (!read unlikely(copy_from_user(data, buf, len))) { + ret = -EFAULT; goto error; + } + } - /* -* We're called from user space, we can use _irq rather then -* _irqsave -*/ - spin_lock_irq(epfile-ffs-eps_lock); + /* We will be using request */ + ret = ffs_mutex_lock(epfile-mutex, file-f_flags O_NONBLOCK); + if (unlikely(ret)) + goto error; - /* -* While we were acquiring mutex endpoint got disabled -* or changed? -*/ - } while (unlikely(epfile-ep != ep)); + spin_lock_irq(epfile-ffs-eps_lock); - /* Halt */ - if (unlikely(halt)) { + if (epfile-ep != ep) { + /* In the meantime, endpoint got disabled or changed. */ + ret = -ESHUTDOWN; + spin_unlock_irq(epfile-ffs-eps_lock); + } else if (halt) { + /* Halt */ if (likely(epfile-ep == ep) !WARN_ON(!ep-ep)) usb_ep_set_halt(ep-ep); spin_unlock_irq(epfile-ffs-eps_lock); -- 1.8.4.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
[PATCH v6 5/5] usb: dwc3: implement gadget's quirk ep_out_align_size
DWC3 requires epout to have buffer size aligned to MaxPacketSize value. This patch implements necessary quirk for it. Signed-off-by: David Cohen david.a.co...@linux.intel.com --- drivers/usb/dwc3/core.h | 6 ++ drivers/usb/dwc3/gadget.c | 23 +++ 2 files changed, 29 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index f8af8d44af85..ff42d7ddc546 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -571,6 +571,12 @@ struct dwc3_request { struct dwc3_ep *dep; u32 start_slot; + /* +* If gadget/epout, we need to pad buffer size to align with +* maxpacketsize. +*/ + size_t pad; + u8 epnum; struct dwc3_trb *trb; dma_addr_t trb_dma; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5452c0fce360..7c2d36f6ad4b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1130,6 +1130,14 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, dev_vdbg(dwc-dev, queing request %p to %s length %d\n, request, ep-name, request-length); + /* If ep out, roundup request-length to epout maxpacketsize */ + if (!(dep-number 1)) { + unsigned int aligned = roundup(request-length, + ep-desc-wMaxPacketSize); + req-pad = aligned - request-length; + request-length = aligned; + } + spin_lock_irqsave(dwc-lock, flags); ret = __dwc3_gadget_ep_queue(dep, req); spin_unlock_irqrestore(dwc-lock, flags); @@ -1173,6 +1181,15 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, } out1: + if (!(dep-number 1)) { + /* +* Sanitize request-length after pad was applied before +* queue. +*/ + request-length -= req-pad; + req-pad = 0; + } + /* giveback the request */ dwc3_gadget_giveback(dep, req, -ECONNRESET); @@ -2600,6 +2617,12 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc-gadget.name= dwc3-gadget; /* +* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize +* on ep out. +*/ + dwc-gadget.quirk_ep_out_aligned_size = true; + + /* * REVISIT: Here we should clear all pending IRQs to be * sure we're starting from a well known location. */ -- 1.8.4.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
[PATCH v5 01/17] ARM: at91: move at91_pmc.h to include/linux/clk/at91_pmc.h
This patch moves at91_pmc.h header from machine specific directory (arch/arm/mach-at91/include/mach/at91_pmc.h) to clk include directory (include/linux/clk/at91_pmc.h). We need this to avoid reference to machine specific headers in clk drivers. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Felipe Balbi ba...@ti.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/at91rm9200.c|2 +- arch/arm/mach-at91/at91sam9260.c |2 +- arch/arm/mach-at91/at91sam9261.c |2 +- arch/arm/mach-at91/at91sam9263.c |2 +- arch/arm/mach-at91/at91sam9g45.c |2 +- arch/arm/mach-at91/at91sam9n12.c |2 +- arch/arm/mach-at91/at91sam9rl.c|2 +- arch/arm/mach-at91/at91sam9x5.c|2 +- arch/arm/mach-at91/clock.c |2 +- arch/arm/mach-at91/pm.c|2 +- arch/arm/mach-at91/pm_slowclock.S |2 +- arch/arm/mach-at91/sama5d3.c |2 +- arch/arm/mach-at91/setup.c |2 +- drivers/usb/gadget/atmel_usba_udc.c|2 +- .../include/mach = include/linux/clk}/at91_pmc.h |2 +- 15 files changed, 15 insertions(+), 15 deletions(-) rename {arch/arm/mach-at91/include/mach = include/linux/clk}/at91_pmc.h (99%) diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 4aad93d..102dac6 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -12,13 +12,13 @@ #include linux/module.h #include linux/reboot.h +#include linux/clk/at91_pmc.h #include asm/irq.h #include asm/mach/arch.h #include asm/mach/map.h #include asm/system_misc.h #include mach/at91rm9200.h -#include mach/at91_pmc.h #include mach/at91_st.h #include mach/cpu.h diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 5de6074..16d7817 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -11,6 +11,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -20,7 +21,6 @@ #include mach/cpu.h #include mach/at91_dbgu.h #include mach/at91sam9260.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 0e07932..c8f5958 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -11,6 +11,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -19,7 +20,6 @@ #include asm/system_misc.h #include mach/cpu.h #include mach/at91sam9261.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 6ce7d18..cd8ad95 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -11,6 +11,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -18,7 +19,6 @@ #include asm/mach/map.h #include asm/system_misc.h #include mach/at91sam9263.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 474ee04..9794b20 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -12,13 +12,13 @@ #include linux/module.h #include linux/dma-mapping.h +#include linux/clk/at91_pmc.h #include asm/irq.h #include asm/mach/arch.h #include asm/mach/map.h #include asm/system_misc.h #include mach/at91sam9g45.h -#include mach/at91_pmc.h #include mach/cpu.h #include at91_aic.h diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index 2d895a2..deafab2 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -8,12 +8,12 @@ #include linux/module.h #include linux/dma-mapping.h +#include linux/clk/at91_pmc.h #include asm/irq.h #include asm/mach/arch.h #include asm/mach/map.h #include mach/at91sam9n12.h -#include mach/at91_pmc.h #include mach/cpu.h #include board.h diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index d4ec0d9..947da95 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -10,6 +10,7 @@ */ #include linux/module.h +#include linux/clk/at91_pmc.h #include asm/proc-fns.h #include asm/irq.h @@ -19,7 +20,6 @@ #include mach/cpu.h #include mach/at91_dbgu.h #include mach/at91sam9rl.h -#include mach/at91_pmc.h #include at91_aic.h #include at91_rstc.h diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index 916e5a1..a930d73 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++
[PATCH v5 03/17] clk: at91: add PMC base support
This patch adds at91 PMC (Power Management Controller) base support. All at91 clocks managed by the PMC unit will use this framework. This framework provides the following fonctionalities: - define a new struct at91_pmc to hide PMC internals (lock, PMC memory mapping, irq domain, ...) - read/write helper functions (pmc_read/write) to access PMC registers - lock/unlock helper functions (pmc_lock/unlock) to lock/unlock access to pmc registers - a new irq domain and its associated irq chip to request PMC specific interrupts (useful for clk prepare callbacks) The PMC unit is declared as a dt clk provider (CLK_OF_DECLARE), and every clk using this framework will declare a table of of_at91_clk_init_cb_t and add it to the pmc_clk_ids table. When the pmc dt clock setup function is called (by of_clk_init function), it triggers the registration of every supported child clk (those matching the definitions in pmc_clk_ids). This patch copies at91_pmc_base (memory mapping) and at91sam9_idle (function) from arch/arm/mach-at91/clock.c (which is not compiled if COMMON_CLK_AT91 is enabled). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/Makefile |1 + drivers/clk/at91/Makefile |5 + drivers/clk/at91/pmc.c| 306 + drivers/clk/at91/pmc.h| 61 + 4 files changed, 373 insertions(+) create mode 100644 drivers/clk/at91/Makefile create mode 100644 drivers/clk/at91/pmc.c create mode 100644 drivers/clk/at91/pmc.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7b11106..28c2678 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_ARCH_ZYNQ)+= zynq/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ +obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile new file mode 100644 index 000..1d4fb21 --- /dev/null +++ b/drivers/clk/at91/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for at91 specific clk +# + +obj-y += pmc.o diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c new file mode 100644 index 000..c8a9a63 --- /dev/null +++ b/drivers/clk/at91/pmc.c @@ -0,0 +1,306 @@ +/* + * drivers/clk/at91/pmc.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/irqchip/chained_irq.h +#include linux/irqdomain.h +#include linux/of_irq.h + +#include asm/proc-fns.h + +#include pmc.h + +void __iomem *at91_pmc_base; +EXPORT_SYMBOL_GPL(at91_pmc_base); + +void at91sam9_idle(void) +{ + at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); + cpu_do_idle(); +} + +int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range) +{ + u32 min, max; + int ret; + + ret = of_property_read_u32_index(np, propname, 0, min); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, propname, 1, max); + if (ret) + return ret; + + if (range) { + range-min = min; + range-max = max; + } + + return 0; +} +EXPORT_SYMBOL_GPL(of_at91_get_clk_range); + +static void pmc_irq_mask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IDR, 1 d-hwirq); +} + +static void pmc_irq_unmask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IER, 1 d-hwirq); +} + +static int pmc_irq_set_type(struct irq_data *d, unsigned type) +{ + if (type != IRQ_TYPE_LEVEL_HIGH) { + pr_warn(PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n); + return -EINVAL; + } + + return 0; +} + +static struct irq_chip pmc_irq = { + .name = PMC, + .irq_disable = pmc_irq_mask, + .irq_mask = pmc_irq_mask, + .irq_unmask = pmc_irq_unmask, + .irq_set_type = pmc_irq_set_type, +}; + +static struct lock_class_key pmc_lock_class; + +static int pmc_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct at91_pmc *pmc = h-host_data; + + irq_set_lockdep_class(virq, pmc_lock_class); + + irq_set_chip_and_handler(virq, pmc_irq, +
[PATCH v5 04/17] clk: at91: add PMC macro file for dt definitions
This patch adds a new macro file for PMC macros. This macro file includes the definitions of SR (status register) bit offsets and will be use to reference PMC irqs. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- include/dt-bindings/clk/at91.h | 22 ++ 1 file changed, 22 insertions(+) create mode 100644 include/dt-bindings/clk/at91.h diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clk/at91.h new file mode 100644 index 000..0b4cb99 --- /dev/null +++ b/include/dt-bindings/clk/at91.h @@ -0,0 +1,22 @@ +/* + * This header provides constants for AT91 pmc status. + * + * The constants defined in this header are being used in dts. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _DT_BINDINGS_CLK_AT91_H +#define _DT_BINDINGS_CLK_AT91_H + +#define AT91_PMC_MOSCS 0 /* MOSCS Flag */ +#define AT91_PMC_LOCKA 1 /* PLLA Lock */ +#define AT91_PMC_LOCKB 2 /* PLLB Lock */ +#define AT91_PMC_MCKRDY3 /* Master Clock */ +#define AT91_PMC_LOCKU 6 /* UPLL Lock */ +#define AT91_PMC_PCKRDY(id)(8 + (id)) /* Programmable Clock */ +#define AT91_PMC_MOSCSELS 16 /* Main Oscillator Selection */ +#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ +#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ + +#endif -- 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: [RFC PATCH 04/15] PM / Runtime: Allow drivers to intercept pm qos flag changes
On Thu, Oct 24, 2013 at 05:42:13PM -0700, Dan Williams wrote: Hi Rafael, sorry about the email mix up. On Thu, Oct 24, 2013 at 4:08 PM, Rafael J. Wysocki r...@rjwysocki.net wrote: + +What: /sys/devices/.../power/pm_qos_no_notify_flags +Date: October 2013 +Contact: Dan Williams dan.j.willi...@intel.com +Description: + The /sys/devices/.../power/pm_qos_no_notify_flags attribute is + used for determining whether the kernel is permitted to forward + changes to the the PM QoS flags (no_power_off, remote_wakeup) to + other devices it deems to be related in the system. When this + flag is set userspace is indicating that it wants exclusive + control This is aganist the way the PM QoS flags were designed. There is no exclusive control over them and user space cannot expect specific behavior when one of them is unset in sysfs. Specifically, no power off unset doesn't mean power off is required. It merely means I have no objections against powering off if that's what you decide to do. 'Exclusive control' was the wrong choice of terms. This admittedly ugly pm_qos_no_notify_flags flag would disable propagating the pm_qos_no_power_off setting to another device. The problem I am trying to solve is that deviceA can only safely be powered off depending on the state of deviceB. The kernel knows this relationship and in most cases when userspace says I don't have any objections to powering off deviceA it almost certainly means I have no objections to you coordinating poweroff of deviceA + deviceB. So your plan was to automatically change the pm_qos_no_port_poweroff flag for deviceB whenever userspace set deviceA pm_qos_no_port_poweroff? And userspace could tell the kernel not to do that with the pm_qos_no_notify_flags file? I could skip this flag and keep this knowledge internal. I.e. userspace would just need to know that clearing pm_qos_no_power_off on deviceA will not enable power off until the same setting is performed on deviceB. I do place a link from deviceA to deviceB in sysfs. That seems to be the easier solution. I suspect that what userspace will do is clear pm_qos_no_power_off for all ports marked as hardwired, and then never touch pm_qos_no_power_off again. It seems like unnecessary optimization to try to pair the two device states. Although ordering becomes trickier without notification... What situations specifically are trickier? Alternatively I could just power manage deviceB behind userspace's back when taking action on deviceA, but I think that is even more of a hack and takes away configuration ability from userspace. Yeah, I don't think that's a good idea. Sarah Sharp -- 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 v5 05/17] clk: at91: add PMC main clock
This patch adds new at91 main oscillator clock implementation using common clk framework. If rate is not provided during clock registration it is calculated using the slow clock (main clk parent in this case) rate and MCFR register. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-main.c | 189 +++ drivers/clk/at91/pmc.c |5 ++ drivers/clk/at91/pmc.h |3 + 4 files changed, 198 insertions(+) create mode 100644 drivers/clk/at91/clk-main.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 1d4fb21..44105bd 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,3 +3,4 @@ # obj-y += pmc.o +obj-y += clk-main.o diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c new file mode 100644 index 000..905ceff --- /dev/null +++ b/drivers/clk/at91/clk-main.c @@ -0,0 +1,189 @@ +/* + * drivers/clk/at91/clk-main.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/delay.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/sched.h +#include linux/wait.h + +#include pmc.h + +#define SLOW_CLOCK_FREQ32768 +#define MAINF_DIV 16 +#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \ +SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MIN_WAIT(USEC_PER_SEC / SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MAX_WAITMAINFRDY_TIMEOUT + +struct clk_main { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned long rate; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_main(hw) container_of(hw, struct clk_main, hw) + +static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) +{ + struct clk_main *clkmain = (struct clk_main *)dev_id; + + wake_up(clkmain-wait); + disable_irq_nosync(clkmain-irq); + + return IRQ_HANDLED; +} + +static int clk_main_prepare(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain-pmc; + unsigned long halt_time, timeout; + u32 tmp; + + while (!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_MOSCS)) { + enable_irq(clkmain-irq); + wait_event(clkmain-wait, + pmc_read(pmc, AT91_PMC_SR) AT91_PMC_MOSCS); + } + + if (clkmain-rate) + return 0; + + timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); + do { + halt_time = jiffies; + tmp = pmc_read(pmc, AT91_CKGR_MCFR); + if (tmp AT91_PMC_MAINRDY) + return 0; + usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); + } while (time_before(halt_time, timeout)); + + return 0; +} + +static int clk_main_is_prepared(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + + return !!(pmc_read(clkmain-pmc, AT91_PMC_SR) AT91_PMC_MOSCS); +} + +static unsigned long clk_main_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain-pmc; + + if (clkmain-rate) + return clkmain-rate; + + tmp = pmc_read(pmc, AT91_CKGR_MCFR) AT91_PMC_MAINF; + clkmain-rate = (tmp * parent_rate) / MAINF_DIV; + + return clkmain-rate; +} + +static const struct clk_ops main_ops = { + .prepare = clk_main_prepare, + .is_prepared = clk_main_is_prepared, + .recalc_rate = clk_main_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_main(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + const char *parent_name, + unsigned long rate) +{ + int ret; + struct clk_main *clkmain; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name) + return ERR_PTR(-EINVAL); + + if (!rate !parent_name) + return ERR_PTR(-EINVAL); + + clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); + if (!clkmain) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = main_ops; + init.parent_names = parent_name ? parent_name : NULL; +
[PATCH v5 08/17] clk: at91: add PMC system clocks
This patch adds new at91 system clock implementation using common clk framework. Some peripherals need to enable a system clock in order to work properly. Each system clock is given an id based on the bit position in SCER/SCDR registers. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-system.c | 137 + drivers/clk/at91/pmc.c|5 ++ drivers/clk/at91/pmc.h|3 + 4 files changed, 146 insertions(+) create mode 100644 drivers/clk/at91/clk-system.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index e28fb2b..c2b7068 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,3 +4,4 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o +obj-y += clk-system.o diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c new file mode 100644 index 000..1c086f4 --- /dev/null +++ b/drivers/clk/at91/clk-system.c @@ -0,0 +1,137 @@ +/* + * drivers/clk/at91/clk-system.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define SYSTEM_MAX_ID 31 + +#define SYSTEM_MAX_NAME_SZ 32 + +#define to_clk_system(hw) container_of(hw, struct clk_system, hw) +struct clk_system { + struct clk_hw hw; + struct at91_pmc *pmc; + u8 id; +}; + +static int clk_system_enable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys-pmc; + + pmc_write(pmc, AT91_PMC_SCER, 1 sys-id); + return 0; +} + +static void clk_system_disable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys-pmc; + + pmc_write(pmc, AT91_PMC_SCDR, 1 sys-id); +} + +static int clk_system_is_enabled(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys-pmc; + + return !!(pmc_read(pmc, AT91_PMC_SCSR) (1 sys-id)); +} + +static const struct clk_ops system_ops = { + .enable = clk_system_enable, + .disable = clk_system_disable, + .is_enabled = clk_system_is_enabled, +}; + +static struct clk * __init +at91_clk_register_system(struct at91_pmc *pmc, const char *name, +const char *parent_name, u8 id) +{ + struct clk_system *sys; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!parent_name || id SYSTEM_MAX_ID) + return ERR_PTR(-EINVAL); + + sys = kzalloc(sizeof(*sys), GFP_KERNEL); + if (!sys) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = system_ops; + init.parent_names = parent_name; + init.num_parents = 1; + /* +* CLK_IGNORE_UNUSED is used to avoid ddrck switch off. +* TODO : we should implement a driver supporting at91 ddr controller +* (see drivers/memory) which would request and enable the ddrck clock. +* When this is done we will be able to remove CLK_IGNORE_UNUSED flag. +*/ + init.flags = CLK_IGNORE_UNUSED; + + sys-id = id; + sys-hw.init = init; + sys-pmc = pmc; + + clk = clk_register(NULL, sys-hw); + if (IS_ERR(clk)) + kfree(sys); + + return clk; +} + +static void __init +of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) +{ + int num; + u32 id; + struct clk *clk; + const char *name; + struct device_node *sysclknp; + const char *parent_name; + + num = of_get_child_count(np); + if (num (SYSTEM_MAX_ID + 1)) + return; + + for_each_child_of_node(np, sysclknp) { + if (of_property_read_u32(sysclknp, reg, id)) + continue; + + if (of_property_read_string(np, clock-output-names, name)) + name = sysclknp-name; + + parent_name = of_clk_get_parent_name(sysclknp, 0); + + clk = at91_clk_register_system(pmc, name, parent_name, id); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); + } +} + +void __init of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_sys_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c
[PATCH v5 09/17] clk: at91: add PMC peripheral clocks
This patch adds new at91 peripheral clock implementation using common clk framework. Almost all peripherals provided by at91 SoCs need a clock to work properly. This clock is enabled/disabled using PCER/PCDR resgisters. Each peripheral is given an id (see atmel's datasheets) which is used to define and reference peripheral clocks. Some new SoCs (at91sam9x5 and sama5d3) provide a new register (PCR) where you can configure the peripheral clock as a division of the master clock. This will help reducing the peripherals power comsumption. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |2 +- drivers/clk/at91/clk-peripheral.c | 412 + drivers/clk/at91/pmc.c|9 + drivers/clk/at91/pmc.h|5 + 4 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-peripheral.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index c2b7068..04deba3 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,4 +4,4 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o -obj-y += clk-system.o +obj-y += clk-system.o clk-peripheral.o diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c new file mode 100644 index 000..15c9518 --- /dev/null +++ b/drivers/clk/at91/clk-peripheral.c @@ -0,0 +1,412 @@ +/* + * drivers/clk/at91/clk-peripheral.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define PERIPHERAL_MAX 64 + +#define PERIPHERAL_AT91RM9200 0 +#define PERIPHERAL_AT91SAM9X5 1 + +#define PERIPHERAL_ID_MIN 2 +#define PERIPHERAL_ID_MAX 31 +#define PERIPHERAL_MASK(id)(1 ((id) PERIPHERAL_ID_MAX)) + +#define PERIPHERAL_RSHIFT_MASK 0x3 +#define PERIPHERAL_RSHIFT(val) (((val) 16) PERIPHERAL_RSHIFT_MASK) + +#define PERIPHERAL_MAX_SHIFT 4 + +struct clk_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 id; +}; + +#define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw) + +struct clk_sam9x5_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + struct clk_range range; + u32 id; + u32 div; + bool auto_div; +}; + +#define to_clk_sam9x5_peripheral(hw) \ + container_of(hw, struct clk_sam9x5_peripheral, hw) + +static int clk_peripheral_enable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph-pmc; + int offset = AT91_PMC_PCER; + u32 id = periph-id; + + if (id PERIPHERAL_ID_MIN) + return 0; + if (id PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCER1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); + return 0; +} + +static void clk_peripheral_disable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph-pmc; + int offset = AT91_PMC_PCDR; + u32 id = periph-id; + + if (id PERIPHERAL_ID_MIN) + return; + if (id PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCDR1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); +} + +static int clk_peripheral_is_enabled(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph-pmc; + int offset = AT91_PMC_PCSR; + u32 id = periph-id; + + if (id PERIPHERAL_ID_MIN) + return 1; + if (id PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCSR1; + return !!(pmc_read(pmc, offset) PERIPHERAL_MASK(id)); +} + +static const struct clk_ops peripheral_ops = { + .enable = clk_peripheral_enable, + .disable = clk_peripheral_disable, + .is_enabled = clk_peripheral_is_enabled, +}; + +static struct clk * __init +at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, +const char *parent_name, u32 id) +{ + struct clk_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name || !parent_name || id PERIPHERAL_ID_MAX) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); + if (!periph) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = peripheral_ops; + init.parent_names = (parent_name ? parent_name :
RE: [PATCHv2 2/2] check quirk to pad epout buf size when not aligned to maxpacketsize
From: linux-usb-ow...@vger.kernel.org [mailto:linux-usb-ow...@vger.kernel.org] On Behalf Of Alan Stern Sent: Tuesday, November 12, 2013 7:51 AM On Mon, 11 Nov 2013, David Cohen wrote: Hi Alan, Michal, On 11/11/2013 01:09 PM, Michal Nazarewicz wrote: On Mon, Nov 11 2013, Alan Stern wrote: On Mon, 11 Nov 2013, Michal Nazarewicz wrote: Check gadget.quirk_ep_out_aligned_size to decide if buffer size requires to be aligned to maxpacketsize of an out endpoint. ffs_epfile_io() needs to pad epout buffer to match above condition if quirk is found. Signed-off-by: Michal Nazarewicz min...@mina86.com I think this is still wrong. @@ -824,7 +832,7 @@ static ssize_t ffs_epfile_io(struct file *file, req-context = done; req-complete = ffs_epfile_io_complete; req-buf = data; - req-length = len; + req-length = data_len; IIUC, req-length should still be set to len, not to data_len. I misunderstood the first time I read it: In order to avoid DWC3 to stall, we need to update req-length (this is the most important fix). kmalloc() is updated too to prevent USB controller to overflow buffer boundaries. Here I disagree. If the DWC3 hardware stalls, it is up to the DWC3 UDC driver to fix it. Gadget drivers should not have to worry. Most especially, gadget drivers should not lie about a request length. The whole point of this quirk is to lie to the DWC3 driver. The quirk is only enabled for the DWC3 driver. If the UDC driver decides to round up req-length before sending it to the hardware, that's okay. Not really. If the DWC3 driver unconditionally rounds up req-length, then in the case where the buffer has not been expanded to a multiple of maxpacket, by this quirk or otherwise, there is the potential to write beyond the end of the allocation. If we do what you suggest, then all the gadgets will have to be audited to make sure an OUT buffer with a non-aligned length is never passed to the DWC3 driver. I still think that's the best solution anyway. Just make that the rule, and then there is no need for this quirk at all. And there is no need to round up req-length in the DWC3 driver either. But req-length should be set to len, not data_len. According to gadget.h: @buf: Buffer used for data @length: Length of that data So why shouldn't length be the length of the allocated data buffer? Remember, this is for the OUT direction only, so the host has control over how much data is actually sent. You could even argue that an OUT data buffer should always be a multiple of the max packet size, given how USB works. And if the hardware receives more than len bytes of data, the UDC driver should set req-status to -EOVERFLOW. That would be nice, but I don't see how to accomplish that given the above. -- Paul -- 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: xhci ring expansion
On Thu, Oct 31, 2013 at 04:16:14PM -, David Laight wrote: Code was recently added to the xhci driver to dynamically add extra ring segments if there is insufficient space for all the fragments of the URB being sent. ISTM that it would be better to just queue the URB (on the ring) and process it when space becomes available. Hmm, better why? I'm reluctant to touch code that Just Works (TM). Especially anything having do with the xHCI ring code, since it's quite complex. This wouldn't solve the problem of pathologically badly fragmented, or very long URB, but there are simpler solutions to that. I believe that very long bulk transfers can be split into separate TD on USB block boundaries - so they can be safely added to the ring in several pieces. No, that's not a good idea. Think about the case where the device driver sets up an IN transfer to receive a specific amount of data from the device. The device can choose to send less data, resulting in a short packet TD completion event. If you queue the URB as one TD, when the short packet occurs, the host returns the short status, and stops requesting any further packets from the device. It then goes on to process the next TD in the ring. Now, assume you queue the URB as multiple TDs. Say you split the URB into five TDs, and the short packet occurs on TD three. The host will return a short packet completion event, and then go on to request data from the device for TDs four and five. This is not what you want, because it changes the bus behavior. I don't know if any other data type is allowed to exceed the block length? Badly fragmented URB are probably best copied into a linear buffer. This would make the code a lot simpler, especially since the tx setup could be started if there were a 'reasonable' number of free entries in the TRB ring without having to calculate the actual number needed (and Additionally it would make it possible to ensure that LINK TRB only happen on the appropriate boundary. This might require some fragments be copied to a linear buffer. If this is a reasonable idea I'll volunteer to do the changes. We are seeing some issues with the xhci driver, and parts of it are just to contorted! The code is complex, especially the interaction between the code to queue to the xHCI rings, the URB cancellation code, and the command ring cancellation code. Any big changes like this would be bound to introduce new bugs. Frankly, since these are your first kernel patches, I can't trust any big sweeping changes you make unless I can throughly understand them. That's just a fact about being a kernel maintainer; I have to understand the code that gets contributed because the contributor is highly likely to disappear, leaving me to fix bugs in their code years later. So, I would recommend you work on small fixes and earn my trust before making big sweeping changes. Let's get the scatter gather issue fixed before you completely re-architect the xHCI driver, okay? :) Sarah Sharp -- 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: [PATCHv2 2/2] check quirk to pad epout buf size when not aligned to maxpacketsize
Hi Paul, On 11/12/2013 03:09 PM, Paul Zimmerman wrote: From: linux-usb-ow...@vger.kernel.org [mailto:linux-usb-ow...@vger.kernel.org] On Behalf Of Alan Stern Sent: Tuesday, November 12, 2013 7:51 AM On Mon, 11 Nov 2013, David Cohen wrote: Hi Alan, Michal, On 11/11/2013 01:09 PM, Michal Nazarewicz wrote: On Mon, Nov 11 2013, Alan Stern wrote: On Mon, 11 Nov 2013, Michal Nazarewicz wrote: Check gadget.quirk_ep_out_aligned_size to decide if buffer size requires to be aligned to maxpacketsize of an out endpoint. ffs_epfile_io() needs to pad epout buffer to match above condition if quirk is found. Signed-off-by: Michal Nazarewicz min...@mina86.com I think this is still wrong. @@ -824,7 +832,7 @@ static ssize_t ffs_epfile_io(struct file *file, req-context = done; req-complete = ffs_epfile_io_complete; req-buf = data; - req-length = len; + req-length = data_len; IIUC, req-length should still be set to len, not to data_len. I misunderstood the first time I read it: In order to avoid DWC3 to stall, we need to update req-length (this is the most important fix). kmalloc() is updated too to prevent USB controller to overflow buffer boundaries. Here I disagree. If the DWC3 hardware stalls, it is up to the DWC3 UDC driver to fix it. Gadget drivers should not have to worry. Most especially, gadget drivers should not lie about a request length. The whole point of this quirk is to lie to the DWC3 driver. The quirk is only enabled for the DWC3 driver. If the UDC driver decides to round up req-length before sending it to the hardware, that's okay. Not really. If the DWC3 driver unconditionally rounds up req-length, then in the case where the buffer has not been expanded to a multiple of maxpacket, by this quirk or otherwise, there is the potential to write beyond the end of the allocation. If we do what you suggest, then all the gadgets will have to be audited to make sure an OUT buffer with a non-aligned length is never passed to the DWC3 driver. I was really convinced about not updating rep-length was a better idea until I read this argument of yours: with this approach buffer overflow can silently happen. I still think that's the best solution anyway. Just make that the rule, and then there is no need for this quirk at all. And there is no need to round up req-length in the DWC3 driver either. I'd have nothing against that, but I'm not sure how it would affect other environments, given embedded environments are pretty sensitive to memory consumption (and performance). But req-length should be set to len, not data_len. According to gadget.h: @buf: Buffer used for data @length: Length of that data So why shouldn't length be the length of the allocated data buffer? Remember, this is for the OUT direction only, so the host has control over how much data is actually sent. You could even argue that an OUT data buffer should always be a multiple of the max packet size, given how USB works. How about something like this, to let USB controllers to know about whole allocated memory and avoid hidden overflows. Does that make sense to you? diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 25a5007f92e3..973b57b709ab 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -31,13 +31,16 @@ struct usb_ep; * struct usb_request - describes one i/o request * @buf: Buffer used for data. Always provide this; some controllers * only use PIO, or don't use DMA for some endpoints. + * @length: Length of that data + * @buf_pad: Some USB controllers may need to pad buffer size due to alignment + * constraints. This keeps track of how much memory was allocated to @buf + * in addition to @length. * @dma: DMA address corresponding to 'buf'. If you don't set this * field, and the usb controller needs one, it is responsible * for mapping and unmapping the buffer. * @sg: a scatterlist for SG-capable controllers. * @num_sgs: number of SG entries * @num_mapped_sgs: number of SG entries mapped to DMA (internal) - * @length: Length of that data * @stream_id: The stream id, when USB3.0 bulk streams are being used * @no_interrupt: If true, hints that no completion irq is needed. * Helpful sometimes with deep request queues that are handled @@ -91,6 +94,7 @@ struct usb_ep; struct usb_request { void*buf; unsignedlength; + unsignedbuf_pad; dma_addr_t dma; struct scatterlist *sg; Br, David Cohen -- 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: [PATCHv2 2/2] check quirk to pad epout buf size when not aligned to maxpacketsize
From: David Cohen [mailto:david.a.co...@linux.intel.com] Sent: Tuesday, November 12, 2013 3:44 PM On 11/12/2013 03:09 PM, Paul Zimmerman wrote: From: linux-usb-ow...@vger.kernel.org [mailto:linux-usb-ow...@vger.kernel.org] On Behalf Of Alan Stern Sent: Tuesday, November 12, 2013 7:51 AM On Mon, 11 Nov 2013, David Cohen wrote: In order to avoid DWC3 to stall, we need to update req-length (this is the most important fix). kmalloc() is updated too to prevent USB controller to overflow buffer boundaries. Here I disagree. If the DWC3 hardware stalls, it is up to the DWC3 UDC driver to fix it. Gadget drivers should not have to worry. Most especially, gadget drivers should not lie about a request length. The whole point of this quirk is to lie to the DWC3 driver. The quirk is only enabled for the DWC3 driver. If the UDC driver decides to round up req-length before sending it to the hardware, that's okay. Not really. If the DWC3 driver unconditionally rounds up req-length, then in the case where the buffer has not been expanded to a multiple of maxpacket, by this quirk or otherwise, there is the potential to write beyond the end of the allocation. If we do what you suggest, then all the gadgets will have to be audited to make sure an OUT buffer with a non-aligned length is never passed to the DWC3 driver. I was really convinced about not updating rep-length was a better idea until I read this argument of yours: with this approach buffer overflow can silently happen. I still think that's the best solution anyway. Just make that the rule, and then there is no need for this quirk at all. And there is no need to round up req-length in the DWC3 driver either. I'd have nothing against that, but I'm not sure how it would affect other environments, given embedded environments are pretty sensitive to memory consumption (and performance). There would be no performance impact. The memory impact would be less than 1024 bytes per OUT ep (worst case), and most gadget devices only have a couple of OUT eps. I don't think it's a problem. But req-length should be set to len, not data_len. According to gadget.h: @buf: Buffer used for data @length: Length of that data So why shouldn't length be the length of the allocated data buffer? Remember, this is for the OUT direction only, so the host has control over how much data is actually sent. You could even argue that an OUT data buffer should always be a multiple of the max packet size, given how USB works. How about something like this, to let USB controllers to know about whole allocated memory and avoid hidden overflows. Does that make sense to you? diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 25a5007f92e3..973b57b709ab 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -31,13 +31,16 @@ struct usb_ep; * struct usb_request - describes one i/o request * @buf: Buffer used for data. Always provide this; some controllers * only use PIO, or don't use DMA for some endpoints. + * @length: Length of that data + * @buf_pad: Some USB controllers may need to pad buffer size due to alignment + * constraints. This keeps track of how much memory was allocated to @buf + * in addition to @length. * @dma: DMA address corresponding to 'buf'. If you don't set this * field, and the usb controller needs one, it is responsible * for mapping and unmapping the buffer. * @sg: a scatterlist for SG-capable controllers. * @num_sgs: number of SG entries * @num_mapped_sgs: number of SG entries mapped to DMA (internal) - * @length: Length of that data * @stream_id: The stream id, when USB3.0 bulk streams are being used * @no_interrupt: If true, hints that no completion irq is needed. * Helpful sometimes with deep request queues that are handled @@ -91,6 +94,7 @@ struct usb_ep; struct usb_request { void*buf; unsignedlength; + unsignedbuf_pad; dma_addr_t dma; struct scatterlist *sg; Yes, I think that would work. But you only need 11 bits or so for buf_pad, so make it 'unsigned buf_pad:11 and move it down with the rest of the bitfields. And you could also report -EOVERFLOW in the DWC3 driver, as Alan suggested, if the received data is more than 'length'. -- Paul -- 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] usbnet: fix race condition caused spinlock bad magic issue
From: wang, biao biao.w...@intel.com Date: Mon, 11 Nov 2013 10:23:40 +0800 Subject: [PATCH] usbnet: fix race condition caused spinlock bad magic issue 1, there is race between usbnet_terminate_urbs and usbnet_bh, when unlink_wakeup used in usbnet_bh, it may be already freed and used by other function as unlink_wakeup was a local var on stack. for example: cpu 0: cpu 1: usb_suspend_both -usbnet_suspend usbnet_bh -usbnet_terminate_urbs -__wake_up -_raw_spin_unlock_irqrestore -do_raw_spin_unlock -spin_bug when usbnet_terminate_urbs complete execution and memory of unlink_wakeup was used by other function, then usbnet_bh may still use it. 2, for the same reason,dev-wait should be judged again before use it, as between the judge point(if(dev-wait)) and use point(wakeup(dev-wait)), the dev-wait may be set NULL by another cpu. for issue 1, declare unlink_wakeup in global section instead of on stack. for issue 2, use a temporary local var to keep the value of dev-wait in stack and judge it before using. Signed-off-by: wang, biao biao.w...@intel.com Acked-by: Ingo Molnar mingo.kernel@gmail.com Acked-by: Oliver Neukum oneu...@suse.de Acked-by: Zhang, Di di.zh...@intel.com --- drivers/net/usb/usbnet.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 90a429b..0603ef6 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -86,6 +86,7 @@ static const char driver_name [] = usbnet; /* use ethtool to change the level for any given device */ static int msg_level = -1; +static DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); module_param (msg_level, int, 0); MODULE_PARM_DESC (msg_level, Override default message level); @@ -761,7 +762,6 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs); // precondition: never called in_interrupt static void usbnet_terminate_urbs(struct usbnet *dev) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup); DECLARE_WAITQUEUE(wait, current); int temp; @@ -1449,7 +1449,9 @@ static void usbnet_bh (unsigned long param) // waiting for all pending urbs to complete? if (dev-wait) { if ((dev-txq.qlen + dev-rxq.qlen + dev-done.qlen) == 0) { - wake_up (dev-wait); + wait_queue_head_t *wait_d = dev-wait; + if (wait_d) + wake_up(wait_d); } // or are we maybe short a few urbs? -- 1.7.0.4 -- 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: xhci: Add 2nd memory barrier to giveback_first_trb()
On Tue, Nov 12, 2013 at 01:58:05PM -, David Laight wrote: There needs to be a wmb() barrier between the write to the cycle bit in the first TRB and the write to the doorbell register. Since it isn't needed in the other places the doobell is rung (because the ring contents haven't been changed) add it to giveback_first_trb() rather than somewhere later. Signed-off-by: David Laight david.lai...@aculab.com --- This patch will only apply cleanly if my earlier patch that affects the previous line has also been applied. drivers/usb/host/xhci-ring.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 35dfed0..8bce4c3 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3136,6 +3136,7 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, */ wmb(); start_trb-field[3] ^= cpu_to_le32(TRB_CYCLE); + wmb(); I don't understand, why is this needed? field[] isn't being used elsewhere at this point in time, is it? When adding barriers, you need to also add a big comment as to exactly why this is needed, in the code itself, which this patch does not do, so we can't take it (well, I will not take it, Sarah might, but then I'll complain to her...) 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 v5 10/17] clk: at91: add peripheral clk macros for peripheral clk dt bindings
This patch adds the peripheral divisors macros (for sam9x5 compatible IPs) which will be used by peripheral clk dt definitions. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- include/dt-bindings/clk/at91.h |6 ++ 1 file changed, 6 insertions(+) diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clk/at91.h index 0b4cb99..a3b07ca 100644 --- a/include/dt-bindings/clk/at91.h +++ b/include/dt-bindings/clk/at91.h @@ -19,4 +19,10 @@ #define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ #define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ +/* sam9x5 peripheral divisors */ +#define AT91SAM9X5_PERIPH_CLK_DIV1 0 +#define AT91SAM9X5_PERIPH_CLK_DIV2 1 +#define AT91SAM9X5_PERIPH_CLK_DIV4 2 +#define AT91SAM9X5_PERIPH_CLK_DIV8 3 + #endif -- 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 v5 11/17] clk: at91: add PMC programmable clocks
This patch adds new at91 programmable clocks implementation using common clk framework. A programmable clock is a clock which can be exported on a given pin to clock external devices. Each programmable clock is given an id (from 0 to 8). The number of available programmable clocks depends on the SoC you're using. Programmable clock driver only implements the clock setting (clock rate and parent setting). It must be chained to a system clock in order to enable/disable the generated clock. The PCKX pins used to output the clock signals must be assigned to the appropriate peripheral (see atmel's datasheets). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/clk/at91/Makefile |2 + drivers/clk/at91/clk-programmable.c | 368 +++ drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h |9 + 4 files changed, 394 insertions(+) create mode 100644 drivers/clk/at91/clk-programmable.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 04deba3..3873b62 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -5,3 +5,5 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o + +obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c new file mode 100644 index 000..1daa05f --- /dev/null +++ b/drivers/clk/at91/clk-programmable.c @@ -0,0 +1,368 @@ +/* + * drivers/clk/at91/clk-programmable.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/wait.h +#include linux/sched.h +#include linux/interrupt.h +#include linux/irq.h + +#include pmc.h + +#define PROG_SOURCE_MAX5 +#define PROG_ID_MAX7 + +#define PROG_STATUS_MASK(id) (1 ((id) + 8)) +#define PROG_PRES_MASK 0x7 +#define PROG_MAX_RM9200_CSS3 + +struct clk_programmable_layout { + u8 pres_shift; + u8 css_mask; + u8 have_slck_mck; +}; + +struct clk_programmable { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 css; + u8 pres; + u8 slckmck; + const struct clk_programmable_layout *layout; +}; + +#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) + + +static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id) +{ + struct clk_programmable *prog = (struct clk_programmable *)dev_id; + + wake_up(prog-wait); + + return IRQ_HANDLED; +} + +static int clk_programmable_prepare(struct clk_hw *hw) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog-pmc; + const struct clk_programmable_layout *layout = prog-layout; + u8 id = prog-id; + u32 mask = PROG_STATUS_MASK(id); + + tmp = prog-css | (prog-pres layout-pres_shift); + if (layout-have_slck_mck prog-slckmck) + tmp |= AT91_PMC_CSSMCK_MCK; + + pmc_write(pmc, AT91_PMC_PCKR(id), tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) mask)) + wait_event(prog-wait, pmc_read(pmc, AT91_PMC_SR) mask); + + return 0; +} + +static int clk_programmable_is_ready(struct clk_hw *hw) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog-pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_PCKR(prog-id)); +} + +static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog-pmc; + const struct clk_programmable_layout *layout = prog-layout; + + tmp = pmc_read(pmc, AT91_PMC_PCKR(prog-id)); + prog-pres = (tmp layout-pres_shift) PROG_PRES_MASK; + + return parent_rate prog-pres; +} + +static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long best_rate = *parent_rate; + unsigned long best_diff; + unsigned long new_diff; + unsigned long cur_rate; + int shift = shift; + + if (rate *parent_rate) + return *parent_rate; + else +
[PATCH v5 12/17] clk: at91: add PMC utmi clock
This adds new at91 utmi clock implementation using common clk framework. This clock is a pll with a fixed factor (x40). It is used as a source for usb clock. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig |7 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-utmi.c | 162 +++ drivers/clk/at91/pmc.c |7 ++ drivers/clk/at91/pmc.h |5 ++ 5 files changed, 182 insertions(+) create mode 100644 drivers/clk/at91/clk-utmi.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 85b53a4..6ad37da 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -1,5 +1,8 @@ if ARCH_AT91 +config HAVE_AT91_UTMI + bool + config HAVE_AT91_DBGU0 bool @@ -78,6 +81,7 @@ config SOC_SAMA5D3 select HAVE_FB_ATMEL select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -124,6 +128,7 @@ config SOC_AT91SAM9RL select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI config SOC_AT91SAM9G45 bool AT91SAM9G45 or AT91SAM9M10 families @@ -131,6 +136,7 @@ config SOC_AT91SAM9G45 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -141,6 +147,7 @@ config SOC_AT91SAM9X5 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 3873b62..a824883 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -7,3 +7,4 @@ obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o +obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c new file mode 100644 index 000..9a133df --- /dev/null +++ b/drivers/clk/at91/clk-utmi.c @@ -0,0 +1,162 @@ +/* + * drivers/clk/at91/clk-utmi.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/of.h +#include linux/of_address.h +#include linux/of_irq.h +#include linux/io.h +#include linux/sched.h +#include linux/wait.h + +#include pmc.h + +#define UTMI_FIXED_MUL 40 + +struct clk_utmi { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) + +static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) +{ + struct clk_utmi *utmi = (struct clk_utmi *)dev_id; + + wake_up(utmi-wait); + disable_irq_nosync(utmi-irq); + + return IRQ_HANDLED; +} + +static int clk_utmi_prepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi-pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | + AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_LOCKU)) { + enable_irq(utmi-irq); + wait_event(utmi-wait, + pmc_read(pmc, AT91_PMC_SR) AT91_PMC_LOCKU); + } + + return 0; +} + +static int clk_utmi_is_ready(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi-pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) AT91_PMC_LOCKU); +} + +static void clk_utmi_disable(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi-pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) ~AT91_PMC_UPLLEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); +} + +static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + /* UTMI clk is a fixed
[PATCH v5 13/17] clk: at91: add PMC usb clock
This patch adds new at91 usb clock implementation using common clk framework. This clock is used to clock usb ports (ohci, ehci and udc). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig | 11 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-usb.c | 400 drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h |9 + 5 files changed, 436 insertions(+) create mode 100644 drivers/clk/at91/clk-usb.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 6ad37da..b76dc4c 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -3,6 +3,9 @@ if ARCH_AT91 config HAVE_AT91_UTMI bool +config HAVE_AT91_USB_CLK + bool + config HAVE_AT91_DBGU0 bool @@ -82,6 +85,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -96,12 +100,14 @@ config SOC_AT91RM9200 select MULTI_IRQ_HANDLER select SPARSE_IRQ select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9260 bool AT91SAM9260, AT91SAM9XE or AT91SAM9G20 select HAVE_AT91_DBGU0 select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -112,6 +118,7 @@ config SOC_AT91SAM9261 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -121,6 +128,7 @@ config SOC_AT91SAM9263 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9RL bool AT91SAM9RL @@ -137,6 +145,7 @@ config SOC_AT91SAM9G45 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -148,6 +157,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -161,6 +171,7 @@ config SOC_AT91SAM9N12 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index a824883..61db058 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -8,3 +8,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000..0454555 --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,400 @@ +/* + * drivers/clk/at91/clk-usb.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define USB_SOURCE_MAX 2 + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_MAX_DIV 0xf + +#define RM9200_USB_DIV_SHIFT 28 +#define RM9200_USB_DIV_TAB_SIZE4 + +struct at91sam9x5_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_usb(hw) \ + container_of(hw, struct at91sam9x5_clk_usb, hw) + +struct at91rm9200_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 divisors[4]; +}; + +#define to_at91rm9200_clk_usb(hw) \ + container_of(hw, struct at91rm9200_clk_usb, hw) + +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 usbdiv; + struct
[PATCH v5 14/17] clk: at91: add PMC smd clock
This patch adds at91 smd (Soft Modem) clock implementation using common clk framework. Not used by any driver right now. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/Kconfig |5 ++ drivers/clk/at91/Makefile |1 + drivers/clk/at91/clk-smd.c | 173 drivers/clk/at91/pmc.c |7 ++ drivers/clk/at91/pmc.h |5 ++ 5 files changed, 191 insertions(+) create mode 100644 drivers/clk/at91/clk-smd.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b76dc4c..97033f7 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -39,6 +39,9 @@ config AT91_SAM9G45_RESET config AT91_SAM9_TIME bool +config HAVE_AT91_SMD + bool + config SOC_AT91SAM9 bool select AT91_SAM9_TIME @@ -85,6 +88,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. @@ -157,6 +161,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 61db058..0e92b71 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -9,3 +9,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o obj-$(CONFIG_HAVE_AT91_USB_CLK)+= clk-usb.o +obj-$(CONFIG_HAVE_AT91_SMD)+= clk-smd.o diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c new file mode 100644 index 000..9f3fa39 --- /dev/null +++ b/drivers/clk/at91/clk-smd.c @@ -0,0 +1,173 @@ +/* + * drivers/clk/at91/clk-smd.c + * + * Copyright (C) 2013 Boris BREZILLON b.brezil...@overkiz.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include linux/clk-provider.h +#include linux/clkdev.h +#include linux/clk/at91_pmc.h +#include linux/of.h +#include linux/of_address.h +#include linux/io.h + +#include pmc.h + +#define SMD_SOURCE_MAX 2 + +#define SMD_DIV_SHIFT 8 +#define SMD_MAX_DIV0xf + +struct at91sam9x5_clk_smd { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_smd(hw) \ + container_of(hw, struct at91sam9x5_clk_smd, hw) + +static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 smddiv; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + tmp = pmc_read(pmc, AT91_PMC_SMD); + smddiv = (tmp AT91_PMC_SMD_DIV) SMD_DIV_SHIFT; + return parent_rate / (smddiv + 1); +} + +static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate = *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div SMD_MAX_DIV) + return *parent_rate / (SMD_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + if (index 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) ~AT91_PMC_SMDS; + if (index) + tmp |= AT91_PMC_SMDS; + pmc_write(pmc, AT91_PMC_SMD, tmp); + return 0; +} + +static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + + return pmc_read(pmc, AT91_PMC_SMD) AT91_PMC_SMDS; +} + +static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd-pmc; + unsigned long div = parent_rate / rate; + +
[PATCH v5 15/17] dt: binding: add at91 clks dt bindings documentation
This patch adds new at91 clks dt bindings documentation. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- .../devicetree/bindings/clock/at91-clock.txt | 339 1 file changed, 339 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/at91-clock.txt diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt new file mode 100644 index 000..cd5e239 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt @@ -0,0 +1,339 @@ +Device Tree Clock bindings for arch-at91 + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be one of the following: + atmel,at91rm9200-pmc or + atmel,at91sam9g45-pmc or + atmel,at91sam9n12-pmc or + atmel,at91sam9x5-pmc or + atmel,sama5d3-pmc: + at91 PMC (Power Management Controller) + All at91 specific clocks (clocks defined below) must be child + node of the PMC node. + + atmel,at91rm9200-clk-main: + at91 main oscillator + + atmel,at91rm9200-clk-master or + atmel,at91sam9x5-clk-master: + at91 master clock + + atmel,at91sam9x5-clk-peripheral or + atmel,at91rm9200-clk-peripheral: + at91 peripheral clocks + + atmel,at91rm9200-clk-pll or + atmel,at91sam9g45-clk-pll or + atmel,at91sam9g20-clk-pllb or + atmel,sama5d3-clk-pll: + at91 pll clocks + + atmel,at91sam9x5-clk-plldiv: + at91 plla divisor + + atmel,at91rm9200-clk-programmable or + atmel,at91sam9g45-clk-programmable or + atmel,at91sam9x5-clk-programmable: + at91 programmable clocks + + atmel,at91sam9x5-clk-smd: + at91 SMD (Soft Modem) clock + + atmel,at91rm9200-clk-system: + at91 system clocks + + atmel,at91rm9200-clk-usb or + atmel,at91sam9x5-clk-usb or + atmel,at91sam9n12-clk-usb: + at91 usb clock + + atmel,at91sam9x5-clk-utmi: + at91 utmi clock + +Required properties for PMC node: +- reg : defines the IO memory reserved for the PMC. +- #size-cells : shall be 0 (reg is used to encode clk id). +- #address-cells : shall be 1 (reg is used to encode clk id). +- interrupts : shall be set to PMC interrupt line. +- interrupt-controller : tell that the PMC is an interrupt controller. +- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id, + and reflect the bit position in the PMC_ER/DR/SR registers. + You can use the dt macros defined in dt-bindings/clk/at91.h. + 0 (AT91_PMC_MOSCS) - main oscillator ready + 1 (AT91_PMC_LOCKA) - PLL A ready + 2 (AT91_PMC_LOCKB) - PLL B ready + 3 (AT91_PMC_MCKRDY) - master clock ready + 6 (AT91_PMC_LOCKU) - UTMI PLL clock ready + 8 .. 15 (AT91_PMC_PCKRDY(id)) - programmable clock ready + 16 (AT91_PMC_MOSCSELS) - main oscillator selected + 17 (AT91_PMC_MOSCRCS) - RC main oscillator stabilized + 18 (AT91_PMC_CFDEV) - clock failure detected + +For example: + pmc: pmc@fc00 { + compatible = atmel,sama5d3-pmc; + interrupts = 1 4 7; + interrupt-controller; + #interrupt-cells = 2; + #size-cells = 0; + #address-cells = 1; + + /* put at91 clocks here */ + }; + +Required properties for main clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to 0. +- #clock-cells : from common clock binding; shall be set to 0. +- clocks (optional if clock-frequency is provided) : shall be the slow clock + phandle. This clock is used to calculate the main clock rate if + clock-frequency is not provided. +- clock-frequency : the main oscillator frequency.Prefer the use of + clock-frequency over automatic clock rate calculation. + +For example: + main: mainck { + compatible = atmel,at91rm9200-clk-main; + interrupt-parent = pmc; + interrupts = 0; + #clock-cells = 0; + clocks = ck32k; + clock-frequency = 18432000; + }; + +Required properties for master clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to 3. +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the master clock sources (see atmel datasheet) phandles. + e.g. ck32k, main, plla, pllb. +- atmel,clk-output-range : minimum and maximum clock frequency (two u32 + fields). + e.g. output = 0 13300; = 0 to 133MHz. +- atmel,clk-divisors : master clock divisors table (four u32 fields). + 0 = reserved
[PATCH v5 17/17] ARM: at91: add new compatible strings for pmc driver
This patch adds new compatible string for PMC node to prepare the transition to common clk. These compatible string come from pmc driver in clk subsystem and are needed to provide new device tree compatibility with old at91 clks (device tree using common clks will use the new compatible strings). Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/clock.c |5 + 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 5f02aea..72b2579 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -884,6 +884,11 @@ static int __init at91_pmc_init(unsigned long main_clock) #if defined(CONFIG_OF) static struct of_device_id pmc_ids[] = { { .compatible = atmel,at91rm9200-pmc }, + { .compatible = atmel,at91sam9260-pmc }, + { .compatible = atmel,at91sam9g45-pmc }, + { .compatible = atmel,at91sam9n12-pmc }, + { .compatible = atmel,at91sam9x5-pmc }, + { .compatible = atmel,sama5d3-pmc }, { /*sentinel*/ } }; -- 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 v5 16/17] ARM: at91: move pit timer to common clk framework
Use device tree to get the source clock of the PIT (Periodic Interval Timer). If the clock is not found in device tree (or dt is not enabled) we'll try to get it using clk_lookup definitions. Signed-off-by: Boris BREZILLON b.brezil...@overkiz.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/at91sam926x_time.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index bb39232..0f04ffe 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -39,6 +39,7 @@ static u32 pit_cycle; /* write-once */ static u32 pit_cnt;/* access only w/system irq blocked */ static void __iomem *pit_base_addr __read_mostly; +static struct clk *mck; static inline unsigned int pit_read(unsigned int reg_offset) { @@ -195,10 +196,14 @@ static int __init of_at91sam926x_pit_init(void) if (!pit_base_addr) goto node_err; + mck = of_clk_get(np, 0); + /* Get the interrupts property */ ret = irq_of_parse_and_map(np, 0); if (!ret) { pr_crit(AT91: PIT: Unable to get IRQ from DT\n); + if (!IS_ERR(mck)) + clk_put(mck); goto ioremap_err; } at91sam926x_pit_irq.irq = ret; @@ -230,6 +235,8 @@ void __init at91sam926x_pit_init(void) unsignedbits; int ret; + mck = ERR_PTR(-ENOENT); + /* For device tree enabled device: initialize here */ of_at91sam926x_pit_init(); @@ -237,7 +244,12 @@ void __init at91sam926x_pit_init(void) * Use our actual MCK to figure out how many MCK/16 ticks per * 1/HZ period (instead of a compile-time constant LATCH). */ - pit_rate = clk_get_rate(clk_get(NULL, mck)) / 16; + if (IS_ERR(mck)) + mck = clk_get(NULL, mck); + + if (IS_ERR(mck)) + panic(AT91: PIT: Unable to get mck clk\n); + pit_rate = clk_get_rate(mck) / 16; pit_cycle = (pit_rate + HZ/2) / HZ; WARN_ON(((pit_cycle - 1) ~AT91_PIT_PIV) != 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] net: cdc_ncm: cleanup a type issue in cdc_ncm_setup()
This is harmless but cdc_ncm_setup() returns negative error codes truncated to u8 values. There is only one caller and treats all non-zero returns as errors but doesn't store the the return code. So the code works correctly but it's messy and upsets the static checkers. Signed-off-by: Dan Carpenter dan.carpen...@oracle.com diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index f74786a..e15ec2b 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -66,7 +66,7 @@ static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); static struct usb_driver cdc_ncm_driver; -static u8 cdc_ncm_setup(struct usbnet *dev) +static int cdc_ncm_setup(struct usbnet *dev) { struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev-data[0]; struct usb_cdc_ncm_ntb_parameters ncm_parm; -- 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 2/4] usb: usbtest: support usb2 extension descriptor test
Hi Sarah, On Tue, Nov 12, 2013 at 09:43:20AM -0800, Sarah Sharp wrote: On Mon, Oct 28, 2013 at 11:31:33PM +0800, Huang Rui wrote: In Test 9 of usbtest module, it is used for performing chapter 9 tests N times. USB2.0 Extension descriptor is one of the generic device-level capbility descriptors which added in section 9.6.2.1 of USB 3.0 spec. This patch adds to support getting usb2.0 extension descriptor test scenario for USB 3.0. Why not check the USB 2.0 extension BOS descriptor for USB 2.1 devices as well? Just change you check to be bcdUSB = 0x0210. You would have to make sure you fail a USB 2.1 device with a the USB 3.0 BOS extension descriptor or the Container ID BOS extension. Thank you to look at these patches. I tested with a USB 3.0 pen drive of DT Ultimate G2 16G which is attached on USB2 bus and act as a USB 2.1 device. It passed. But there aren't BOS descriptor set from lsusb message attached, it's strange, why? BTW, is BOS descriptor set not mandatory for USB 2.1 device? More comments below. Signed-off-by: Huang Rui ray.hu...@amd.com --- drivers/usb/misc/usbtest.c | 77 ++ 1 file changed, 77 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 38ebe1d..d9ac215 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -606,6 +606,28 @@ static int is_good_config(struct usbtest_dev *tdev, int len) return 0; } +static int is_good_ext(struct usbtest_dev *tdev, char *buf) +{ + struct usb_ext_cap_descriptor *ext; + u32 attr; + + ext = (struct usb_ext_cap_descriptor *) buf; + + if (ext-bLength != USB_DT_USB_EXT_CAP_SIZE) { + ERROR(tdev, bogus usb 2.0 extension descriptor length\n); + return 0; + } + + attr = le32_to_cpu(ext-bmAttributes); + /* bits[1:4] is used and others are reserved */ + if (attr ~0x1e) { /* reserved == 0 */ + ERROR(tdev, reserved bits set\n); + return 0; + } New errata for USB 2.1 Link PM that adds support for the BESL and DBESL encoding uses bits[1:15]. See the USB2-LPM-Errata-final.pdf file in the latest download of the USB 2.0 spec. This code should be fixed to reflect those changes (bitmask should be 0xfffe rather than 0x1e). You're right. I will make a patch to fix it. Thanks, Rui Bus 001 Device 005: ID 0951:1656 Kingston Technology Device Descriptor: bLength18 bDescriptorType 1 bcdUSB 2.10 bDeviceClass0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize064 idVendor 0x0951 Kingston Technology idProduct 0x1656 bcdDevice1.10 iManufacturer 1 Kingston iProduct2 DT Ultimate G2 iSerial 3 0018F30BFDDCBC41003D bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 32 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 498mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Device Status: 0x (Bus Powered)