diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/emul/usb-emul-uclass.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/dwc2_udc_otg.c | 22 | ||||
-rw-r--r-- | drivers/usb/gadget/dwc2_udc_otg_regs.h | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 7 | ||||
-rw-r--r-- | drivers/usb/host/ehci-zynq.c | 103 | ||||
-rw-r--r-- | drivers/usb/host/usb-uclass.c | 9 | ||||
-rw-r--r-- | drivers/usb/musb-new/musb_dsps.c | 2 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/phy/rockchip_usb2_phy.c | 107 |
10 files changed, 191 insertions, 78 deletions
diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c index ee7ea5a..6e03c1e 100644 --- a/drivers/usb/emul/usb-emul-uclass.c +++ b/drivers/usb/emul/usb-emul-uclass.c @@ -8,7 +8,6 @@ #include <common.h> #include <dm.h> #include <usb.h> -#include <dm/root.h> #include <dm/device-internal.h> DECLARE_GLOBAL_DATA_PTR; @@ -265,12 +264,6 @@ int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, return 0; } -int usb_emul_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - void usb_emul_reset(struct udevice *dev) { struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); @@ -282,7 +275,7 @@ void usb_emul_reset(struct udevice *dev) UCLASS_DRIVER(usb_emul) = { .id = UCLASS_USB_EMUL, .name = "usb_emul", - .post_bind = usb_emul_post_bind, + .post_bind = dm_scan_fdt_dev, .per_child_auto_alloc_size = sizeof(struct usb_device), .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), }; diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index a23278d..029927f 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -403,6 +403,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) int i; unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); uint32_t dflt_gusbcfg; + uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; debug("Reseting OTG controller\n"); @@ -467,18 +468,27 @@ static void reconfig_usbd(struct dwc2_udc *dev) /* 10. Unmask device IN EP common interrupts*/ writel(DIEPMSK_INIT, ®->diepmsk); + rx_fifo_sz = RX_FIFO_SIZE; + np_tx_fifo_sz = NPTX_FIFO_SIZE; + tx_fifo_sz = PTX_FIFO_SIZE; + + if (dev->pdata->rx_fifo_sz) + rx_fifo_sz = dev->pdata->rx_fifo_sz; + if (dev->pdata->np_tx_fifo_sz) + np_tx_fifo_sz = dev->pdata->np_tx_fifo_sz; + if (dev->pdata->tx_fifo_sz) + tx_fifo_sz = dev->pdata->tx_fifo_sz; + /* 11. Set Rx FIFO Size (in 32-bit words) */ - writel(RX_FIFO_SIZE >> 2, ®->grxfsiz); + writel(rx_fifo_sz, ®->grxfsiz); /* 12. Set Non Periodic Tx FIFO Size */ - writel((NPTX_FIFO_SIZE >> 2) << 16 | ((RX_FIFO_SIZE >> 2)) << 0, + writel((np_tx_fifo_sz << 16) | rx_fifo_sz, ®->gnptxfsiz); for (i = 1; i < DWC2_MAX_HW_ENDPOINTS; i++) - writel((PTX_FIFO_SIZE >> 2) << 16 | - ((RX_FIFO_SIZE + NPTX_FIFO_SIZE + - PTX_FIFO_SIZE*(i-1)) >> 2) << 0, - ®->dieptxf[i-1]); + writel((rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz*(i-1)) | + tx_fifo_sz << 16, ®->dieptxf[i-1]); /* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl); diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index 78ec90e..c94396a 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -130,9 +130,9 @@ struct dwc2_usbotg_reg { #define HIGH_SPEED_CONTROL_PKT_SIZE 64 #define HIGH_SPEED_BULK_PKT_SIZE 512 -#define RX_FIFO_SIZE (1024*4) -#define NPTX_FIFO_SIZE (1024*4) -#define PTX_FIFO_SIZE (1536*1) +#define RX_FIFO_SIZE (1024) +#define NPTX_FIFO_SIZE (1024) +#define PTX_FIFO_SIZE (384) #define DEPCTL_TXFNUM_0 (0x0<<22) #define DEPCTL_TXFNUM_1 (0x1<<22) diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index 12f5c85..0d6d2fb 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -110,6 +110,9 @@ static int setdma_rx(struct dwc2_ep *ep, struct dwc2_request *req) ctrl = readl(®->out_endp[ep_num].doepctl); + invalidate_dcache_range((unsigned long) ep->dma_buf, + (unsigned long) ep->dma_buf + ep->len); + writel((unsigned int) ep->dma_buf, ®->out_endp[ep_num].doepdma); writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length), ®->out_endp[ep_num].doeptsiz); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 09db938..7f94c1f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -101,6 +101,13 @@ config USB_EHCI_MSM This driver supports combination of Chipidea USB controller and Synapsys USB PHY in host mode only. +config USB_EHCI_ZYNQ + bool "Support for Xilinx Zynq on-chip EHCI USB controller" + depends on ARCH_ZYNQ + default y + ---help--- + Enable support for Zynq on-chip EHCI USB controller + config USB_EHCI_GENERIC bool "Support for generic EHCI USB controller" depends on OF_CONTROL diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c index 37a7935..76642cd 100644 --- a/drivers/usb/host/ehci-zynq.c +++ b/drivers/usb/host/ehci-zynq.c @@ -7,55 +7,48 @@ */ #include <common.h> +#include <dm.h> +#include <usb.h> #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> #include <asm/io.h> -#include <usb.h> #include <usb/ehci-ci.h> #include <usb/ulpi.h> #include "ehci.h" -#define ZYNQ_USB_USBCMD_RST 0x0000002 -#define ZYNQ_USB_USBCMD_STOP 0x0000000 -#define ZYNQ_USB_NUM_MIO 12 +struct zynq_ehci_priv { + struct ehci_ctrl ehcictrl; + struct usb_ehci *ehci; +}; -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, - struct ehci_hcor **hcor) +static int ehci_zynq_ofdata_to_platdata(struct udevice *dev) { - struct usb_ehci *ehci; + struct zynq_ehci_priv *priv = dev_get_priv(dev); + + priv->ehci = (struct usb_ehci *)dev_get_addr_ptr(dev); + if (!priv->ehci) + return -EINVAL; + + return 0; +} + +static int ehci_zynq_probe(struct udevice *dev) +{ + struct usb_platdata *plat = dev_get_platdata(dev); + struct zynq_ehci_priv *priv = dev_get_priv(dev); + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; struct ulpi_viewport ulpi_vp; - int ret, mio_usb; /* Used for writing the ULPI data address */ struct ulpi_regs *ulpi = (struct ulpi_regs *)0; + int ret; - if (!index) { - mio_usb = zynq_slcr_get_mio_pin_status("usb0"); - if (mio_usb != ZYNQ_USB_NUM_MIO) { - printf("usb0 wrong num MIO: %d, Index %d\n", mio_usb, - index); - return -1; - } - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0; - } else { - mio_usb = zynq_slcr_get_mio_pin_status("usb1"); - if (mio_usb != ZYNQ_USB_NUM_MIO) { - printf("usb1 wrong num MIO: %d, Index %d\n", mio_usb, - index); - return -1; - } - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1; - } - - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + hccr = (struct ehci_hccr *)((uint32_t)&priv->ehci->caplength); + hcor = (struct ehci_hcor *)((uint32_t) hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint; + ulpi_vp.viewport_addr = (u32)&priv->ehci->ulpi_viewpoint; ulpi_vp.port_num = 0; ret = ulpi_init(&ulpi_vp); @@ -77,28 +70,34 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); - return 0; + return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type); } -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) +static int ehci_zynq_remove(struct udevice *dev) { - struct usb_ehci *ehci; - - if (!index) - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0; - else - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1; + int ret; - /* Stop controller */ - writel(ZYNQ_USB_USBCMD_STOP, &ehci->usbcmd); - udelay(1000); - - /* Initiate controller reset */ - writel(ZYNQ_USB_USBCMD_RST, &ehci->usbcmd); + ret = ehci_deregister(dev); + if (ret) + return ret; return 0; } + +static const struct udevice_id ehci_zynq_ids[] = { + { .compatible = "xlnx,zynq-usb-2.20a" }, + { } +}; + +U_BOOT_DRIVER(ehci_zynq) = { + .name = "ehci_zynq", + .id = UCLASS_USB, + .of_match = ehci_zynq_ids, + .ofdata_to_platdata = ehci_zynq_ofdata_to_platdata, + .probe = ehci_zynq_probe, + .remove = ehci_zynq_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct zynq_ehci_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 69c9a50..be114fc 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -14,7 +14,6 @@ #include <usb.h> #include <dm/device-internal.h> #include <dm/lists.h> -#include <dm/root.h> #include <dm/uclass-internal.h> DECLARE_GLOBAL_DATA_PTR; @@ -349,12 +348,6 @@ struct usb_device *usb_get_dev_index(struct udevice *bus, int index) } #endif -int usb_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) { struct usb_platdata *plat; @@ -768,7 +761,7 @@ UCLASS_DRIVER(usb) = { .id = UCLASS_USB, .name = "usb", .flags = DM_UC_FLAG_SEQ_ALIAS, - .post_bind = usb_post_bind, + .post_bind = dm_scan_fdt_dev, .priv_auto_alloc_size = sizeof(struct usb_uclass_priv), .per_child_auto_alloc_size = sizeof(struct usb_device), .per_device_auto_alloc_size = sizeof(struct usb_bus_priv), diff --git a/drivers/usb/musb-new/musb_dsps.c b/drivers/usb/musb-new/musb_dsps.c index bb7c952..a71db76 100644 --- a/drivers/usb/musb-new/musb_dsps.c +++ b/drivers/usb/musb-new/musb_dsps.c @@ -627,7 +627,7 @@ static int __devinit dsps_probe(struct platform_device *pdev) /* get memory resource */ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { - dev_err(&pdev->dev, "failed to get usbss mem resourse\n"); + dev_err(&pdev->dev, "failed to get usbss mem resource\n"); ret = -ENODEV; goto err1; } diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 93d147e..4e548c2 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_TWL4030_USB) += twl4030.o obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o +obj-$(CONFIG_ROCKCHIP_USB2_PHY) += rockchip_usb2_phy.o diff --git a/drivers/usb/phy/rockchip_usb2_phy.c b/drivers/usb/phy/rockchip_usb2_phy.c new file mode 100644 index 0000000..1958478 --- /dev/null +++ b/drivers/usb/phy/rockchip_usb2_phy.c @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <libfdt.h> + +#include "../gadget/dwc2_udc_otg_priv.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define BIT_WRITEABLE_SHIFT 16 + +struct usb2phy_reg { + unsigned int offset; + unsigned int bitend; + unsigned int bitstart; + unsigned int disable; + unsigned int enable; +}; + +/** + * struct rockchip_usb2_phy_cfg: usb-phy port configuration + * @port_reset: usb otg per-port reset register + * @soft_con: software control usb otg register + * @suspend: phy suspend register + */ +struct rockchip_usb2_phy_cfg { + struct usb2phy_reg port_reset; + struct usb2phy_reg soft_con; + struct usb2phy_reg suspend; +}; + +struct rockchip_usb2_phy_dt_id { + char compatible[128]; + const void *data; +}; + +static const struct rockchip_usb2_phy_cfg rk3288_pdata = { + .port_reset = {0x00, 12, 12, 0, 1}, + .soft_con = {0x08, 2, 2, 0, 1}, + .suspend = {0x0c, 5, 0, 0x01, 0x2A}, +}; + +static struct rockchip_usb2_phy_dt_id rockchip_usb2_phy_dt_ids[] = { + { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata }, + {} +}; + +static void property_enable(struct dwc2_plat_otg_data *pdata, + const struct usb2phy_reg *reg, bool en) +{ + unsigned int val, mask, tmp; + + tmp = en ? reg->enable : reg->disable; + mask = GENMASK(reg->bitend, reg->bitstart); + val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); + + writel(val, pdata->regs_phy + reg->offset); +} + + +void otg_phy_init(struct dwc2_udc *dev) +{ + struct dwc2_plat_otg_data *pdata = dev->pdata; + struct rockchip_usb2_phy_cfg *phy_cfg = NULL; + struct rockchip_usb2_phy_dt_id *of_id; + int i; + + for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) { + of_id = &rockchip_usb2_phy_dt_ids[i]; + if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node, + of_id->compatible) == 0) { + phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data; + break; + } + } + if (!phy_cfg) { + debug("Can't find device platform data\n"); + + hang(); + return; + } + pdata->priv = phy_cfg; + /* disable software control */ + property_enable(pdata, &phy_cfg->soft_con, false); + + /* reset otg port */ + property_enable(pdata, &phy_cfg->port_reset, true); + mdelay(1); + property_enable(pdata, &phy_cfg->port_reset, false); + udelay(1); +} + +void otg_phy_off(struct dwc2_udc *dev) +{ + struct dwc2_plat_otg_data *pdata = dev->pdata; + struct rockchip_usb2_phy_cfg *phy_cfg = pdata->priv; + + /* enable software control */ + property_enable(pdata, &phy_cfg->soft_con, true); + /* enter suspend */ + property_enable(pdata, &phy_cfg->suspend, true); +} |