Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-or...@linaro.org>
---
 .../arm/include/asm/arch-hi3798cv200/hi3798cv200.h |  93 ++++++++++
 drivers/usb/host/Kconfig                           |   6 +
 drivers/usb/host/Makefile                          |   1 +
 drivers/usb/host/ehci-hi3798cv200.c                | 196 +++++++++++++++++++++
 4 files changed, 296 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h
 create mode 100644 drivers/usb/host/ehci-hi3798cv200.c

diff --git a/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h 
b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h
new file mode 100644
index 0000000..c67fda1
--- /dev/null
+++ b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2017 Linaro
+ * Jorge Ramirez-Ortiz <jorge.ramirez-or...@linaro.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __HI3798cv200_H__
+#define __HI3798cv200_H__
+
+#define REG_BASE_CRG                   0xF8A22000
+#define REG_BASE_SCTL                  0xF8000000
+#define REG_BASE_CRG                   0xF8A22000
+#define REG_BASE_PERI_CTRL             0xF8A20000
+
+/* DEVICES */
+#define REG_BASE_UART0                 0xF8B00000
+#define REG_BASE_EHCI                  0XF9890000
+#define REG_BASE_MCI                   0xF9830000
+#define REG_BASE_MMC0                  0xF9830000
+
+/* SC */
+#define REG_SC_CTRL                    0x0000
+#define REG_SC_SYSRES                  0x0004
+#define REG_SC_GEN0                    0x0080
+#define REG_SC_GEN1                    0x0084
+#define REG_SC_GEN2                    0x0088
+#define REG_SC_GEN12                   0x00B0
+
+/* USB EHCI driver */
+#define PERI_USB0                      (0xF8A20000 + 0x120)
+#define PERI_USB1                      (0xF8A20000 + 0x124)
+#define PERI_USB3                      (0xF8A20000 + 0x12c)
+#define PERI_USB4                      (0xF8A20000 + 0x130)
+
+#define WORDINTERFACE                  (1 << 0)
+#define ULPI_BYPASS_EN_PORT0           (1 << 3)
+#define SS_BURST16_EN                  (1 << 9)
+#define TEST_WRDATA                    (0x4)
+#define TEST_ADDR                      (0x6 << 8)
+#define TEST_WREN                      (1 << 21)
+#define TEST_CLK                       (1 << 22)
+#define TEST_RSTN                      (1 << 23)
+
+#define PERI_CRG46                     (0xF8A22000 + 0xb8)
+#define USB2_BUS_CKEN                  (1<<0)
+#define USB2_OHCI48M_CKEN              (1<<1)
+#define USB2_OHCI12M_CKEN              (1<<2)
+#define USB2_OTG_UTMI_CKEN             (1<<3)
+#define USB2_HST_PHY_CKEN              (1<<4)
+#define USB2_UTMI0_CKEN                        (1<<5)
+#define USB2_BUS_SRST_REQ              (1<<12)
+#define USB2_UTMI0_SRST_REQ            (1<<13)
+#define USB2_HST_PHY_SYST_REQ          (1<<16)
+#define USB2_OTG_PHY_SYST_REQ          (1<<17)
+#define USB2_CLK48_SEL                 (1<<20)
+
+#define PERI_CRG47                     (0xF8A22000 + 0xbc)
+#define USB2_PHY01_REF_CKEN            (1 << 0)
+#define USB2_PHY2_REF_CKEN             (1 << 2)
+#define USB2_PHY01_SRST_REQ            (1 << 4)
+#define USB2_PHY2_SRST_REQ             (1 << 6)
+#define USB2_PHY01_SRST_TREQ0          (1 << 8)
+#define USB2_PHY01_SRST_TREQ1          (1 << 9)
+#define USB2_PHY2_SRST_TREQ            (1 << 10)
+#define USB2_PHY01_REFCLK_SEL          (1 << 12)
+#define USB2_PHY2_REFCLK_SEL           (1 << 14)
+
+#define REG_START_MODE                 0x0000
+#define REG_PERI_STAT                  0x0004
+#define REG_PERI_CTRL                  0x0008
+#define REG_PERI_CRG26                 0x00A8
+#define NF_BOOTBW_MASK                 (1<<12)
+
+#define HI3798CV200_EHCI_CTRL          (PERI_USB0)
+
+/* Generate padding data ranges with unique identifiers. */
+#define ___cat(a,b)             a##b
+#define __cat(a,b)              ___cat(a,b)
+#define __padding(__words) struct { __u32 __cat(__pad, __COUNTER__)[__words]; }
+
+struct hi3798cv200_ehci_ctrl_regs {
+       u32 peri_usb0;
+       u32 peri_usb1;
+       u32 peri_usb2;
+       u32 peri_usb3;
+       u32 peri_usb4;
+       __padding(0x7e1);
+       u32 peri_crg46;
+       u32 peri_crg47;
+};
+
+#endif
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0bf8274..a749d0e 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -128,6 +128,12 @@ config USB_EHCI_ZYNQ
        ---help---
          Enable support for Zynq on-chip EHCI USB controller
 
+config USB_EHCI_POPLAR
+       bool "Support for HI3798cv200 EHCI USB controller"
+       default y
+       ---help---
+         Enable support for Poplar 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/Makefile b/drivers/usb/host/Makefile
index 58c0cf5..3661636 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
 obj-$(CONFIG_USB_EHCI_VF) += ehci-vf.o
 obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o
 obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o
+obj-$(CONFIG_USB_EHCI_POPLAR) += ehci-hi3798cv200.o
 
 # xhci
 obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o
diff --git a/drivers/usb/host/ehci-hi3798cv200.c 
b/drivers/usb/host/ehci-hi3798cv200.c
new file mode 100644
index 0000000..c535de1
--- /dev/null
+++ b/drivers/usb/host/ehci-hi3798cv200.c
@@ -0,0 +1,196 @@
+/*
+ * (C) Copyright 2017 Linaro
+ * Jorge Ramirez-Ortiz <jorge.ramirez-or...@linaro.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/hi3798cv200.h>
+#include <asm/io.h>
+
+#include "ehci.h"
+
+static struct hi3798cv200_ehci_ctrl_regs *ctrl = (void *) 
HI3798CV200_EHCI_CTRL;
+
+static void inno_phy_config_2p_1(void)
+{
+       u32 reg;
+       /* write 0x4 to addr 0x06
+       * config 2P PHY clk output
+       * delay 1ms for waiting PLL stable
+       */
+       reg = TEST_WRDATA|TEST_ADDR|TEST_WREN|TEST_RSTN;
+       writel(reg, &ctrl->peri_usb0);
+       reg = TEST_WRDATA|TEST_ADDR|TEST_WREN|TEST_RSTN|TEST_CLK;
+       writel(reg, &ctrl->peri_usb0);
+       reg = TEST_WRDATA|TEST_ADDR|TEST_WREN|TEST_RSTN;
+       writel(reg, &ctrl->peri_usb0);
+       mdelay(1);
+
+       /* write 0x1c to addr 0x00
+       * 0x00[0] = 0 : close EOP pre-emphasis
+       * 0x00[2] = 1 : open Data pre-emphasis
+       */
+       writel(0xa1001c, &ctrl->peri_usb0);
+       writel(0xe1001c, &ctrl->peri_usb0);
+       writel(0xa1001c, &ctrl->peri_usb0);
+       udelay(20);
+
+       /* write 0x07 to 0x06
+       * {0x06[1:0],0x05[7]} = 110 : Rcomp = 150mV , increase DC level
+       */
+       writel(0xa00607, &ctrl->peri_usb0);
+       writel(0xe00607, &ctrl->peri_usb0);
+       writel(0xa00607, &ctrl->peri_usb0);
+       udelay(20);
+
+       /* write 0x00 to addr 0x07
+       * 0x07[1] = 0 : Keep Rcomp working
+       */
+       writel(0xa10700, &ctrl->peri_usb0);
+       writel(0xe10700, &ctrl->peri_usb0);
+       writel(0xa10700, &ctrl->peri_usb0);
+       udelay(20);
+
+       /* write 0xab to 0x0a
+       * 0x0a[7:5] = 101 : Icomp = 212mV , increase current drive
+       */
+       writel(0xa00aab, &ctrl->peri_usb0);
+       writel(0xe00aab, &ctrl->peri_usb0);
+       writel(0xa00aab, &ctrl->peri_usb0);
+       udelay(20);
+
+       /* write 0x40 to addr 0x11
+       * 0x11[6:5] = 10 : sovle EMI problem, rx_active will
+       * not stay at 1 when error packets received
+       */
+       writel(0xa11140, &ctrl->peri_usb0);
+       writel(0xe11140, &ctrl->peri_usb0);
+       writel(0xa11140, &ctrl->peri_usb0);
+       udelay(20);
+
+       /* write 0x41 to addr 0x10
+       * 0x10[0] = 1 : Comp Mode Select
+       */
+       writel(0xa11041, &ctrl->peri_usb0);
+       writel(0xe11041, &ctrl->peri_usb0);
+       writel(0xa11041, &ctrl->peri_usb0);
+       udelay(20);
+
+       /*
+       * {0x00a[0],0x009[7:6]} = 110 : Eye Diagram Adjust
+       * {0x10a[0],0x109[7:6]} = 000 : Eye Diagram Adjust
+       */
+       writel(0xa0098c, &ctrl->peri_usb0);
+       writel(0xe0098c, &ctrl->peri_usb0);
+       writel(0xa0098c, &ctrl->peri_usb0);
+       writel(0xa10a0a, &ctrl->peri_usb0);
+       writel(0xe10a0a, &ctrl->peri_usb0);
+       writel(0xa10a0a, &ctrl->peri_usb0);
+       udelay(20);
+}
+
+#ifndef CONFIG_DM_USB
+int ehci_hcd_init(int index, enum usb_init_type init,
+               struct ehci_hccr **hccr, struct ehci_hcor **hcor)
+{
+       int reg;
+
+       *hccr = (struct ehci_hccr *) REG_BASE_EHCI;
+       *hcor = (struct ehci_hcor *)( (void *) REG_BASE_EHCI +
+                       HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+
+       /* reset controller bus/utmi/roothub  */
+       reg = readl(&ctrl->peri_crg46);
+       reg |= (USB2_BUS_SRST_REQ
+               | USB2_UTMI0_SRST_REQ
+               | USB2_HST_PHY_SYST_REQ
+               | USB2_OTG_PHY_SYST_REQ);
+       writel(reg, &ctrl->peri_crg46);
+       udelay(200);
+
+       /* reset phy por/utmi */
+       reg = readl(&ctrl->peri_crg47);
+       reg |= (USB2_PHY01_SRST_REQ
+               | USB2_PHY01_SRST_TREQ1);
+       writel(reg, &ctrl->peri_crg47);
+       udelay(200);
+
+       reg = readl(&ctrl->peri_usb3);
+       reg |= ULPI_BYPASS_EN_PORT0;
+       reg &= ~(WORDINTERFACE);
+       reg &= ~(SS_BURST16_EN);
+       writel(reg, &ctrl->peri_usb3);
+       udelay(100);
+
+       /* open ref clk */
+       reg = readl(&ctrl->peri_crg47);
+       reg |= (USB2_PHY01_REF_CKEN);
+       writel(reg, &ctrl->peri_crg47);
+       udelay(300);
+
+       /* cancel power on reset */
+       reg = readl(&ctrl->peri_crg47);
+       reg &= ~(USB2_PHY01_SRST_REQ);
+       writel(reg, &ctrl->peri_crg47);
+       udelay(500);
+
+       inno_phy_config_2p_1();
+
+       /* cancel port reset
+        * delay 10ms for waiting comp circuit stable
+       */
+       reg = readl(&ctrl->peri_crg47);
+       reg &= ~(USB2_PHY01_SRST_TREQ1);
+       writel(reg, &ctrl->peri_crg47);
+       mdelay(10);
+
+       /* open controller clk */
+       reg = readl(&ctrl->peri_crg46);
+       reg |= (USB2_BUS_CKEN
+               | USB2_OHCI48M_CKEN
+               | USB2_OHCI12M_CKEN
+               | USB2_OTG_UTMI_CKEN
+               | USB2_HST_PHY_CKEN
+               | USB2_UTMI0_CKEN);
+       writel(reg, &ctrl->peri_crg46);
+       udelay(200);
+
+       /* cancel control reset */
+       reg = readl(&ctrl->peri_crg46);
+       reg &= ~(USB2_BUS_SRST_REQ
+               | USB2_UTMI0_SRST_REQ
+               | USB2_HST_PHY_SYST_REQ
+               | USB2_OTG_PHY_SYST_REQ);
+       writel(reg, &ctrl->peri_crg46);
+       udelay(200);
+
+
+       return 0;
+}
+
+int ehci_hcd_stop(int index)
+{
+       int reg;
+
+       reg = readl(&ctrl->peri_crg46);
+       reg |= (USB2_BUS_SRST_REQ
+               | USB2_UTMI0_SRST_REQ
+               | USB2_HST_PHY_SYST_REQ);
+       writel(reg, &ctrl->peri_crg46);
+
+       udelay(200);
+
+       reg = readl(&ctrl->peri_crg47);
+       reg |= (USB2_PHY01_SRST_REQ
+               | USB2_PHY01_SRST_TREQ1);
+       writel(reg, &ctrl->peri_crg47);
+
+       udelay(100);
+
+       return 0;
+}
+#else
+error "CONFIG_DM_USB not supported for hi3798cv200"
+#endif
-- 
2.7.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to