[U-Boot] [PATCH 2/5] driver: usb: add EHCI driver for hi3787cv200 SoC
Marek Vasut
marex at denx.de
Fri May 5 15:34:34 UTC 2017
On 05/05/2017 04:32 PM, Tom Rini wrote:
> On Thu, May 04, 2017 at 03:47:07PM +0200, Jorge Ramirez-Ortiz wrote:
>
> CC'ing Marek...
>
>> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz at 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-ortiz at linaro.org>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#ifndef __HI3798cv200_H__
>> +#define __HI3798cv200_H__
This should be a separate patch ..
>> +#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)
Use BIT()
>> +#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)
Superfluous parenthesis.
>> +/* 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]; }
Uh what ? Needed ?
>> +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;
Just use #define FOO_REG_BAR 0xf00 , drop this structure stuff ...
>> +};
>> +
>> +#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"
Does HI stand for Hitachi ?
>> + 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-ortiz at 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;
This should use DM
>> +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);
Can the ulpi-phy code we have help here ? Also, clrsetbits_le32() and co ...
>> + /* 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 at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot
>
--
Best regards,
Marek Vasut
More information about the U-Boot
mailing list