[U-Boot] [PATCH 4/4] Armada100: Adds support for USB on gplugD

Ajay Bhargav ajay.bhargav at einfochips.com
Fri Jul 8 08:22:48 CEST 2011


Signed-off-by: Ajay Bhargav <ajay.bhargav at einfochips.com>
---
 arch/arm/cpu/arm926ejs/armada100/Makefile          |    1 +
 arch/arm/cpu/arm926ejs/armada100/cpu.c             |   14 ++
 arch/arm/cpu/arm926ejs/armada100/pxa168_u2h.c      |  154 ++++++++++++++++++++
 arch/arm/include/asm/arch-armada100/cpu.h          |   31 ++++
 .../include/asm/arch-armada100/pxa168_usb_phy.h    |  115 +++++++++++++++
 drivers/usb/host/Makefile                          |    1 +
 drivers/usb/host/ehci-pxa168.c                     |   58 ++++++++
 include/configs/gplugd.h                           |   20 +++
 8 files changed, 394 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/armada100/pxa168_u2h.c
 create mode 100644 arch/arm/include/asm/arch-armada100/pxa168_usb_phy.h
 create mode 100644 drivers/usb/host/ehci-pxa168.c

diff --git a/arch/arm/cpu/arm926ejs/armada100/Makefile b/arch/arm/cpu/arm926ejs/armada100/Makefile
index 76bd06d..8f931ff 100644
--- a/arch/arm/cpu/arm926ejs/armada100/Makefile
+++ b/arch/arm/cpu/arm926ejs/armada100/Makefile
@@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(SOC).o
 
 COBJS-y	= cpu.o timer.o dram.o
+COBJS-${CONFIG_USB_EHCI_PXA168} += pxa168_u2h.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS-y))
diff --git a/arch/arm/cpu/arm926ejs/armada100/cpu.c b/arch/arm/cpu/arm926ejs/armada100/cpu.c
index c21938e..2db42a0 100644
--- a/arch/arm/cpu/arm926ejs/armada100/cpu.c
+++ b/arch/arm/cpu/arm926ejs/armada100/cpu.c
@@ -106,3 +106,17 @@ void i2c_clk_enable(void)
 {
 }
 #endif
+
+/* Both USB host as well as USB ETH requires this function.
+ * So moving it from usb eth file (usbeth/mv_u2o_ctl.c) to this common file */
+/* CHIP ID:
+ * Z0: 0x00a0c910
+ * Y0: 0x00f0c910
+ */
+int pxa910_is_z0(void)
+{
+	if ((readl(CHIP_ID) & 0x00f00000) == 0x00a00000)
+		return 1;
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/armada100/pxa168_u2h.c b/arch/arm/cpu/arm926ejs/armada100/pxa168_u2h.c
new file mode 100644
index 0000000..99d94f0
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/armada100/pxa168_u2h.c
@@ -0,0 +1,154 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2009, 2010 Marvell International Ltd.
+ *
+ * This file is part of GNU program.
+ *
+ * GNU program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNU program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ *
+ * If not, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ *************************************************************************/
+
+#include <common.h>
+
+#include <linux/types.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <common.h>
+#include <config.h>
+#include <net.h>
+#include <command.h>
+#include <malloc.h>
+
+#include <asm/arch/cpu.h>
+#include <asm/arch/pxa168_usb_phy.h>
+
+#define PXA168_USB_SPH_PHY_BASE         CONFIG_USB_SPH_PHY_BASE
+#define PMUA_USB_CLK_RES_CTRL   (0xd428285c)
+
+#undef DEBUG
+
+#if DEBUG
+static unsigned int usb_debug = DEBUG;
+#else
+#define usb_debug 0     /* gcc will remove all the debug code for us */
+#endif
+
+/*****************************************************************************
+ * The registers read/write routines
+ ******************************************************************************/
+static unsigned usb_sph_get(unsigned *base, unsigned offset)
+{
+	return readl(base + (offset>>2));
+}
+
+static void usb_sph_set(unsigned *base, unsigned offset, unsigned value)
+{
+	unsigned int reg;
+
+	if (usb_debug)
+		printf("base %p off %x base+off %p read %x\n", base, offset,
+		(base + (offset>>2)), *(unsigned *)(base + (offset>>2)));
+	reg = readl(base + (offset>>2));
+	reg |= value;
+	writel(reg, base + (offset>>2));
+	readl(base + (offset>>2));
+}
+
+static void usb_sph_clear(unsigned *base, unsigned offset, unsigned value)
+{
+	unsigned int reg;
+
+	reg = readl(base + (offset>>2));
+	reg &= ~value;
+	writel(reg, base + (offset>>2));
+	readl(base + (offset>>2));
+}
+
+static void usb_sph_write(unsigned *base, unsigned offset, unsigned value)
+{
+	writel(value, base + (offset>>2));
+	readl(base + (offset>>2));
+}
+
+static void usb_sph_phy_init(unsigned *base)
+{
+	if (usb_debug)
+		printf("init phy\n\n");
+
+	usb_sph_set(base, U2PCTRL, 1<<UTMI_CTRL_INPKT_DELAY_SOF_SHIFT);
+	usb_sph_set(base, U2PCTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
+	udelay(1000);
+	usb_sph_set(base, U2PCTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
+
+	/* aspen specific*/
+	if (cpu_is_pxa910_168())
+		/* Turn on UTMI PHY OTG extension */
+		usb_sph_write(base, 0x3C, 1);
+
+	usb_sph_clear(base, U2PPLL, UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK);
+	usb_sph_set(base, U2PPLL, 0xee<<UTMI_PLL_FBDIV_SHIFT |
+			0xb<<UTMI_PLL_REFDIV_SHIFT);
+	usb_sph_set(base, U2PTX, 0x80000);
+
+	/* calibrate */
+	while ((usb_sph_get(base, U2PPLL) & PLL_READY) == 0)
+		;
+
+	/* toggle VCOCAL_START bit of U2PPLL */
+	udelay(200);
+	usb_sph_set(base, U2PPLL, VCOCAL_START);
+	udelay(40);
+	usb_sph_clear(base, U2PPLL, VCOCAL_START);
+
+	/* toggle REG_RCAL_START bit of U2PTX */
+	udelay(200);
+	usb_sph_set(base, U2PTX, REG_RCAL_START);
+	udelay(400);
+	usb_sph_clear(base, U2PTX, REG_RCAL_START);
+
+	/* make sure phy is ready */
+	while ((usb_sph_get(base, U2PPLL) & PLL_READY) == 0)
+		;
+}
+
+
+/* PXA USB SPH init */
+/* Initialize USB host controller's UTMI physical interface */
+void pxa168_usb_sph_init(void)
+{
+	u32 tmp;
+
+	/* Turn on Main PMU clocks ACGR */
+	writel(0x1EFFFF, 0xD4051024);
+
+	/* USB clk reset */
+	writel(0x18, PMUA_USB_CLK_RES_CTRL);
+	writel(0x1b, PMUA_USB_CLK_RES_CTRL);
+
+	/* enable the pull up */
+	if (!cpu_is_pxa910_168()) {
+		if (pxa910_is_z0()) {
+			writel((1<<20), (0xc0000004));
+		} else {
+			tmp = readl(0xd4207004);
+			tmp |= (1<<20);
+			writel(tmp, (0xd4207004));
+		}
+	}
+
+	/* init the UTMI transceiver */
+	usb_sph_phy_init((unsigned *)PXA168_USB_SPH_PHY_BASE);
+}
diff --git a/arch/arm/include/asm/arch-armada100/cpu.h b/arch/arm/include/asm/arch-armada100/cpu.h
index 6ab3bf9..7c62bfa 100644
--- a/arch/arm/include/asm/arch-armada100/cpu.h
+++ b/arch/arm/include/asm/arch-armada100/cpu.h
@@ -28,6 +28,36 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
+#define CPUID_ID                0
+
+#define __stringify_1(x)        #x
+#define __stringify(x)          __stringify_1(x)
+
+#define read_cpuid(reg)							\
+	({								\
+		unsigned int __val;					\
+		asm("mrc        p15, 0, %0, c0, c0, " __stringify(reg)	\
+		    : "=r" (__val)					\
+		    :							\
+		    : "cc");						\
+		__val;							\
+	})
+
+#define __cpu_is_pxa910_168(id)						\
+	({								\
+		unsigned int _id = (id) & 0xffff;			\
+		_id == 0x9263 || _id == 0x8400;				\
+	})
+
+
+#define cpu_is_pxa910_168()						\
+	({								\
+		unsigned int id = read_cpuid(CPUID_ID);			\
+		__cpu_is_pxa910_168(id);				\
+	})
+
+#define CHIP_ID    0xd4282c00
+
 /*
  * CPU Interface Registers
  * Refer Datasheet Appendix A.2
@@ -49,6 +79,7 @@ struct armd1cpu_registers {
  */
 u32 armd1_sdram_base(int);
 u32 armd1_sdram_size(int);
+int pxa910_is_z0(void);
 
 #ifdef CONFIG_PXASDH
 int pxa_sdh_init(bd_t *);
diff --git a/arch/arm/include/asm/arch-armada100/pxa168_usb_phy.h b/arch/arm/include/asm/arch-armada100/pxa168_usb_phy.h
new file mode 100644
index 0000000..752ad5c
--- /dev/null
+++ b/arch/arm/include/asm/arch-armada100/pxa168_usb_phy.h
@@ -0,0 +1,115 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2009, 2010 Marvell International Ltd.
+ *
+ * This file is part of GNU program.
+ *
+ * GNU program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNU program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ *
+ * If not, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ *************************************************************************/
+
+#ifndef PXA168_USB_PHY
+#define PXA168_USB_PHY
+
+/* ASPEN */
+#define UTMI_REVISION           0x0
+#define UTMI_CTRL               0x4
+#define UTMI_PLL                0x8
+#define UTMI_TX                 0xc
+#define UTMI_RX                 0x10
+#define UTMI_IVREF              0x14
+#define UTMI_T0                 0x18
+#define UTMI_T1                 0x1c
+#define UTMI_T2                 0x20
+#define UTMI_T3                 0x24
+#define UTMI_T4                 0x28
+#define UTMI_T5                 0x2c
+#define UTMI_RESERVE            0x30
+#define UTMI_USB_INT            0x34
+#define UTMI_DBG_CTL            0x38
+#define UTMI_OTG_ADDON          0x3c
+
+/* TTC/TD */
+#define U2PRSRVD        0x0
+#define U2PCTRL         0x4
+#define U2PPLL          0x8
+#define U2PTX           0xc
+#define U2PRX           0x10
+#define U2PIVREF        0x14
+#define U2PT0           0x18
+#define U2PT1           0x1c
+#define U2PT2           0x20
+#define U2PID           0x24
+#define U2PINT          0x28
+#define U2PDBGCTL       0x2c
+#define U2PCTL1         0x30
+#define U2PT3           0x34
+#define U2PT4           0x38
+#define U2PT5           0x3c
+
+/* For UTMICTRL Register */
+#define UTMI_CTRL_USB_CLK_EN                    (1<<31)
+/* pxa168 */
+#define UTMI_CTRL_SUSPEND_SET1                  (1<<30)
+#define UTMI_CTRL_SUSPEND_SET2                  (1<<29)
+#define UTMI_CTRL_RXBUF_PDWN                    (1<<24)
+#define UTMI_CTRL_TXBUF_PDWN                    (1<<11)
+
+#define UTMI_CTRL_INPKT_DELAY_SHIFT             30
+#define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT		28
+#define UTMI_CTRL_PU_REF_SHIFT			20
+#define UTMI_CTRL_ARC_PULLDN_SHIFT              12
+#define UTMI_CTRL_PLL_PWR_UP_SHIFT              1
+#define UTMI_CTRL_PWR_UP_SHIFT                  0
+/* For UTMI_PLL Register */
+#define UTMI_PLL_CLK_BLK_EN_SHIFT               24
+#define UTMI_PLL_FBDIV_SHIFT                    4
+#define UTMI_PLL_REFDIV_SHIFT                   0
+#define UTMI_PLL_FBDIV_MASK                     0x00000FF0
+#define UTMI_PLL_REFDIV_MASK                    0x0000000F
+#define UTMI_PLL_ICP_MASK                       0x00007000
+#define UTMI_PLL_KVCO_MASK                      0x00031000
+#define UTMI_PLL_PLLCALI12_SHIFT		29
+#define UTMI_PLL_PLLCALI12_MASK			(0x3<<29)
+#define UTMI_PLL_PLLVDD18_SHIFT			27
+#define UTMI_PLL_PLLVDD18_MASK			(0x3<<27)
+#define UTMI_PLL_PLLVDD12_SHIFT			25
+#define UTMI_PLL_PLLVDD12_MASK			(0x3<<25)
+#define UTMI_PLL_KVCO_SHIFT			15
+#define UTMI_PLL_ICP_SHIFT			12
+/* For UTMI_TX Register */
+#define UTMI_TX_LOW_VDD_EN_SHIFT                11
+#define UTMI_TX_IMPCAL_VTH_SHIFT                14
+#define UTMI_TX_IMPCAL_VTH_MASK                 (0x7<<14)
+#define UTMI_TX_CK60_PHSEL_SHIFT                17
+#define UTMI_TX_CK60_PHSEL_MASK                 (0xf<<17)
+#define UTMI_TX_TXVDD12_SHIFT                   22
+#define UTMI_TX_TXVDD12_MASK                    (0x3<<22)
+/* For UTMI_RX Register */
+#define UTMI_RX_SQ_THRESH_SHIFT                 4
+#define UTMI_RX_SQ_THRESH_MASK                  (0xf<<4)
+#define UTMI_REG_SQ_LENGTH_SHIFT                15
+#define UTMI_REG_SQ_LENGTH_MASK                 (0x3<<15)
+
+#define REG_RCAL_START                          0x00001000
+#define VCOCAL_START                            0x00200000
+#define KVCO_EXT                                0x00400000
+#define PLL_READY                               0x00800000
+#define CLK_BLK_EN                              0x01000000
+
+void pxa168_usb_sph_init(void);
+
+#endif /* PXA168_USB_PHY */
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 51b2494..b399ba6 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -46,6 +46,7 @@ COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
 COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o
 COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
 COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
+COBJS-$(CONFIG_USB_EHCI_PXA168) += ehci-pxa168.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c
new file mode 100644
index 0000000..1194f03
--- /dev/null
+++ b/drivers/usb/host/ehci-pxa168.c
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2009, 2010 Marvell International Ltd.
+ *
+ * This file is part of GNU program.
+ *
+ * GNU program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNU program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ *
+ * If not, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ *************************************************************************/
+
+#include <common.h>
+#include <asm/io.h>
+#include <usb.h>
+#include "ehci.h"
+#include "ehci-core.h"
+
+#include <asm/arch/pxa168_usb_phy.h>
+#define PXA168_USB_SPH_BASE	CONFIG_USB_SPH_REG_BASE
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(void)
+{
+	pxa168_usb_sph_init();
+
+	hccr = (struct ehci_hccr *)(PXA168_USB_SPH_BASE + 0x100);
+	hcor = (struct ehci_hcor *)(PXA168_USB_SPH_BASE + 0x140);
+
+	debug("Pxa168-ehci: init hccr %x and hcor %x hc_length %d\n",
+		(uint32_t)hccr, (uint32_t)hcor,
+		(uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+	return 0;
+}
diff --git a/include/configs/gplugd.h b/include/configs/gplugd.h
index 16fd03e..12421ee 100644
--- a/include/configs/gplugd.h
+++ b/include/configs/gplugd.h
@@ -124,6 +124,26 @@
 #endif /* CONFIG_PXASDH */
 
 /*
+ *  * USB/EHCI
+ *   */
+#define CONFIG_CMD_USB
+#define CONFIG_USB_SPH_REG_BASE         0xd4209000
+#define CONFIG_USB_SPH_PHY_BASE         0xd4206000
+
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_EHCI                 /* Enable EHCI USB support */
+#define CONFIG_USB_EHCI_PXA168
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
+#ifndef CONFIG_DOS_PARTITION
+#define CONFIG_DOS_PARTITION
+#endif /* CONFIG_DOS_PARTITION */
+#define CONFIG_ISO_PARTITION
+#define CONFIG_SUPPORT_VFAT
+#define CONFIG_CMD_EXT2
+#endif /* CONFIG_CMD_USB */
+
+/*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
  */
-- 
1.7.0.4



More information about the U-Boot mailing list