From 5740ad5e144c8f469416c74dd670a44029434881 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 22 Jun 2021 08:47:05 +0200 Subject: usb: ehci: Handle clocks and phys The generic ehci binding also describes clocks and a phy. Add support for these properties to the driver. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20210622064711.14058-1-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- drivers/usb/host/ehci-hcd.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8c4da9fd12..4dd4d1dddb 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "ehci.h" @@ -1413,6 +1415,9 @@ static int ehci_probe(struct device_d *dev) struct ehci_platform_data *pdata = dev->platform_data; struct device_node *dn = dev->device_node; struct ehci_host *ehci; + struct clk_bulk_data *clks; + int num_clocks, ret; + struct phy *usb2_generic_phy; if (pdata) data.flags = pdata->flags; @@ -1440,6 +1445,27 @@ static int ehci_probe(struct device_d *dev) else data.hcor = NULL; + usb2_generic_phy = phy_optional_get(dev, "usb"); + if (IS_ERR(usb2_generic_phy)) + return PTR_ERR(usb2_generic_phy); + + ret = phy_init(usb2_generic_phy); + if (ret) + return ret; + + ret = phy_power_on(usb2_generic_phy); + if (ret) + return ret; + + ret = clk_bulk_get_all(dev, &clks); + if (ret < 0) + return ret; + + num_clocks = ret; + ret = clk_bulk_enable(num_clocks, clks); + if (ret) + return ret; + ehci = ehci_register(dev, &data); if (IS_ERR(ehci)) return PTR_ERR(ehci); -- cgit v1.2.3 From fbcb07e192b50ed32f4ec1bbad5447279f24516d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 22 Jun 2021 09:45:45 +0200 Subject: usb: dwc3: Use _io functions on dma coherent memory On both ARM and ARM64 we map DMA coherent memory the same as IO memory. This has the effect that unaligned accesses are not possible on DMA coherent memory. The dwc3 gadget driver uses memset() and memcpy() on that memory which may generate unaligned accesses and result in data aborts. Use memcpy_fromio() and memset_io() instead which are desgined to work on IO space and thus do not generate unaligned accesses. The alternative would be to map DMA coherent memory as MT_NORMAL_NC instead of MT_DEVICE_nGnRnE, but that require us to add memory barriers to drivers which we currently do not have. SO instead of risking regressions in drivers we take the easy way out and avoid unaligned accesses in the dwc3 driver. In this concrete case the dwc3 driver generated unaligned accesses on a Rockchip RK3568 ARM64 system. The driver copies data out of the receive queue. In my case first 4 bytes were copied, both source and target were aligned. The second access then copied more data beginning at the place where the first memcpy stopped. On this 4byte aligned address memcpy generated an 8byte read access which resulted in a data abort. On an ARM32 system this might not be a problem as that place, while not 8byte aligned, is still 4byte aligned, enough for a 32bit system. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20210622074545.17059-1-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- drivers/usb/dwc3/gadget.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f416acc999..49deaf4d98 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -643,14 +643,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) /* Initialize the TRB ring */ dep->trb_dequeue = 0; dep->trb_enqueue = 0; - memset(dep->trb_pool, 0, + memset_io(dep->trb_pool, 0, sizeof(struct dwc3_trb) * DWC3_TRB_NUM); /* Link TRB. The HWO bit is never reset */ trb_st_hw = &dep->trb_pool[0]; trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; - memset(trb_link, 0, sizeof(*trb_link)); + memset_io(trb_link, 0, sizeof(*trb_link)); trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); @@ -2908,10 +2908,10 @@ static void dwc3_gadget_poll(struct usb_gadget * g) buf = xzalloc(count); amount = min(count, evt->length - evt->lpos); - memcpy(buf, evt->buf + evt->lpos, amount); + memcpy_fromio(buf, evt->buf + evt->lpos, amount); if (amount < count) - memcpy(buf + amount, evt->buf, count - amount); + memcpy_fromio(buf + amount, evt->buf, count - amount); evt->lpos = (evt->lpos + count) % evt->length; -- cgit v1.2.3