
Signed-off-by: Ajay Bhargav ajay.bhargav@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 */