summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/emul/usb-emul-uclass.c9
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg.c22
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg_regs.h6
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c3
-rw-r--r--drivers/usb/host/Kconfig7
-rw-r--r--drivers/usb/host/ehci-zynq.c103
-rw-r--r--drivers/usb/host/usb-uclass.c9
-rw-r--r--drivers/usb/musb-new/musb_dsps.c2
-rw-r--r--drivers/usb/phy/Makefile1
-rw-r--r--drivers/usb/phy/rockchip_usb2_phy.c107
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, &reg->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, &reg->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, &reg->grxfsiz);
+ writel(rx_fifo_sz, &reg->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,
&reg->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,
- &reg->dieptxf[i-1]);
+ writel((rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz*(i-1)) |
+ tx_fifo_sz << 16, &reg->dieptxf[i-1]);
/* Flush the RX FIFO */
writel(RX_FIFO_FLUSH, &reg->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(&reg->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, &reg->out_endp[ep_num].doepdma);
writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length),
&reg->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);
+}