From efe491be15ead3bbcf7e715337fdee7dfa41f699 Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Tue, 11 Dec 2012 15:32:19 +0800 Subject: ENGR00216076-1: PM: Add Power Management driver for Vybrid System could run into STOP and LPRun modes. When system was working in STOP mode, pressing SW1 button or inserting or removing SD card could wake up it. Signed-off-by: Alison Wang --- arch/arm/mach-mvf/Makefile | 4 +- arch/arm/mach-mvf/board-twr-vf700.c | 15 +- arch/arm/mach-mvf/cpu.c | 3 +- arch/arm/mach-mvf/crm_regs.h | 1 + arch/arm/mach-mvf/irq.c | 10 +- arch/arm/mach-mvf/mvf_suspend.S | 484 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-mvf/pm.c | 312 +++++++++++++++++++++++ arch/arm/mach-mvf/regs-pm.h | 77 ++++++ arch/arm/mach-mvf/regs-src.h | 45 ++++ arch/arm/mach-mvf/system.c | 139 ++++++++++- 10 files changed, 1076 insertions(+), 14 deletions(-) create mode 100644 arch/arm/mach-mvf/mvf_suspend.S create mode 100644 arch/arm/mach-mvf/pm.c create mode 100644 arch/arm/mach-mvf/regs-pm.h create mode 100644 arch/arm/mach-mvf/regs-src.h (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile index c103e4dc3078..e25fb28b7216 100644 --- a/arch/arm/mach-mvf/Makefile +++ b/arch/arm/mach-mvf/Makefile @@ -3,8 +3,8 @@ # # Object file lists. -obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o usb_dr.o usb_dr2.o +obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o usb_dr.o usb_dr2.o pm.o obj-y += l2switch.o -obj-$(CONFIG_ARCH_MVFA5) += clock.o +obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o obj-$(CONFIG_MACH_MVFA5_TWR_VF700) += board-twr-vf700.o diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index 03cc6ad51788..5903f7ae0244 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -364,22 +365,20 @@ static void spi_device_init(void) ARRAY_SIZE(mvf_spi_board_info)); } -#if 1 -static void vf700_suspend_enter(void) +static void vf600_suspend_enter(void) { /* suspend preparation */ } -static void vf700_suspend_exit(void) +static void vf600_suspend_exit(void) { /* resmue resore */ } -static const struct pm_platform_data mvf_vf700_pm_data __initconst = { +static const struct pm_platform_data mvf_vf600_pm_data __initconst = { .name = "mvf_pm", - .suspend_enter = vf700_suspend_enter, - .suspend_exit = vf700_suspend_exit, + .suspend_enter = vf600_suspend_enter, + .suspend_exit = vf600_suspend_exit, }; -#endif static struct mvf_dcu_platform_data mvf_dcu_pdata = { .mode_str = "480x272", @@ -458,6 +457,8 @@ static void __init mvf_board_init(void) mvf_add_snvs_rtc(); + mvf_add_pm_imx(0, &mvf_vf600_pm_data); + mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data); mvf_add_imx_i2c(0, &mvf600_i2c_data); diff --git a/arch/arm/mach-mvf/cpu.c b/arch/arm/mach-mvf/cpu.c index 2254ac5974c5..4c6d018cd076 100644 --- a/arch/arm/mach-mvf/cpu.c +++ b/arch/arm/mach-mvf/cpu.c @@ -81,8 +81,7 @@ EXPORT_SYMBOL(mvf_revision); static int __init post_cpu_init(void) { - - /*iram_init(MVF_IRAM_BASE_ADDR, MVF_IRAM_SIZE);*/ + iram_init(MVF_IRAM_BASE_ADDR, MVF_IRAM_SIZE); /* Move wait routine into iRAM */ ccm_base = MVF_IO_ADDRESS(MVF_CCM_BASE_ADDR); diff --git a/arch/arm/mach-mvf/crm_regs.h b/arch/arm/mach-mvf/crm_regs.h index 78604eb96447..57fac5bbe973 100644 --- a/arch/arm/mach-mvf/crm_regs.h +++ b/arch/arm/mach-mvf/crm_regs.h @@ -50,6 +50,7 @@ #define PFD_480_BASE_ADDR (MXC_PLL_BASE + 0xF0) #define PFD_528_BASE_ADDR (MXC_PLL_BASE + 0x100) #define PFD_528SYS_BASE_ADDR (MXC_PLL_BASE + 0x2B0) +#define ANADIG_2P5_ADDR (MXC_PLL_BASE + 0x130) #define ANADIG_MISC0_REG (MXC_PLL_BASE + 0x150) #define ANADIG_MISC1_REG (MXC_PLL_BASE + 0x160) #define PLL_PFD_480_USB1 (MXC_PLL_BASE + 0xF0) diff --git a/arch/arm/mach-mvf/irq.c b/arch/arm/mach-mvf/irq.c index c3e7b9291faa..89c7d382173f 100644 --- a/arch/arm/mach-mvf/irq.c +++ b/arch/arm/mach-mvf/irq.c @@ -36,9 +36,9 @@ static int mvf_gic_irq_set_wake(struct irq_data *d, unsigned int enable) if (enable) { gpc_wake_irq[d->irq / 32 - 1] |= 1 << (d->irq % 32); - printk(KERN_INFO "add wake up source irq %d\n", d->irq); + printk(KERN_DEBUG "add wake up source irq %d\n", d->irq); } else { - printk(KERN_INFO "remove wake up source irq %d\n", d->irq); + printk(KERN_DEBUG "remove wake up source irq %d\n", d->irq); gpc_wake_irq[d->irq / 32 - 1] &= ~(1 << (d->irq % 32)); } return 0; @@ -48,6 +48,7 @@ void mvf_init_irq(void) unsigned int i; void __iomem *int_router_base = MVF_IO_ADDRESS(MVF_MSCM_INT_ROUTER_BASE); + struct irq_desc *desc; /* start offset if private timer irq id, which is 29. * ID table: @@ -60,6 +61,11 @@ void mvf_init_irq(void) gic_init(0, 27, MVF_IO_ADDRESS(MVF_INTD_BASE_ADDR), MVF_IO_ADDRESS(MVF_SCUGIC_BASE_ADDR + 0x100)); + for (i = MXC_INT_START; i <= MXC_INT_END; i++) { + desc = irq_to_desc(i); + desc->irq_data.chip->irq_set_wake = mvf_gic_irq_set_wake; + } + mvf_register_gpios(); for (i = 0; i < 112; i++) diff --git a/arch/arm/mach-mvf/mvf_suspend.S b/arch/arm/mach-mvf/mvf_suspend.S new file mode 100644 index 000000000000..ce9205162538 --- /dev/null +++ b/arch/arm/mach-mvf/mvf_suspend.S @@ -0,0 +1,484 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + */ + +#include +#include +#include +#include +#include "regs-src.h" +#include "crm_regs.h" + +#define PERIPBASE_VIRT_OFFSET 0xb2000000 +#define TTRBIT_MASK 0xffffc000 +#define TABLE_INDEX_MASK 0xfff00000 +#define TABLE_ENTRY 0x00000c02 +#define CACHE_DISABLE_MASK 0xfffffffb +#define IRAM_SUSPEND_SIZE (1 << 15) + +/************************************************************* +mvf_suspend: + +Suspend the processor (eg, wait for interrupt). + +r1: iram_paddr +r2: suspend_iram_base +*************************************************************/ + + .macro mvf_stop_mode_enter + + ldr r3, =MVF_ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* pll7 disable */ + ldr r4, [r3, #0x20] + bic r4, r4, #0x2000 + str r4, [r3, #0x20] + + /* pll3 disable */ + ldr r4, [r3, #0x10] + bic r4, r4, #0x2000 + str r4, [r3, #0x10] + + /* pll4 disable */ + ldr r4, [r3, #0x70] + bic r4, r4, #0x2000 + str r4, [r3, #0x70] + + /* pll6 disable */ + ldr r4, [r3, #0xa0] + bic r4, r4, #0x2000 + str r4, [r3, #0xa0] + + /* pll5 disable */ + ldr r4, [r3, #0xe0] + bic r4, r4, #0x2000 + str r4, [r3, #0xe0] + + /* pll1 disable */ + ldr r4, [r3, #0x270] + bic r4, r4, #0x2000 + str r4, [r3, #0x270] + + /* stop mode is masked to Anatop */ + ldr r3, =MVF_CCM_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + ldr r4, [r3, #0x2c] + bic r4, r4, #0x100 + str r4, [r3, #0x2c] + + ldr r3, =MVF_GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* ensure power domain 0 */ + ldr r4, [r3, #0x0] + bic r4, r4, #0x01 + str r4, [r3, #0x0] + + /* enable deep sleep for memories */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x80 + str r4, [r3, #0x0] + + /* disable well bias */ + ldr r4, [r3, #0x0] + bic r4, r4, #0x10 + str r4, [r3, #0x0] + + /* turn off HPREG in stop mode */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x08 + str r4, [r3, #0x0] + + /* gpc_lpmr set stop mode */ + ldr r4, =0x02 + str r4, [r3, #0x40] + + .endm + + .macro mvf_lpstop_mode_enter + + ldr r3, =MVF_ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* pll7 disable */ + ldr r4, [r3, #0x20] + bic r4, r4, #0x2000 + str r4, [r3, #0x20] + + /* pll3 disable */ + ldr r4, [r3, #0x10] + bic r4, r4, #0x2000 + str r4, [r3, #0x10] + + /* pll4 disable */ + ldr r4, [r3, #0x70] + bic r4, r4, #0x2000 + str r4, [r3, #0x70] + + /* pll6 disable */ + ldr r4, [r3, #0xa0] + bic r4, r4, #0x2000 + str r4, [r3, #0xa0] + + /* pll5 disable */ + ldr r4, [r3, #0xe0] + bic r4, r4, #0x2000 + str r4, [r3, #0xe0] + + /* pll1 disable */ + ldr r4, [r3, #0x270] + bic r4, r4, #0x2000 + str r4, [r3, #0x270] + + ldr r3, =MVF_CCM_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + ldr r4, [r3, #0x2c] + bic r4, r4, #0x100 + str r4, [r3, #0x2c] + + ldr r3, =MVF_GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* enable deep sleep for memories */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x40 + str r4, [r3, #0x0] + + /* enable LPSTOP3 */ + ldr r4, [r3, #0x0] + bic r4, r4, #0x04 + bic r4, r4, #0x02 + str r4, [r3, #0x0] + + /* ensure power domain 1 */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x01 + str r4, [r3, #0x0] + + /* gpc_lpmr set low-power stop mode */ + ldr r4, =0x02 + str r4, [r3, #0x40] + + .endm + +/****************************************************************** +Invalidate l1 dcache, r0-r4, r6, r7 used +******************************************************************/ + .macro invalidate_l1_dcache + + mov r0, #0 + mcr p15, 2, r0, c0, c0, 0 + mrc p15, 1, r0, c0, c0, 0 + + ldr r1, =0x7fff + and r2, r1, r0, lsr #13 + + ldr r1, =0x3ff + + and r3, r1, r0, lsr #3 @ NumWays - 1 + add r2, r2, #1 @ NumSets + + and r0, r0, #0x7 + add r0, r0, #4 @ SetShift + + clz r1, r3 @ WayShift + add r4, r3, #1 @ NumWays +1: + sub r2, r2, #1 @ NumSets-- + mov r3, r4 @ Temp = NumWays +2: + subs r3, r3, #1 @ Temp-- + mov r7, r3, lsl r1 + mov r6, r2, lsl r0 + orr r7, r7, r6 + mcr p15, 0, r7, c7, c6, 2 + bgt 2b + cmp r2, #0 + bgt 1b + dsb + isb + + .endm + +/****************************************************************** +Flush and disable L1 dcache +******************************************************************/ + .macro flush_disable_l1_dcache + + /* + * Flush all data from the L1 data cache before disabling + * SCTLR.C bit. + */ + push {r0-r12, lr} + ldr r0, =v7_flush_dcache_all + mov lr, pc + mov pc, r0 + pop {r0-r12, lr} + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. Clearing SCTLR.C would make all the data accesses + * strongly ordered and would not hit the cache. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Invalidate L1 data cache. Even though only invalidate is + * necessary exported flush API is used here. Doing clean + * on already clean cache would be almost NOP. + */ + push {r0-r12, lr} + ldr r0, =v7_flush_dcache_all + mov lr, pc + mov pc, r0 + pop {r0-r12, lr} + + /* + * Execute an ISB instruction to ensure that all of the + * CP15 register changes have been committed. + */ + isb + + /* + * Execute a barrier instruction to ensure that all cache, + * TLB and branch predictor maintenance operations issued + * by any CPU in the cluster have completed. + */ + dsb + dmb + + .endm + +ENTRY(mvf_suspend) + stmfd sp!, {r0-r12} @ Save registers +/************************************************************* +suspend mode entry +*************************************************************/ + mov r11, r0 + + cmp r0, #0x1 + bne dormant + + /* Need to flush and disable L1 dcache*/ + flush_disable_l1_dcache + + wfi + + nop + nop + nop + nop + + /* Invalidate L1 I-cache first */ + mov r1, #0x0 + mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache + + /* Need to invalidate L1 dcache, as the power is dropped */ + invalidate_l1_dcache + + /* Enable L1 dcache first */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + +/*********************************************************** +never run to here +************************************************************/ + b out /* exit standby */ + /* Place the literal pool here so that literals are + within 16KB range */ + .ltorg + +/************************************************************ +dormant entry, data save in stack +************************************************************/ +dormant: + +/************************************************************ +saved register and context as below: + sp + spsr + lr + CPACR + TTBR0 + TTBR1 + TTBCR + DACR + PRRR + NMRR + ACTLR + Context ID + User r/w thread ID + Secure or NS VBAR + CPSR + SCTLR +************************************************************/ + /* stack is from the tail of iram_suspend base */ + mov r0, r2 /* get suspend_iram_base */ + add r0, r0, #IRAM_SUSPEND_SIZE + + mov r4, r11 @ Store state entered + stmfd r0!, {r4} + + mov r4, sp @ Store sp + mrs r5, spsr @ Store spsr + mov r6, lr @ Store lr + stmfd r0!, {r4-r6} + + /* c1 and c2 registers */ + mrc p15, 0, r4, c1, c0, 2 @ CPACR + mrc p15, 0, r5, c2, c0, 0 @ TTBR0 + mrc p15, 0, r6, c2, c0, 1 @ TTBR1 + mrc p15, 0, r7, c2, c0, 2 @ TTBCR + stmfd r0!, {r4-r7} + + /* c3 and c10 registers */ + mrc p15, 0, r4, c3, c0, 0 @ DACR + mrc p15, 0, r5, c10, c2, 0 @ PRRR + mrc p15, 0, r6, c10, c2, 1 @ NMRR + mrc p15, 0, r7, c1, c0, 1 @ ACTLR + stmfd r0!,{r4-r7} + + /* c12, c13 and CPSR registers */ + mrc p15, 0, r4, c13, c0, 1 @ Context ID + mrc p15, 0, r5, c13, c0, 2 @ User r/w thread ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR + mrs r7, cpsr @ Store CPSR + stmfd r0!, {r4-r7} + + /* c1 control register */ + mrc p15, 0, r4, c1, c0, 0 @ SCTLR + stmfd r0!, {r4} + + /* Need to flush and disable L1 dcache*/ + flush_disable_l1_dcache + + /* Make sure TLBs are primed */ + ldr r1, =MVF_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_SRC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_GPC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + + /* Do a DSB to drain the buffers */ + dsb + + mvf_stop_mode_enter + +/**************************************************************** +execute a wfi instruction to let SOC go into stop mode. +****************************************************************/ + wfi + + nop + nop + nop + nop + +/**************************************************************** +if go here, means there is a wakeup irq pending, we should resume +system immediately. +****************************************************************/ + mov r0, r2 /* get suspend_iram_base */ + add r0, r0, #IRAM_SUSPEND_SIZE + + ldmea r0!, {r11} @ standby or mem + + /* mask all the GPC interrupts */ + ldr r3, =MVF_GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + ldr r4, =0xffffffff + str r4, [r3, #0x44] + str r4, [r3, #0x48] + str r4, [r3, #0x4c] + str r4, [r3, #0x50] + + /* pll2 enable */ + ldr r3, =MVF_ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + ldr r4, [r3, #0x30] + orr r4, r4, #0x2000 + str r4, [r3, #0x30] + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + mrc p15, 0, r1, c1, c0, 0 + orr r1, r1, #(1 << 2) @ Enable the C bit + mcr p15, 0, r1, c1, c0, 0 + + b out + +/************************************************ +return back to mvf_suspend_enter for suspend +*************************************************/ +out: + ldmfd sp!, {r0-r12} + mov pc, lr + + .type mvf_do_suspend, #object +ENTRY(mvf_do_suspend) + .word mvf_suspend + .size mvf_suspend, . - mvf_suspend diff --git a/arch/arm/mach-mvf/pm.c b/arch/arm/mach-mvf/pm.c new file mode 100644 index 000000000000..0e62caf372da --- /dev/null +++ b/arch/arm/mach-mvf/pm.c @@ -0,0 +1,312 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crm_regs.h" +#include "regs-anadig.h" +#include "regs-pm.h" +#include "regs-src.h" + +static struct clk *cpu_clk; +static struct clk *ipg_clk; +static struct clk *periph_clk; + +extern void mvf_suspend(suspend_state_t state); + +static struct device *pm_dev; +static void __iomem *scu_base; +static void __iomem *gpc_base; +static void __iomem *src_base; +static void __iomem *anadig_base; + +static void *suspend_iram_base; +static void (*suspend_in_iram)(suspend_state_t state, + unsigned long iram_paddr, unsigned long suspend_iram_base) = NULL; +static unsigned long iram_paddr, cpaddr; + +static u32 ccm_ccr, ccm_clpcr, ccm_ccsr, scu_ctrl; +static u32 gpc_imr[4], gpc_pgcr, gpc_lpmr; +static u32 ccm_anadig_pfd528, ccm_anadig_pfd480_usb0, ccm_anadig_2p5; +static int g_state; + +static void mvf_suspend_store(void) +{ + /* save some settings before suspend */ + ccm_ccr = __raw_readl(MXC_CCM_CCR); + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR); + ccm_ccsr = __raw_readl(MXC_CCM_CCSR); + ccm_anadig_pfd528 = __raw_readl(PFD_528_BASE_ADDR); + ccm_anadig_pfd480_usb0 = __raw_readl(PFD_480_BASE_ADDR); + ccm_anadig_2p5 = __raw_readl(ANADIG_2P5_ADDR); + + scu_ctrl = __raw_readl(scu_base + SCU_CTRL_OFFSET); + gpc_imr[0] = __raw_readl(gpc_base + GPC_IMR1_OFFSET); + gpc_imr[1] = __raw_readl(gpc_base + GPC_IMR2_OFFSET); + gpc_imr[2] = __raw_readl(gpc_base + GPC_IMR3_OFFSET); + gpc_imr[3] = __raw_readl(gpc_base + GPC_IMR4_OFFSET); + gpc_pgcr = __raw_readl(gpc_base + GPC_PGCR_OFFSET); + gpc_lpmr = __raw_readl(gpc_base + GPC_LPMR_OFFSET); +} + +static void mvf_suspend_restore(void) +{ + /* restore settings after suspend */ + __raw_writel(ccm_anadig_2p5, ANADIG_2P5_ADDR); + + udelay(50); + + __raw_writel(ccm_ccr, MXC_CCM_CCR); + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + __raw_writel(ccm_anadig_pfd528, PFD_528_BASE_ADDR); + __raw_writel(ccm_anadig_pfd480_usb0, PFD_480_BASE_ADDR); + + __raw_writel(scu_ctrl, scu_base + SCU_CTRL_OFFSET); + __raw_writel(gpc_imr[0], gpc_base + GPC_IMR1_OFFSET); + __raw_writel(gpc_imr[1], gpc_base + GPC_IMR2_OFFSET); + __raw_writel(gpc_imr[2], gpc_base + GPC_IMR3_OFFSET); + __raw_writel(gpc_imr[3], gpc_base + GPC_IMR4_OFFSET); + __raw_writel(gpc_pgcr, gpc_base + GPC_PGCR_OFFSET); + __raw_writel(gpc_lpmr, gpc_base + GPC_LPMR_OFFSET); + + /* enable PLLs */ + __raw_writel(__raw_readl(PLL3_480_USB1_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL3_480_USB1_BASE_ADDR); + __raw_writel(__raw_readl(PLL3_480_USB2_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL3_480_USB2_BASE_ADDR); + __raw_writel(__raw_readl(PLL4_AUDIO_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL4_AUDIO_BASE_ADDR); + __raw_writel(__raw_readl(PLL6_VIDEO_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL6_VIDEO_BASE_ADDR); + __raw_writel(__raw_readl(PLL5_ENET_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL5_ENET_BASE_ADDR); + __raw_writel(__raw_readl(PLL1_SYS_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL1_SYS_BASE_ADDR); + + /* restore system clock */ + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); +} + +static void uart_reinit(unsigned long int clkspeed, unsigned long int baud) +{ + void __iomem *membase; + u8 tmp; + u16 sbr, brfa; + + membase = MVF_IO_ADDRESS(MVF_UART1_BASE_ADDR); + + __raw_writeb(0, membase + MXC_UARTMODEM); + + /* make sure the transmitter and receiver are + * disabled while changing settings */ + tmp = __raw_readb(membase + MXC_UARTCR2); + tmp &= ~MXC_UARTCR2_RE; + tmp &= ~MXC_UARTCR2_TE; + __raw_writeb(tmp, membase + MXC_UARTCR2); + + __raw_writeb(0, membase + MXC_UARTCR1); + + sbr = (u16) ((clkspeed * 1000) / (baud * 16)); + brfa = ((clkspeed * 1000) / baud) - (sbr * 16); + + tmp = __raw_readb(membase + MXC_UARTBDH); + tmp &= ~MXC_UARTBDH_SBR_MASK; + tmp |= ((sbr & 0x1f00) >> 8); + __raw_writeb(tmp, membase + MXC_UARTBDH); + tmp = sbr & 0x00ff; + __raw_writeb(tmp, membase + MXC_UARTBDL); + + tmp = __raw_readb(membase + MXC_UARTCR4); + tmp &= ~MXC_UARTCR4_BRFA_MASK; + tmp |= (brfa & MXC_UARTCR4_BRFA_MASK); + __raw_writeb(tmp , membase + MXC_UARTCR4); + + tmp = __raw_readb(membase + MXC_UARTCR2); + tmp |= MXC_UARTCR2_RE; + tmp |= MXC_UARTCR2_TE; + __raw_writeb(tmp, membase + MXC_UARTCR2); +} + +static int mvf_suspend_enter(suspend_state_t state) +{ + struct gic_dist_state gds; + struct gic_cpu_state gcs; + bool arm_pg = false; + + mvf_suspend_store(); + + switch (state) { + case PM_SUSPEND_MEM: + mvf_cpu_lp_set(LOW_POWER_STOP); + g_state = PM_SUSPEND_MEM; + arm_pg = true; + break; + case PM_SUSPEND_STANDBY: + mvf_cpu_lp_set(LOW_POWER_RUN); + g_state = PM_SUSPEND_STANDBY; + arm_pg = true; + break; + default: + return -EINVAL; + } + + if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { + local_flush_tlb_all(); + flush_cache_all(); + + if (arm_pg) { + /* preserve GIC state */ + save_gic_dist_state(0, &gds); + save_gic_cpu_state(0, &gcs); + } + + suspend_in_iram(state, (unsigned long)iram_paddr, + (unsigned long)suspend_iram_base); + + /* reconfigure UART1 when using 24MHz system clock */ + uart_reinit(4000, 115200); + + printk(KERN_DEBUG "Read GPC_PGSR register: %x\n", + __raw_readl(gpc_base + GPC_PGSR_OFFSET)); + + /* mask all interrupts */ + __raw_writel(0xffffffff, gpc_base + GPC_IMR1_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR2_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR3_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR4_OFFSET); + + udelay(80); + + if (arm_pg) { + /* restore GIC registers */ + restore_gic_dist_state(0, &gds); + restore_gic_cpu_state(0, &gcs); + } + + mvf_suspend_restore(); + + /* reconfigure UART1 when using 396MHz system clock */ + uart_reinit(66000, 115200); + + __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, + ANADIG_MISC0_REG); + } else + cpu_do_idle(); + + return 0; +} + +static void mvf_suspend_finish(void) +{ + if (g_state == PM_SUSPEND_MEM) + free_irq(MVF_INT_WKPU0, NULL); +} + +static int mvf_pm_valid(suspend_state_t state) +{ + return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); +} + +const struct platform_suspend_ops mvf_suspend_ops = { + .valid = mvf_pm_valid, + .enter = mvf_suspend_enter, + .finish = mvf_suspend_finish, +}; + +static int __devinit mvf_pm_probe(struct platform_device *pdev) +{ + pm_dev = &pdev->dev; + + return 0; +} + +static struct platform_driver mvf_pm_driver = { + .driver = { + .name = "imx_pm", + }, + .probe = mvf_pm_probe, +}; + +static int __init pm_init(void) +{ + scu_base = MVF_IO_ADDRESS(MVF_SCUGIC_BASE_ADDR); + gpc_base = MVF_GPC_BASE; + anadig_base = MXC_PLL_BASE; + src_base = MVF_IO_ADDRESS(MVF_SRC_BASE_ADDR); + + pr_info("Static Power Management for Freescale Vybrid\n"); + + if (platform_driver_register(&mvf_pm_driver) != 0) { + printk(KERN_ERR "mvf_pm_driver register failed\n"); + return -ENODEV; + } + + suspend_set_ops(&mvf_suspend_ops); + + /* move suspend routine into sram */ + cpaddr = (unsigned long)iram_alloc(SZ_32K, &iram_paddr); + + /* need to remap the area here since we want the memory region + * to be executable */ + suspend_iram_base = __arm_ioremap(iram_paddr, SZ_32K, + MT_MEMORY_NONCACHED); + printk(KERN_DEBUG "cpaddr = %x suspend_iram_base=%x iram_paddr %x\n", + (unsigned int)cpaddr, (unsigned int)suspend_iram_base, + (unsigned int)iram_paddr); + + /* need to run the suspend code from sram */ + memcpy((void *)cpaddr, mvf_suspend, SZ_32K); + + suspend_in_iram = (void *)suspend_iram_base; + + cpu_clk = clk_get(NULL, "cpu_clk"); + if (IS_ERR(cpu_clk)) { + printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__); + return PTR_ERR(cpu_clk); + } + ipg_clk = clk_get(NULL, "ipg_clk"); + if (IS_ERR(ipg_clk)) { + printk(KERN_DEBUG "%s: failed to get ipg_clk\n", __func__); + return PTR_ERR(ipg_clk); + } + periph_clk = clk_get(NULL, "periph_clk"); + if (IS_ERR(periph_clk)) { + printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__); + return PTR_ERR(periph_clk); + } + + printk(KERN_INFO "PM driver module loaded\n"); + return 0; +} + +static void __exit pm_cleanup(void) +{ + platform_driver_unregister(&mvf_pm_driver); +} + +module_init(pm_init); +module_exit(pm_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("PM driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mvf/regs-pm.h b/arch/arm/mach-mvf/regs-pm.h new file mode 100644 index 000000000000..c54bdd346709 --- /dev/null +++ b/arch/arm/mach-mvf/regs-pm.h @@ -0,0 +1,77 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + * + */ + +#ifndef __ARCH_ARM_MACH_MVF_REGS_PM_H__ +#define __ARCH_ARM_MACH_MVF_REGS_PM_H__ + +/* GPC registers */ +#define GPC_PGCR_OFFSET (0x00) +#define GPC_PGCR_DS_STOP (0x000000080) +#define GPC_PGCR_DS_LPSTOP (0x000000040) +#define GPC_PGCR_WB_STOP (0x000000010) +#define GPC_PGCR_HP_OFF (0x000000008) +#define GPC_PGCR_PG_48K (0x000000004) +#define GPC_PGCR_PG_16K (0x000000002) +#define GPC_PGCR_PG_PD1 (0x000000001) + +#define GPC_PGSR_OFFSET (0x0c) + +#define GPC_LPMR_OFFSET (0x40) +#define GPC_LPMR_CLPCR_RUN (0x00000000) +#define GPC_LPMR_CLPCR_WAIT (0x00000001) +#define GPC_LPMR_CLPCR_STOP (0x00000002) + +#define GPC_IMR1_OFFSET (0x44) +#define GPC_IMR2_OFFSET (0x48) +#define GPC_IMR3_OFFSET (0x4c) +#define GPC_IMR4_OFFSET (0x50) +#define GPC_ISR1_OFFSET (0x54) +#define GPC_ISR2_OFFSET (0x58) +#define GPC_ISR3_OFFSET (0x5c) +#define GPC_ISR4_OFFSET (0x60) + +/* VREG registers */ +#define VREG_CTRL_OFFSET (0x00) +#define VREG_CTRL_PORPU (0x00010000) +#define VREG_CTRL_HVDMASK (0x00000001) +#define VREG_STAT_OFFSET (0x04) + +/* WKPU registers */ +#define WKPU_NSR_OFFSET (0x00) + +#define WKPU_NCR_OFFSET (0x08) +#define WKPU_NCR_NLOCK0 (0x80000000) +#define WKPU_NCR_NWRE0 (0x10000000) +#define WKPU_NCR_NREE0 (0x04000000) +#define WKPU_NCR_NFEE0 (0x02000000) +#define WKPU_NCR_NFE0 (0x01000000) + +#define WKPU_WISR_OFFSET (0x14) + +#define WKPU_IRER_OFFSET (0x18) + +#define WKPU_WRER_OFFSET (0x1c) + +#define WKPU_WIREER_OFFSET (0x28) + +#define WKPU_WIFEER_OFFSET (0x2c) + +#define WKPU_WIFER_OFFSET (0x30) + +#define WKPU_WIPUER_OFFSET (0x34) + +#define RISING_EDGE_ENABLED (0x9e) +#define FALLING_EDGE_ENABLED (0xfe) + +/* SCU registers */ +#define SCU_CTRL_OFFSET (0x00) + + +#endif /* __ARCH_ARM_MACH_MVF_REGS_PM_H__ */ diff --git a/arch/arm/mach-mvf/regs-src.h b/arch/arm/mach-mvf/regs-src.h new file mode 100644 index 000000000000..b93e99d92da1 --- /dev/null +++ b/arch/arm/mach-mvf/regs-src.h @@ -0,0 +1,45 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc, + * + * This 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. + + * This 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _SRC_REGISTER_HEADER_ +#define _SRC_REGISTER_HEADER_ + +#define SRC_SCR_OFFSET 0x000 +#define SRC_SBMR_OFFSET 0x004 +#define SRC_SRSR_OFFSET 0x008 +#define SRC_SECR_OFFSET 0x00c +#define SRC_SISR_OFFSET 0x014 +#define SRC_SIMR_OFFSET 0x018 +#define SRC_SBMR2_OFFSET 0x01c +#define SRC_GPR0_OFFSET 0x020 +#define SRC_GPR1_OFFSET 0x024 +#define SRC_GPR2_OFFSET 0x028 +#define SRC_GPR3_OFFSET 0x02c +#define SRC_GPR4_OFFSET 0x030 +#define SRC_HAB0_OFFSET 0x034 +#define SRC_HAB1_OFFSET 0x038 +#define SRC_HAB2_OFFSET 0x03c +#define SRC_HAB3_OFFSET 0x040 +#define SRC_HAB4_OFFSET 0x044 +#define SRC_HAB5_OFFSET 0x048 +#define SRC_MISC0_OFFSET 0x04c +#define SRC_MISC1_OFFSET 0x050 +#define SRC_MISC2_OFFSET 0x054 +#define SRC_MISC3_OFFSET 0x058 + +#endif diff --git a/arch/arm/mach-mvf/system.c b/arch/arm/mach-mvf/system.c index 764c608cbf42..989c75a02ed1 100644 --- a/arch/arm/mach-mvf/system.c +++ b/arch/arm/mach-mvf/system.c @@ -21,7 +21,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -29,6 +30,142 @@ #include #include "crm_regs.h" #include "regs-anadig.h" +#include "regs-pm.h" + +#define SW1_WAKEUP_PIN 38 +#define SW1_PORT1_PCR6_ADDR 0x4004a018 + +static void __iomem *gpc_base = MVF_GPC_BASE; + +void gpc_set_wakeup(void) +{ + __raw_writel(0xffffffff, gpc_base + GPC_IMR1_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR2_OFFSET); + /* unmask WKPU0 interrupt */ + __raw_writel(0xefffffff, gpc_base + GPC_IMR3_OFFSET); + /* unmask GPIO4 interrupt */ + __raw_writel(0xffff7fff, gpc_base + GPC_IMR4_OFFSET); + + return; +} + +void enable_wkpu(u32 source, u32 rise_fall) +{ + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_IRER_OFFSET); + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WRER_OFFSET); + + if (rise_fall == RISING_EDGE_ENABLED) + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WIREER_OFFSET); + else + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WIFEER_OFFSET); +} + +static irqreturn_t wkpu_irq(int irq, void *dev_id) +{ + u32 wisr; + + wisr = __raw_readl(MVF_WKPU_BASE + WKPU_WISR_OFFSET); + if (wisr) + __raw_writel(wisr, MVF_WKPU_BASE + WKPU_WISR_OFFSET); + + return IRQ_NONE; +} + +/* set cpu multiple modes before WFI instruction */ +void mvf_cpu_lp_set(enum mvf_cpu_pwr_mode mode) +{ + u32 ccm_ccsr, ccm_clpcr, ccm_ccr; + u32 tmp; + int ret; + + if ((mode == LOW_POWER_STOP) || (mode == STOP_MODE)) { + /* config SW1 for waking up system */ + gpio_request_one(SW1_WAKEUP_PIN, GPIOF_IN, "SW1 wakeup"); + gpio_set_value(SW1_WAKEUP_PIN, 0); + /* PORT1_PCR6 IRQC interrupt/dma request disabled */ + tmp = __raw_readl(MVF_IO_ADDRESS(SW1_PORT1_PCR6_ADDR)); + tmp &= ~0x000f0000; + __raw_writel(tmp, MVF_IO_ADDRESS(SW1_PORT1_PCR6_ADDR)); + + ret = request_irq(MVF_INT_WKPU0, wkpu_irq, + IRQF_DISABLED, "wkpu irq", NULL); + if (ret) + printk(KERN_ERR "Request wkpu IRQ failed\n"); + + /* enable WKPU interrupt */ + enable_wkpu(11, FALLING_EDGE_ENABLED); + } + + ccm_ccr = __raw_readl(MXC_CCM_CCR); + ccm_ccsr = __raw_readl(MXC_CCM_CCSR); + + switch (mode) { + case WAIT_MODE: + break; + case LOW_POWER_RUN: + ccm_ccr |= MXC_CCM_CCR_FIRC_EN; + __raw_writel(ccm_ccr, MXC_CCM_CCR); + ccm_ccsr &= ~MXC_CCM_CCSR_FAST_CLK_SEL_MASK; + ccm_ccsr &= ~MXC_CCM_CCSR_SLOW_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + /* switch system clock to FIRC 24MHz */ + ccm_ccsr &= ~MXC_CCM_CCSR_SYS_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + __raw_writel(__raw_readl(PLL3_480_USB1_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL3_480_USB1_BASE_ADDR); + __raw_writel(__raw_readl(PLL3_480_USB2_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL3_480_USB2_BASE_ADDR); + __raw_writel(__raw_readl(PLL4_AUDIO_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL4_AUDIO_BASE_ADDR); + __raw_writel(__raw_readl(PLL6_VIDEO_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL6_VIDEO_BASE_ADDR); + __raw_writel(__raw_readl(PLL5_ENET_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL5_ENET_BASE_ADDR); + __raw_writel(__raw_readl(PLL1_SYS_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL1_SYS_BASE_ADDR); + break; + case STOP_MODE: + case LOW_POWER_STOP: + gpc_set_wakeup(); + + /* unmask UART1 in low-power mode */ + __raw_writel(0xfffeffff, MXC_CCM_CCGR0); + /* unmask WKUP and GPC in low-power mode */ + __raw_writel(0xfeefffff, MXC_CCM_CCGR4); + /* unmask DDRC in low-power mode */ + __raw_writel(0xefffffff, MXC_CCM_CCGR6); + + ccm_ccr |= MXC_CCM_CCR_FIRC_EN; + __raw_writel(ccm_ccr, MXC_CCM_CCR); + ccm_ccsr &= ~MXC_CCM_CCSR_FAST_CLK_SEL_MASK; + ccm_ccsr &= ~MXC_CCM_CCSR_SLOW_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + /* switch system clock to FIRC 24MHz */ + ccm_ccsr &= ~MXC_CCM_CCSR_SYS_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + /* on-chip oscillator will not be + * powered down in stop mode */ + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR); + ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; + ccm_clpcr &= ~MXC_CCM_CLPCR_M_CORE1_WFI; + ccm_clpcr &= ~MXC_CCM_CLPCR_M_CORE0_WFI; + ccm_clpcr &= ~MXC_CCM_CLPCR_ARM_CLK_LPM; + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + + /* mask stop mode to Anatop */ + __raw_writel(ccm_clpcr & ~MXC_CCM_CLPCR_ANATOP_STOP_MODE, + MXC_CCM_CLPCR); + + break; + default: + printk(KERN_WARNING "UNKNOW cpu power mode: %d\n", mode); + return; + } +} void arch_idle(void) { -- cgit v1.2.3 From 3bb1551c08e3a5b0303bd0a4f52d048ee75cee65 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Mon, 10 Dec 2012 13:09:42 +0800 Subject: ENGR00216087-2:Add Vybrid ASRC platform device Signed-off-by: Jingchang Lu --- arch/arm/mach-mvf/board-twr-vf700.c | 9 +++++++++ arch/arm/mach-mvf/clock.c | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index 5903f7ae0244..d9d0ff6161dd 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -426,6 +426,11 @@ static struct led_pwm_platform_data mvf_led_data __initdata = { .leds = &mvf_led, }; +static struct imx_asrc_platform_data imx_asrc_data = { + .channel_bits = 4, + .clk_map_ver = 3, +}; + static void __init mvf_twr_init_usb(void) { imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); @@ -483,6 +488,10 @@ static void __init mvf_board_init(void) mvf_add_mxc_pwm(0); mvf_add_pwm_leds(&mvf_led_data); + imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); + imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); + mvf_add_asrc(&imx_asrc_data); + } static void __init mvf_timer_init(void) diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index cfcea6eccff2..140f0edee565 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1818,6 +1818,29 @@ static struct clk qspi1_clk = { .get_rate = _clk_qspi1_get_rate, }; +static int _clk_asrc_serial_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +static struct clk asrc_clk[] = { + { + __INIT_CLK_DEBUG(asrc_clk) + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(asrc_serial_clk) + .id = 1, + .parent = &audio_external_clk, + .set_rate = _clk_asrc_serial_set_rate, + }, +}; + static struct clk dummy_clk = { .id = 0, }; @@ -1874,6 +1897,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "mvf-usb.1", usb_phy1_clk), _REGISTER_CLOCK(NULL, "pwm", ftm_pwm_clk), _REGISTER_CLOCK("mvf-qspi.0", NULL, qspi0_clk), + _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk[0]), + _REGISTER_CLOCK(NULL, "asrc_serial_clk", asrc_clk[1]), }; static void clk_tree_init(void) -- cgit v1.2.3 From 051e157a7bcacf3d4f84289c2e8cc561ecb4a3c3 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Fri, 7 Dec 2012 17:28:16 +0800 Subject: ENGR00216081-1:Add USB host and gadget PM support Handle usb suspend/resume, currently the BSP doesn't support usb plug/unplug wakeup. Signed-off-by: Jingchang Lu --- arch/arm/mach-mvf/board-twr-vf700.c | 6 +- arch/arm/mach-mvf/devices-mvf.h | 8 +- arch/arm/mach-mvf/usb_dr.c | 198 +++++++++++++++++++++++++++++++++++- arch/arm/mach-mvf/usb_dr2.c | 181 +++++++++++++++++++++++++++++++- 4 files changed, 385 insertions(+), 8 deletions(-) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index d9d0ff6161dd..a267df7a303f 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -435,12 +435,12 @@ static void __init mvf_twr_init_usb(void) { imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); /*mvf_set_otghost_vbus_func(mvf_twr_usbotg_vbus);*/ -#ifdef CONFIG_USB_GADGET_ARC - mvf_usb_dr_init(); -#endif #ifdef CONFIG_USB_EHCI_ARC mvf_usb_dr2_init(); #endif +#ifdef CONFIG_USB_GADGET_ARC + mvf_usb_dr_init(); +#endif } /*! diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index 61792fb34530..b8bea993bdee 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -69,9 +69,11 @@ extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; imx_add_fsl_usb2_otg(&mvf_fsl_usb2_otg_data, pdata) extern -const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data __initconst; -#define mvf_add_fsl_usb2_otg_wakeup(pdata) \ - imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data, pdata) +const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst; +#define mvf_add_fsl_usb2_ehci_otg_wakeup(pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[1], pdata) +#define mvf_add_fsl_usb2_udc_wakeup(pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[0], pdata) extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_hs_wakeup_data[] __initconst; diff --git a/arch/arm/mach-mvf/usb_dr.c b/arch/arm/mach-mvf/usb_dr.c index 2467acc1bf28..bbd29f3b45a9 100644 --- a/arch/arm/mach-mvf/usb_dr.c +++ b/arch/arm/mach-mvf/usb_dr.c @@ -35,6 +35,7 @@ static int usbotg_init_ext(struct platform_device *pdev); static void usbotg_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); +static void usbotg_wakeup_event_clear(void); /* The usb_phy0_clk do not have enable/disable function at clock.c * and PLL output for usb0's phy should be always enabled. @@ -62,6 +63,13 @@ static struct fsl_usb2_platform_data dr_utmi_config = { .dr_discharge_line = _dr_discharge_line, }; +/* Platform data for wakeup operation */ +static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = { + .name = "Gadget wakeup", + .usb_clock_for_pm = usbotg_clock_gate, + .usb_wakeup_exhandle = usbotg_wakeup_event_clear, +}; + static void usbotg_internal_phy_clock_gate(bool on) { u32 reg; @@ -183,25 +191,213 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) +static u32 low_power_enable_src; /* only useful at otg mode */ +static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; + pr_debug("DR: %s begins, enable is %d\n", __func__, enable); + + if (enable) { + UOG_PORTSC1 |= PORTSC_PHCD; + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET); + usbotg_internal_phy_clock_gate(false); + + } else { + if (UOG_PORTSC1 & PORTSC_PHCD) { + UOG_PORTSC1 &= ~PORTSC_PHCD; + mdelay(1); + } + usbotg_internal_phy_clock_gate(true); + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); + + } + pr_debug("DR: %s ends, enable is %d\n", __func__, enable); +} + +static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable, int source) +{ + if (enable) { + low_power_enable_src |= source; + enter_phy_lowpower_suspend(pdata, enable); + } else { + enter_phy_lowpower_suspend(pdata, enable); + low_power_enable_src &= ~source; + } +} + +static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + + pr_debug("%s, enable is %d\n", __func__, enable); + if (enable) { + __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP + | BM_USBPHY_CTRL_ENVBUSCHG_WKUP + | BM_USBPHY_CTRL_ENDPDMCHG_WKUP + | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS + | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD + | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE + | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE + | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL, + phy_reg + HW_USBPHY_CTRL_SET); + USBC0_CTRL |= UCTRL_OWIE; + } else { + USBC0_CTRL &= ~UCTRL_OWIE; + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, + bool on, int source) +{ + /* otg host and device share the OWIE bit, only when host and device + * all enable the wakeup irq, we can enable the OWIE bit + */ + if (on) { + otg_wake_up_enable(pdata, on); + } else { + otg_wake_up_enable(pdata, on); + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +/* The wakeup operation for DR port, it will clear the wakeup irq status + * and re-enable the wakeup + */ +static void usbotg_wakeup_event_clear(void) +{ + int wakeup_req = USBC0_CTRL & UCTRL_OWIR; + + if (wakeup_req != 0) { + pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC); + /* Disable OWIE to clear OWIR, wait 3 clock + * cycles of standly clock(32KHz) + */ + USBC0_CTRL &= ~UCTRL_OWIE; + udelay(100); + USBC0_CTRL |= UCTRL_OWIE; + } +} +/* End of Common operation for DR port */ #ifdef CONFIG_USB_EHCI_ARC_OTG #endif /* CONFIG_USB_EHCI_ARC_OTG */ #ifdef CONFIG_USB_GADGET_ARC +/* Beginning of device related operation for DR port */ +static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE); +} + +static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __wakeup_irq_enable(pdata, enable, ENABLED_BY_DEVICE); + if (enable) { + pr_debug("device wakeup enable\n"); + device_wakeup_enable(&pdata->pdev->dev); + } else { + pr_debug("device wakeup disable\n"); + device_wakeup_disable(&pdata->pdev->dev); + } +} + +static enum usb_wakeup_event +_is_device_wakeup(struct fsl_usb2_platform_data *pdata) +{ + int wakeup_req = USBC0_CTRL & UCTRL_OWIR; + + /* if ID=1, it is a device wakeup event */ + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && + (UOG_USBSTS & USBSTS_URI)) { + printk(KERN_INFO "otg udc wakeup, host sends reset signal\n"); + return WAKEUP_EVENT_DPDM; + } + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && \ + ((UOG_USBSTS & USBSTS_PCI) || + (UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME))) { + /* + * When the line state from J to K, the Port Change Detect bit + * in the USBSTS register is also set to '1'. + */ + printk(KERN_INFO "otg udc wakeup, host sends resume signal\n"); + return WAKEUP_EVENT_DPDM; + } + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && + (UOG_OTGSC & OTGSC_STS_A_VBUS_VALID) && + (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) { + printk(KERN_INFO "otg udc vbus rising wakeup\n"); + return WAKEUP_EVENT_VBUS; + } + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && + !(UOG_OTGSC & OTGSC_STS_A_VBUS_VALID)) { + printk(KERN_INFO "otg udc vbus falling wakeup\n"); + return WAKEUP_EVENT_VBUS; + } + + return WAKEUP_EVENT_DPDM; +} + +static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata) +{ + _device_phy_lowpower_suspend(pdata, false); + _device_wakeup_enable(pdata, false); +} +/* end of device related operation for DR port */ #endif /* CONFIG_USB_GADGET_ARC */ void __init mvf_usb_dr_init(void) { - struct platform_device *pdev; + struct platform_device *pdev, *pdev_wakeup; u32 reg; #ifdef CONFIG_USB_GADGET_ARC dr_utmi_config.operating_mode = DR_UDC_MODE; + dr_utmi_config.wake_up_enable = _device_wakeup_enable; dr_utmi_config.platform_suspend = NULL; dr_utmi_config.platform_resume = NULL; + dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend; + dr_utmi_config.is_wakeup_event = _is_device_wakeup; + dr_utmi_config.wakeup_pdata = &dr_wakeup_config; + dr_utmi_config.wakeup_handler = device_wakeup_handler; pdev = mvf_add_fsl_usb2_udc(&dr_utmi_config); + dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data; + + /* register wakeup device */ + pdev_wakeup = mvf_add_fsl_usb2_udc_wakeup(&dr_wakeup_config); + if (pdev != NULL) + ((struct fsl_usb2_platform_data *) + (pdev->dev.platform_data))->wakeup_pdata = + (struct fsl_usb2_wakeup_platform_data *) + (pdev_wakeup->dev.platform_data); + + device_set_wakeup_capable(&pdev->dev, true); __raw_writel(((0x01 << 30) | 0x2), ANADIG_USB1_MISC); __raw_writel(0x00000894, USBPHY1_CTRL); diff --git a/arch/arm/mach-mvf/usb_dr2.c b/arch/arm/mach-mvf/usb_dr2.c index d26cfde125e0..67e3fcdbc921 100644 --- a/arch/arm/mach-mvf/usb_dr2.c +++ b/arch/arm/mach-mvf/usb_dr2.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ static int usbotg2_init_ext(struct platform_device *pdev); static void usbotg2_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); +static void usbotg_wakeup_event_clear(void); static struct clk *usb_phy1_clk; static u8 otg2_used; @@ -58,6 +60,13 @@ static struct fsl_usb2_platform_data dr_utmi_config = { .dr_discharge_line = _dr_discharge_line, }; +/* Platform data for wakeup operation */ +static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = { + .name = "Host wakeup", + .usb_clock_for_pm = usbotg_clock_gate, + .usb_wakeup_exhandle = usbotg_wakeup_event_clear, +}; + static void usbotg_internal_phy_clock_gate(bool on) { void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY1_BASE_ADDR); @@ -181,6 +190,113 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) +static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY1_BASE_ADDR); + u32 tmp; + pr_debug("DR: %s begins, enable is %d\n", __func__, enable); + + if (enable) { + UOG2_PORTSC1 |= PORTSC_PHCD; + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET); + usbotg_internal_phy_clock_gate(false); + + } else { + if (UOG2_PORTSC1 & PORTSC_PHCD) { + UOG2_PORTSC1 &= ~PORTSC_PHCD; + mdelay(1); + } + usbotg_internal_phy_clock_gate(true); + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); + + } + pr_debug("DR: %s ends, enable is %d\n", __func__, enable); +} + +static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable, int source) +{ + if (enable) + enter_phy_lowpower_suspend(pdata, enable); + else { + pr_debug("phy lowpower disable\n"); + enter_phy_lowpower_suspend(pdata, enable); + } +} + +static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY1_BASE_ADDR); + + pr_debug("%s, enable is %d\n", __func__, enable); + if (enable) { + __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP + | BM_USBPHY_CTRL_ENVBUSCHG_WKUP + | BM_USBPHY_CTRL_ENDPDMCHG_WKUP + | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS + | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD + | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE + | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE + | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL, + phy_reg + HW_USBPHY_CTRL_SET); + USBC1_CTRL |= UCTRL_OWIE; + } else { + USBC1_CTRL &= ~UCTRL_OWIE; + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, + bool on, int source) +{ + pr_debug("USB Host %s,on=%d\n", __func__, on); + mdelay(3); + if (on) { + otg_wake_up_enable(pdata, on); + } else { + otg_wake_up_enable(pdata, on); + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +/* The wakeup operation for DR port, it will clear the wakeup irq status + * and re-enable the wakeup + */ +static void usbotg_wakeup_event_clear(void) +{ + int wakeup_req = USBC1_CTRL & UCTRL_OWIR; + + if (wakeup_req != 0) { + pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC); + /* Disable OWIE to clear OWIR, wait 3 clock + * cycles of standly clock(32KHz) + */ + USBC1_CTRL &= ~UCTRL_OWIE; + udelay(100); + USBC1_CTRL |= UCTRL_OWIE; + } +} + /* End of Common operation for DR port */ #ifdef CONFIG_USB_EHCI_ARC_OTG @@ -215,22 +331,85 @@ static void _host_platform_resume(struct fsl_usb2_platform_data *pdata) __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); } +static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST); +} + +static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST); + + if (enable) + device_wakeup_enable(&pdata->pdev->dev); + else + device_wakeup_disable(&pdata->pdev->dev); +} + +static enum usb_wakeup_event +_is_host_wakeup(struct fsl_usb2_platform_data *pdata) +{ + u32 wakeup_req = USBC1_CTRL & UCTRL_OWIR; + u32 otgsc = UOG2_OTGSC; + + if (wakeup_req) { + pr_debug("the otgsc is 0x%x, usbsts is 0x%x," + " portsc is 0x%x, wakeup_irq is 0x%x\n", + UOG2_OTGSC, UOG2_USBSTS, UOG2_PORTSC1, wakeup_req); + } + /* if ID change sts, it is a host wakeup event */ + if (wakeup_req && (otgsc & OTGSC_IS_USB_ID)) { + pr_debug("otg host ID wakeup\n"); + /* if host ID wakeup, we must clear the b session change sts */ + otgsc &= (~OTGSC_IS_USB_ID); + return WAKEUP_EVENT_ID; + } + if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) { + pr_debug("otg host Remote wakeup\n"); + return WAKEUP_EVENT_DPDM; + } + return WAKEUP_EVENT_INVALID; +} + +static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata) +{ + _host_phy_lowpower_suspend(pdata, false); + _host_wakeup_enable(pdata, false); +} + /* End of host related operation for DR port */ #endif /* CONFIG_USB_EHCI_ARC_OTG */ void __init mvf_usb_dr2_init(void) { - struct platform_device *pdev; + struct platform_device *pdev, *pdev_wakeup; u32 reg; #ifdef CONFIG_USB_EHCI_ARC_OTG dr_utmi_config.operating_mode = DR_HOST_MODE; + dr_utmi_config.wake_up_enable = _host_wakeup_enable; dr_utmi_config.platform_suspend = _host_platform_suspend; dr_utmi_config.platform_resume = _host_platform_resume; + dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend; + dr_utmi_config.is_wakeup_event = _is_host_wakeup; + dr_utmi_config.wakeup_pdata = &dr_wakeup_config; + dr_utmi_config.wakeup_handler = host_wakeup_handler; pdev = mvf_add_fsl_ehci_otg(&dr_utmi_config); + dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data; + + /* register wakeup device */ + pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(&dr_wakeup_config); + if (pdev != NULL) + ((struct fsl_usb2_platform_data *) + (pdev->dev.platform_data))->wakeup_pdata = + (struct fsl_usb2_wakeup_platform_data *) + (pdev_wakeup->dev.platform_data); + __raw_writel(0x0220C802, USBPHY2_CTRL); udelay(20); -- cgit v1.2.3 From 3664f4e8ca3d18e87bc695f4b6838be61382dc17 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Mon, 10 Dec 2012 18:35:41 +0800 Subject: ENGR00181365-1: ADC: Add platform support for ADC driver Add platform support for ADC driver. Signed-off-by: Wang Xiaojun --- arch/arm/mach-mvf/board-twr-vf700.c | 7 +++++++ arch/arm/mach-mvf/clock.c | 13 +++++++++++++ arch/arm/mach-mvf/devices-mvf.h | 4 ++++ 3 files changed, 24 insertions(+) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index a267df7a303f..d64622b2db19 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -443,6 +443,11 @@ static void __init mvf_twr_init_usb(void) #endif } +static void __init mvf_init_adc(void) +{ + mvf_add_adc(0); +} + /*! * Board specific initialization. */ @@ -462,6 +467,8 @@ static void __init mvf_board_init(void) mvf_add_snvs_rtc(); + mvf_init_adc(); + mvf_add_pm_imx(0, &mvf_vf600_pm_data); mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data); diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 140f0edee565..16d86fb73368 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1626,6 +1626,18 @@ static struct clk pit_clk = { .get_rate = _clk_uart_get_rate, }; +static struct clk adc_clk[] = { + { + __INIT_CLK_DEBUG(adc_clk) + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + static struct clk i2c_clk[] = { { __INIT_CLK_DEBUG(i2c_clk_0) @@ -1886,6 +1898,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("pit", NULL, pit_clk), _REGISTER_CLOCK("fec.0", NULL, enet_clk[0]), _REGISTER_CLOCK("fec.1", NULL, enet_clk[1]), + _REGISTER_CLOCK("mvf-adc.0", NULL, adc_clk[0]), _REGISTER_CLOCK("switch.0", NULL, enet_clk[0]), _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk), _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc1_clk), diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index b8bea993bdee..6bc61871fd5e 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -144,6 +144,10 @@ extern const struct imx_imx2_wdt_data mvf_imx2_wdt_data[] __initconst; #define mvf_add_imx2_wdt(id, pdata) \ imx_add_imx2_wdt(&mvf_imx2_wdt_data[id]) +extern const struct mvf_adc_data mvfa5_adc_data[] __initconst; +#define mvf_add_adc(id) \ + mvf_add_adcdev(&mvfa5_adc_data[id]) + extern const struct imx_imx2_wdt_data fsl_imx2_wdt_data[] __initconst; #define mvf_add_wdt(id) \ imx_add_imx2_wdt(&fsl_imx2_wdt_data[id]) -- cgit v1.2.3 From da9fd56e1e47c7773c8dfc4db445e3d1852d5aa5 Mon Sep 17 00:00:00 2001 From: Jason Jin Date: Tue, 11 Dec 2012 18:25:40 +0800 Subject: Vybrid CAAM driver From Singh Pradip-B09147. Integrate by Jason Jin Signed-off-by: Jason Jin --- arch/arm/mach-mvf/Kconfig | 1 + arch/arm/mach-mvf/board-twr-vf700.c | 2 ++ arch/arm/mach-mvf/clock.c | 10 +++++++++- arch/arm/mach-mvf/devices-mvf.h | 4 ++++ 4 files changed, 16 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig index 10ec5b6307df..931ef6af6dd4 100644 --- a/arch/arm/mach-mvf/Kconfig +++ b/arch/arm/mach-mvf/Kconfig @@ -54,6 +54,7 @@ config MACH_MVFA5_TWR_VF700 select IMX_HAVE_PLATFORM_MVF_DCU select IMX_HAVE_PLATFORM_MVF_SAI select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MVF_CAAM help Include support for MVF TWR-VF700 platform. This includes specific configurations for the board and its peripherals. diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index d64622b2db19..01fd4dc364cc 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -471,6 +471,8 @@ static void __init mvf_board_init(void) mvf_add_pm_imx(0, &mvf_vf600_pm_data); + mvf700_add_caam(); + mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data); mvf_add_imx_i2c(0, &mvf600_i2c_data); diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 16d86fb73368..5ac0ff1766fb 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1613,6 +1613,14 @@ static struct clk clko2_clk = { .get_rate = _clk_clko2_get_rate, .round_rate = _clk_clko_round_rate, }; +static struct clk caam_clk = { + __INIT_CLK_DEBUG(caam_clk) + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR11, + .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; static struct clk pit_clk = { __INIT_CLK_DEBUG(pit_clk) @@ -1912,10 +1920,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mvf-qspi.0", NULL, qspi0_clk), _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk[0]), _REGISTER_CLOCK(NULL, "asrc_serial_clk", asrc_clk[1]), + _REGISTER_CLOCK(NULL, "caam_clk", caam_clk), }; static void clk_tree_init(void) - { unsigned int reg = 0xffffffff; diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index 6bc61871fd5e..c434834ba0b2 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -224,3 +224,7 @@ extern const struct imx_epdc_data mvf_epdc_data __initconst; #define mvf_add_pwm_leds(pdata) \ imx_add_platform_device("leds_pwm", 0, NULL, 0, pdata, sizeof(*pdata)) + +extern const struct mvf_caam_data mvf_caam_data __initconst; +#define mvf700_add_caam() \ + mvf_add_caam(&mvf_caam_data) -- cgit v1.2.3 From 9d7ee1114441401aee095ca522d75ed530e2e894 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Tue, 27 Nov 2012 10:52:37 -0800 Subject: Initial phyCORE-Vybrid changes Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/Kconfig | 33 +++ arch/arm/mach-mvf/Makefile | 1 + arch/arm/mach-mvf/board-pcm052.c | 564 +++++++++++++++++++++++++++++++++++++++ arch/arm/mach-mvf/clock.c | 36 ++- 4 files changed, 630 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-mvf/board-pcm052.c (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig index 931ef6af6dd4..0ef1f8a09d37 100644 --- a/arch/arm/mach-mvf/Kconfig +++ b/arch/arm/mach-mvf/Kconfig @@ -59,4 +59,37 @@ config MACH_MVFA5_TWR_VF700 Include support for MVF TWR-VF700 platform. This includes specific configurations for the board and its peripherals. +config MACH_PCM052 + bool "Support phyCORE-Vybrid (MVF Cortex-A5) platform" + select ARCH_MVFA5 + select SOC_MVFA5 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_DMA + select IMX_HAVE_PLATFORM_FEC + select IMX_HAVE_PLATFORM_GPMI_NFC + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_VIV_GPU + select IMX_HAVE_PLATFORM_IMX_VPU + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_FSL_OTG + select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP + select IMX_HAVE_PLATFORM_AHCI + select IMX_HAVE_PLATFORM_IMX_OCOTP + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_SNVS_RTC + select IMX_HAVE_PLATFORM_IMX_PM + select IMX_HAVE_PLATFORM_MXC_HDMI + select IMX_HAVE_PLATFORM_IMX_ASRC + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_MVF_SPI + select IMX_HAVE_PLATFORM_MVF_DCU + select IMX_HAVE_PLATFORM_MVF_SAI + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for PHYTEC phyCORE-Vybrid platform. This includes + specific configurations for the board and its peripherals. + endif diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile index e25fb28b7216..fad70a4a9dc7 100644 --- a/arch/arm/mach-mvf/Makefile +++ b/arch/arm/mach-mvf/Makefile @@ -8,3 +8,4 @@ obj-y += l2switch.o obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o obj-$(CONFIG_MACH_MVFA5_TWR_VF700) += board-twr-vf700.o +obj-$(CONFIG_MACH_PCM052) += board-pcm052.o diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c new file mode 100644 index 000000000000..dc583b4a69f5 --- /dev/null +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -0,0 +1,564 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + + * This 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "devices-mvf.h" +#include "usb.h" +#include "crm_regs.h" + +#define PCM052_SD1_CD 85 +#define PCM052_TS_IRQ 32 + +#ifdef PCM952_REV0 +#undef PCM952_REV0 +#endif + +static iomux_v3_cfg_t pcm052_pads[] = { + + /*SDHC1*/ + MVF600_PAD14_PTA24__SDHC1_CLK, + MVF600_PAD15_PTA25__SDHC1_CMD, + MVF600_PAD16_PTA26__SDHC1_DAT0, + MVF600_PAD17_PTA27__SDHC1_DAT1, + MVF600_PAD18_PTA28__SDHC1_DAT2, + MVF600_PAD19_PTA29__SDHC1_DAT3, + /*set PTD6 as GPIO for sdhc card detecting*/ + MVF600_PAD85_PTD6__SDHC1_SW_CD, + + /*I2C2*/ + MVF600_PAD12_PTA22__I2C2_SCL, + MVF600_PAD13_PTA23__I2C2_SDA, + + /*CAN0*/ + MVF600_PAD36_PTB14__CAN0_RX, + MVF600_PAD37_PTB15__CAN0_TX, + + /*CAN1*/ + MVF600_PAD38_PTB16__CAN1_RX, + MVF600_PAD39_PTB17__CAN1_TX, + + /*DSPI0*/ + MVF600_PAD41_PTB19__DSPI0_PCS0, + MVF600_PAD42_PTB20__DSPI0_SIN, + MVF600_PAD43_PTB21__DSPI0_SOUT, + MVF600_PAD44_PTB22__DSPI0_SCK, + + /*FEC0*/ + MVF600_PAD0_PTA6__RMII_CLKIN, + MVF600_PAD45_PTC0__RMII0_MDC, + MVF600_PAD46_PTC1__RMII0_MDIO, + MVF600_PAD47_PTC2__RMII0_CRS_DV, + MVF600_PAD48_PTC3__RMII0_RXD1, + MVF600_PAD49_PTC4__RMII0_RXD0, + MVF600_PAD50_PTC5__RMII0_RXER, + MVF600_PAD51_PTC6__RMII0_TXD1, + MVF600_PAD52_PTC7__RMII0_TXD0, + MVF600_PAD53_PTC8__RMII0_TXEN, + +#if defined(CONFIG_FEC1) || defined(CONFIG_FSL_L2_SWITCH) + /*FEC1*/ + MVF600_PAD54_PTC9__RMII1_MDC, + MVF600_PAD55_PTC10__RMII1_MDIO, + MVF600_PAD56_PTC11__RMII1_CRS_DV, + MVF600_PAD57_PTC12__RMII1_RXD1, + MVF600_PAD58_PTC13__RMII1_RXD0, + MVF600_PAD59_PTC14__RMII1_RXER, + MVF600_PAD60_PTC15__RMII1_TXD1, + MVF600_PAD61_PTC16__RMII1_TXD0, + MVF600_PAD62_PTC17__RMII1_TXEN, +#endif + + /*SAI2*/ +// MVF600_PAD6_PTA16_SAI2_TX_BCLK, + MVF600_PAD8_PTA18_SAI2_TX_DATA, +// MVF600_PAD3_PTA10_SAI2_TX_SYNC, // originally PAD9_PTA19 + MVF600_PAD11_PTA21_SAI2_RX_BCLK, +// MVF600_PAD23_PTB1_SAI2_RX_DATA, // originally PAD12_PTA22 +// MVF600_PAD13_PTA23_SAI2_RX_SYNC, // UNUSED +// MVF600_PAD40_PTB18_EXT_AUDIO_MCLK, // UNUSED +// MVF600_PAD33_PTB11__CKO2, // phyCORE MCLK + + /*DCU0*/ + MVF600_PAD25_PTB3_LCD_ENABLE, + MVF600_PAD105_PTE0_DCU0_HSYNC, + MVF600_PAD106_PTE1_DCU0_VSYNC, + MVF600_PAD107_PTE2_DCU0_PCLK, + MVF600_PAD109_PTE4_DCU0_DE, + MVF600_PAD110_PTE5_DCU0_R0, + MVF600_PAD111_PTE6_DCU0_R1, + MVF600_PAD112_PTE7_DCU0_R2, + MVF600_PAD113_PTE8_DCU0_R3, + MVF600_PAD114_PTE9_DCU0_R4, + MVF600_PAD115_PTE10_DCU0_R5, + MVF600_PAD116_PTE11_DCU0_R6, + MVF600_PAD117_PTE12_DCU0_R7, + MVF600_PAD118_PTE13_DCU0_G0, + MVF600_PAD119_PTE14_DCU0_G1, + MVF600_PAD120_PTE15_DCU0_G2, + MVF600_PAD121_PTE16_DCU0_G3, + MVF600_PAD122_PTE17_DCU0_G4, + MVF600_PAD123_PTE18_DCU0_G5, + MVF600_PAD124_PTE19_DCU0_G6, + MVF600_PAD125_PTE20_DCU0_G7, + MVF600_PAD126_PTE21_DCU0_B0, + MVF600_PAD127_PTE22_DCU0_B1, + MVF600_PAD128_PTE23_DCU0_B2, + MVF600_PAD129_PTE24_DCU0_B3, + MVF600_PAD130_PTE25_DCU0_B4, + MVF600_PAD131_PTE26_DCU0_B5, + MVF600_PAD132_PTE27_DCU0_B6, + MVF600_PAD133_PTE28_DCU0_B7, + + /*UART1*/ + MVF600_PAD26_PTB4_UART1_TX, + MVF600_PAD27_PTB5_UART1_RX, + + /*USB0/1 VBUS_EN*/ +#ifdef PCM952_REV0 + MVF600_PAD6_PTA16__USB0_VBUS_EN, +#else + MVF600_PAD134_PTA7__USB0_VBUS_EN, +#endif + MVF600_PAD7_PTA17__USB_OC_N, + + /* + * FlexTimer PWM channels + * FTM0 CH0~3 are connected to demo LED0~3 + * PAD30 mux with LCD enable signal + */ + MVF600_PAD22_PTB0_FTM0CH0, + MVF600_PAD23_PTB1_FTM0CH1, + MVF600_PAD24_PTB2_FTM0CH2, +// MVF600_PAD25_PTB3_FTM0CH3, + + MVF600_PAD28_PTB6_FTM0CH6, + MVF600_PAD29_PTB7_FTM0CH7, + /*MVF600_PAD30_PTB8_FTM1CH0,*/ + MVF600_PAD31_PTB9_FTM1CH1, + + /* Touch Screen */ + MVF600_PAD32_PTB10_TS_IRQ, + + /* Quad SPI */ + MVF600_PAD79_PTD0_QSPI0_A_SCK, + MVF600_PAD80_PTD1_QSPI0_A_CS0, + MVF600_PAD81_PTD2_QSPI0_A_D3, + MVF600_PAD82_PTD3_QSPI0_A_D2, + MVF600_PAD83_PTD4_QSPI0_A_D1, + MVF600_PAD84_PTD5_QSPI0_A_D0, + MVF600_PAD86_PTD7_QSPI0_B_SCK, + MVF600_PAD87_PTD8_QSPI0_B_CS0, + MVF600_PAD88_PTD9_QSPI0_B_D3, + MVF600_PAD89_PTD10_QSPI0_B_D2, + MVF600_PAD90_PTD11_QSPI0_B_D1, + MVF600_PAD91_PTD12_QSPI0_B_D0, +}; + +static struct mxc_audio_platform_data pcm052_audio_data; + +static int pcm052_sgtl5000_init(void) +{ + pcm052_audio_data.sysclk = 24576000; + return 0; +} + +static struct mvf_sai_platform_data mvf_sai_pdata = { + .flags = MVF_SAI_DMA | MVF_SAI_TRA_SYN | MVF_SAI_USE_I2S_SLAVE, +}; + +static struct mxc_audio_platform_data pcm052_audio_data = { + .sai_num = 1, + .src_port = 2, + .ext_port = 2, + .init = pcm052_sgtl5000_init, +}; + +static struct platform_device pcm052_audio_device = { + .name = "mvf-sgtl5000", +}; + +static struct imxuart_platform_data mvf_uart1_pdata = { + .flags = IMXUART_FIFO | IMXUART_EDMA, + .dma_req_rx = DMA_MUX03_UART1_RX, + .dma_req_tx = DMA_MUX03_UART1_TX, +}; + +static inline void pcm052_init_uart(void) +{ + mvf_add_imx_uart(1, &mvf_uart1_pdata); +} + +static struct fec_platform_data fec_data __initdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static struct switch_platform_data switch_data __initdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static int pcm052_spi_cs[] = { + 134, +}; + +static const struct spi_mvf_master pcm052_spi_data __initconst = { + .bus_num = 0, + .chipselect = pcm052_spi_cs, + .num_chipselect = ARRAY_SIZE(pcm052_spi_cs), + .cs_control = NULL, +}; + +static int pcm052_qspi_cs[] = { + 80, + 87, +}; + +static const struct spi_mvf_master pcm052_qspi_data __initconst = { + .bus_num = 0, + .chipselect = pcm052_qspi_cs, + .num_chipselect = ARRAY_SIZE(pcm052_qspi_cs), + .cs_control = NULL, +}; + +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition at26df081a_partitions[] = { + { + .name = "at26df081a", + .size = (1024 * 64 * 16), + .offset = 0x00000000, + .mask_flags = 0, + } +}; + +static struct flash_platform_data at26df081a_platform_data = { + .name = "Atmel at26df081a SPI Flash chip", + .parts = at26df081a_partitions, + .nr_parts = ARRAY_SIZE(at26df081a_partitions), + .type = "at26df081a", +}; + +static struct spi_mvf_chip at26df081a_chip_info = { + .mode = SPI_MODE_3, + .bits_per_word = 8, + .void_write_data = 0, + .dbr = 0, + .pbr = 0, + .br = 0, + .pcssck = 0, + .pasc = 0, + .pdt = 0, + .cssck = 0, + .asc = 0, + .dt = 0, +}; + +static struct mtd_partition s25fl256s_partitions[] = { + { + .name = "s25fl256s", + .size = (1024 * 64 * 256), + .offset = 0x00000000, + .mask_flags = 0, + } +}; + +static struct flash_platform_data s25fl256s_spi_flash_data = { + .name = "Spansion s25fl128s SPI Flash chip", + .parts = s25fl256s_partitions, + .nr_parts = ARRAY_SIZE(s25fl256s_partitions), + .type = "s25fl128s", +}; +#endif + +static struct spi_board_info mvf_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) +#if defined(CONFIG_SPI_MVF_QSPI) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &s25fl256s_spi_flash_data, + }, +#endif +#if defined(CONFIG_SPI_MVF) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 16000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &at26df081a_platform_data, + .controller_data = &at26df081a_chip_info + }, +#endif +#endif +}; + +static void spi_device_init(void) +{ + spi_register_board_info(mvf_spi_board_info, + ARRAY_SIZE(mvf_spi_board_info)); +} + +#if 1 +static void pcm052_suspend_enter(void) +{ + /* suspend preparation */ +} + +static void pcm052_suspend_exit(void) +{ + /* resmue resore */ +} +static const struct pm_platform_data pcm052_pm_data __initconst = { + .name = "mvf_pm", + .suspend_enter = pcm052_suspend_enter, + .suspend_exit = pcm052_suspend_exit, +}; +#endif + +static struct mvf_dcu_platform_data mvf_dcu_pdata = { + .mode_str = "pm070wl4", + .default_bpp = 24, +}; + +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ +} +/* + * Not defined the cd/wp so far, set it always present for debug*/ +static const struct esdhc_platform_data pcm052_sd1_data __initconst = { + .cd_gpio = PCM052_SD1_CD, + .wp_gpio = -1, +}; + +static struct at24_platform_data board_eeprom = { + .byte_len = 4096, + .page_size = 32, + .flags = AT24_FLAG_ADDR16, +}; + +static struct stmpe_gpio_platform_data pba_gpio_stm_data = { + .gpio_base = -1, + .norequest_mask = STMPE_GPIO_NOREQ_811_TOUCH, +}; + +static struct stmpe_ts_platform_data pba_ts_stm_pdata = { + .sample_time = 4, + .mod_12b = 1, + .ref_sel = 0, + .adc_freq = 1, + .ave_ctrl = 3, + .touch_det_delay = 3, + .settling = 3, + .fraction_z = 7, + .i_drive = 0, +}; + +static struct stmpe_platform_data pba_stm_pdata = { + .blocks = STMPE_BLOCK_GPIO | STMPE_BLOCK_TOUCHSCREEN, + .irq_base = NR_IRQS, + .irq_trigger = IRQF_TRIGGER_RISING, + .irq_invert_polarity = true, + .gpio = &pba_gpio_stm_data, + .ts = &pba_ts_stm_pdata, +}; + +static struct imxi2c_platform_data pcm052_i2c_data = { + .bitrate = 100000, +}; + +static struct i2c_board_info pcm052_i2c2_board_info[] __initdata = { + { + I2C_BOARD_INFO("sgtl5000", 0x0a), + }, + { + I2C_BOARD_INFO("at24", 0x50), + .platform_data = &board_eeprom, + }, + { + I2C_BOARD_INFO("stmpe811", 0x41), + .irq = PCM052_TS_IRQ, + .platform_data = &pba_stm_pdata, + }, +}; + +static struct mxc_nand_platform_data mvf_data __initdata = { + .width = 2, +}; + +static struct led_pwm mvf_led __initdata = { + .name = "mvf_leds", + .pwm_id = 1, + .active_low = 0, + .max_brightness = 6, + .pwm_period_ns = 100000000, +}; + +static struct led_pwm_platform_data mvf_led_data __initdata = { + .num_leds = 1, + .leds = &mvf_led, +}; + +static void __init pcm052_init_usb(void) +{ + imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); + /*mvf_set_otghost_vbus_func(pcm052_usbotg_vbus);*/ +#ifdef CONFIG_USB_GADGET_ARC + mvf_usb_dr_init(); +#endif +#ifdef CONFIG_USB_EHCI_ARC + mvf_usb_dr2_init(); +#endif +} + +/*! + * Board specific initialization. + */ +static void __init pcm052_board_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(pcm052_pads, + ARRAY_SIZE(pcm052_pads)); + pcm052_init_uart(); + +#ifdef CONFIG_FEC + mvf_init_fec(fec_data); +#endif + +#ifdef CONFIG_FSL_L2_SWITCH + mvf_init_switch(switch_data); +#endif + + mvf_add_snvs_rtc(); + + mvf_add_sdhci_esdhc_imx(1, &pcm052_sd1_data); + + mvf_add_imx_i2c(2, &pcm052_i2c_data); + i2c_register_board_info(2, pcm052_i2c2_board_info, + ARRAY_SIZE(pcm052_i2c2_board_info)); + + mvf_add_dspi(0, &pcm052_spi_data); + mvf_add_qspi(0, &pcm052_qspi_data); + spi_device_init(); + + mvfa5_add_dcu(0, &mvf_dcu_pdata); + +// mxc_register_device(&pcm052_audio_device, &pcm052_audio_data); +// mvfa5_add_sai(2, &mvf_sai_pdata); + +// mvf_add_wdt(0); + + pcm052_init_usb(); + + mvf_add_nand(&mvf_data); + +// mvf_add_mxc_pwm(0); +// mvf_add_pwm_leds(&mvf_led_data); + +} + +static void __init mvf_timer_init(void) +{ +#if 0 + struct clk *uart_clk; + uart_clk = clk_get_sys("mvf-uart.0", NULL); + early_console_setup(MVF_UART1_BASE_ADDR, uart_clk); +#endif + mvf_clocks_init(32768, 24000000, 0, 0); +} + +static struct sys_timer pcm052_timer = { + .init = mvf_timer_init, +}; + +/* + * initialize __mach_desc_ data structure. + */ +MACHINE_START(PCM052, "PHYTEC phyCORE-Vybrid Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .boot_params = MVF_PHYS_OFFSET + 0x100, + .fixup = fixup_mxc_board, + .map_io = mvf_map_io, + .init_irq = mvf_init_irq, + .init_machine = pcm052_board_init, + .timer = &pcm052_timer, +MACHINE_END diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 5ac0ff1766fb..c7279adba4d2 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1652,7 +1652,34 @@ static struct clk i2c_clk[] = { .id = 0, .parent = &ipg_clk, .enable_reg = MXC_CCM_CCGR4, - .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(i2c_clk_1) + .id = 1, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(i2c_clk_2) + .id = 2, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR10, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(i2c_clk_3) + .id = 3, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR10, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, .enable = _clk_enable, .disable = _clk_disable, }, @@ -1897,7 +1924,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk), /* arm core clk */ _REGISTER_CLOCK(NULL, "periph_clk", periph_clk), /* platform bus clk */ _REGISTER_CLOCK(NULL, "ipg_clk", ipg_clk), - _REGISTER_CLOCK(NULL, "audio ext clk", audio_external_clk), +// _REGISTER_CLOCK(NULL, "audio ext clk", audio_external_clk), _REGISTER_CLOCK(NULL, "mvf-uart.0", uart_clk[0]), _REGISTER_CLOCK(NULL, "mvf-uart.1", uart_clk[0]), _REGISTER_CLOCK(NULL, "mvf-uart.2", uart_clk[0]), @@ -1911,8 +1938,9 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk), _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc1_clk), _REGISTER_CLOCK("mvf-dcu.0", NULL, dcu0_clk), - _REGISTER_CLOCK("mvf-sai.0", NULL, sai2_clk), - _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[0]), +// _REGISTER_CLOCK("mvf-sai.0", NULL, sai2_clk), +// _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[2]), + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]), _REGISTER_CLOCK(NULL, "usb-clk", usb_clk), _REGISTER_CLOCK(NULL, "mvf-usb.0", usb_phy0_clk), _REGISTER_CLOCK(NULL, "mvf-usb.1", usb_phy1_clk), -- cgit v1.2.3 From 139da31fb4b4d98f8fdb7f3a62662b73b9d8b705 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 17 Dec 2012 11:38:33 -0800 Subject: pcm052: enable EEPROM driver in config, fix TSC IRQs Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/board-pcm052.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c index dc583b4a69f5..08b071f1dcf7 100644 --- a/arch/arm/mach-mvf/board-pcm052.c +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -436,7 +436,7 @@ static struct stmpe_ts_platform_data pba_ts_stm_pdata = { static struct stmpe_platform_data pba_stm_pdata = { .blocks = STMPE_BLOCK_GPIO | STMPE_BLOCK_TOUCHSCREEN, - .irq_base = NR_IRQS, + .irq_base = STMPE_IRQ_BASE, .irq_trigger = IRQF_TRIGGER_RISING, .irq_invert_polarity = true, .gpio = &pba_gpio_stm_data, @@ -457,7 +457,7 @@ static struct i2c_board_info pcm052_i2c2_board_info[] __initdata = { }, { I2C_BOARD_INFO("stmpe811", 0x41), - .irq = PCM052_TS_IRQ, + .irq = gpio_to_irq(PCM052_TS_IRQ), .platform_data = &pba_stm_pdata, }, }; -- cgit v1.2.3 From 10d675e891b7969fe0658db17ad0ecc88fd6eda5 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 4 Feb 2013 14:12:45 -0800 Subject: pcm052: usb: fix VBUS enable mux settings and assert GPIO to enable VBUS Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/board-pcm052.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c index 08b071f1dcf7..85706add0494 100644 --- a/arch/arm/mach-mvf/board-pcm052.c +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -195,7 +195,7 @@ static iomux_v3_cfg_t pcm052_pads[] = { #ifdef PCM952_REV0 MVF600_PAD6_PTA16__USB0_VBUS_EN, #else - MVF600_PAD134_PTA7__USB0_VBUS_EN, + MVF600_PAD134_PTA7__USB_VBUS_EN, #endif MVF600_PAD7_PTA17__USB_OC_N, @@ -275,7 +275,7 @@ static struct switch_platform_data switch_data __initdata = { }; static int pcm052_spi_cs[] = { - 134, + 41, }; static const struct spi_mvf_master pcm052_spi_data __initconst = { @@ -479,13 +479,14 @@ static struct led_pwm_platform_data mvf_led_data __initdata = { .leds = &mvf_led, }; +#define USB_VBUS_ENABLE_PIN 134 static void __init pcm052_init_usb(void) { - imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); - /*mvf_set_otghost_vbus_func(pcm052_usbotg_vbus);*/ -#ifdef CONFIG_USB_GADGET_ARC - mvf_usb_dr_init(); -#endif + gpio_request_one(USB_VBUS_ENABLE_PIN, GPIOF_OUT_INIT_LOW, "VBUS_EN"); + msleep(2); + gpio_set_value(USB_VBUS_ENABLE_PIN, 1); + +// mvf_usb_dr_init(); #ifdef CONFIG_USB_EHCI_ARC mvf_usb_dr2_init(); #endif -- cgit v1.2.3 From fd5b59f7d6fc1736c2b00f306dcfeb574fea4512 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 11 Feb 2013 15:33:19 -0800 Subject: mvf: usb: create modular defines for ehci and some hardware address changes. ehci changes are currently only used with phyCORE-Vybrid (pcm052) Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/clock.c | 2 ++ arch/arm/mach-mvf/devices-mvf.h | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index c7279adba4d2..74ce8a9f290e 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -670,10 +670,12 @@ static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate) else return -EINVAL; +#ifndef CONFIG_MACH_PCM052 reg = __raw_readl(PLL3_480_USB1_BASE_ADDR); reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK; reg |= div; __raw_writel(reg, PLL3_480_USB1_BASE_ADDR); +#endif return 0; } diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index c434834ba0b2..f4ec88b062ac 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -52,6 +52,15 @@ extern const struct imx_mxc_nand_data mvf_nand_data __initconst; #define mvf_add_nand(pdata) \ imx_add_mxc_nand(&mvf_nand_data, pdata) +#ifdef CONFIG_MACH_PCM052 +extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data[] __initconst; +#define mvf_add_fsl_usb2_udc(id, pdata) \ + imx_add_fsl_usb2_udc(&mvf_fsl_usb2_udc_data[id], pdata) + +extern const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data[] __initconst; +#define mvf_add_fsl_ehci_otg(id, pdata) \ + imx_add_fsl_ehci(&mvf_mxc_ehci_otg_data[id], pdata) +#else extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data __initconst; #define mvf_add_fsl_usb2_udc(pdata) \ imx_add_fsl_usb2_udc(&mvf_fsl_usb2_udc_data, pdata) @@ -59,10 +68,16 @@ extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data __initconst; extern const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data __initconst; #define mvf_add_fsl_ehci_otg(pdata) \ imx_add_fsl_ehci(&mvf_mxc_ehci_otg_data, pdata) +#endif extern const struct imx_mxc_ehci_data mvf_mxc_ehci_hs_data[] __initconst; +#ifdef CONFIG_MACH_PCM052 +#define mvf_add_fsl_ehci_hs(id, pdata) \ + imx_add_fsl_ehci(&mvf_mxc_ehci_hs_data[id], pdata) +#else #define mvf_add_fsl_ehci_hs(id, pdata) \ imx_add_fsl_ehci(&mvf_mxc_ehci_hs_data[id - 1], pdata) +#endif extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; #define mvf_add_fsl_usb2_otg(pdata) \ @@ -70,15 +85,26 @@ extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst; +#ifdef CONFIG_MACH_PCM052 +#define mvf_add_fsl_usb2_ehci_otg_wakeup(id, pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[id], pdata) +#define mvf_add_fsl_usb2_udc_wakeup(id, pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[id], pdata) +#else #define mvf_add_fsl_usb2_ehci_otg_wakeup(pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[1], pdata) #define mvf_add_fsl_usb2_udc_wakeup(pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[0], pdata) +#endif extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_hs_wakeup_data[] __initconst; +#ifdef CONFIG_MACH_PCM052 +#define mvf_add_fsl_usb2_hs_wakeup(id, pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_hs_wakeup_data[id], pdata) #define mvf_add_fsl_usb2_hs_wakeup(id, pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_hs_wakeup_data[id - 1], pdata) +#endif extern const struct imx_imx_esai_data mvf_imx_esai_data[] __initconst; #define mvf_add_imx_esai(id, pdata) \ -- cgit v1.2.3 From 16af5ee7d9556c47b332788e4107cbed5ee7ec10 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 11 Feb 2013 13:34:12 -0800 Subject: pcm052: usb: enable both USB0 and USB1 as ehci-host note: there are still intermittent detection errors with USB0 Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/board-pcm052.c | 2 +- arch/arm/mach-mvf/usb_dr.c | 228 +++++++++++++++++++++++---------------- arch/arm/mach-mvf/usb_dr2.c | 22 ++-- 3 files changed, 145 insertions(+), 107 deletions(-) (limited to 'arch/arm/mach-mvf') diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c index 85706add0494..84bd65623ebb 100644 --- a/arch/arm/mach-mvf/board-pcm052.c +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -486,8 +486,8 @@ static void __init pcm052_init_usb(void) msleep(2); gpio_set_value(USB_VBUS_ENABLE_PIN, 1); -// mvf_usb_dr_init(); #ifdef CONFIG_USB_EHCI_ARC + mvf_usb_dr_init(); mvf_usb_dr2_init(); #endif } diff --git a/arch/arm/mach-mvf/usb_dr.c b/arch/arm/mach-mvf/usb_dr.c index bbd29f3b45a9..34377c4c19b3 100644 --- a/arch/arm/mach-mvf/usb_dr.c +++ b/arch/arm/mach-mvf/usb_dr.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -37,10 +38,6 @@ static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); static void usbotg_wakeup_event_clear(void); -/* The usb_phy0_clk do not have enable/disable function at clock.c - * and PLL output for usb0's phy should be always enabled. - * usb_phy0_clk only stands for usb uses pll3 as its parent. - */ static struct clk *usb_phy0_clk; static u8 otg_used; @@ -65,24 +62,22 @@ static struct fsl_usb2_platform_data dr_utmi_config = { /* Platform data for wakeup operation */ static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = { - .name = "Gadget wakeup", + .name = "Host wakeup", .usb_clock_for_pm = usbotg_clock_gate, .usb_wakeup_exhandle = usbotg_wakeup_event_clear, }; static void usbotg_internal_phy_clock_gate(bool on) { - u32 reg; - void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); - reg = __raw_readl(phy_reg + HW_USBPHY_CTRL); if (on) - reg &= ~BM_USBPHY_CTRL_CLKGATE; + __raw_writel(BM_USBPHY_CTRL_CLKGATE, + phy_reg + HW_USBPHY_CTRL_CLR); else - reg |= BM_USBPHY_CTRL_CLKGATE; + __raw_writel(BM_USBPHY_CTRL_CLKGATE, + phy_reg + HW_USBPHY_CTRL_SET); - __raw_writel(reg, phy_reg + HW_USBPHY_CTRL); } static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) @@ -114,6 +109,13 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) /* Power up the PHY */ __raw_writel(0, phy_reg + HW_USBPHY_PWD); + if ((pdata->operating_mode == FSL_USB2_DR_HOST) || + (pdata->operating_mode == FSL_USB2_DR_OTG)) { + /* enable FS/LS device */ + __raw_writel( + BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3, + phy_reg + HW_USBPHY_CTRL_SET); + } return 0; } @@ -136,8 +138,8 @@ static int usbotg_init_ext(struct platform_device *pdev) usbotg_internal_phy_clock_gate(true); usb_phy_enable(pdev->dev.platform_data); /* - * after the phy reset,can not read the value for id/vbus at - * the register of otgsc ,cannot read at once ,need delay 3 ms + * after the phy reset,can't read the value for id/vbus at + * the register of otgsc at once ,need delay 3 ms */ mdelay(3); } @@ -159,21 +161,18 @@ static void usbotg_uninit_ext(struct platform_device *pdev) static void usbotg_clock_gate(bool on) { - pr_debug("%s: on is %d\n", __func__, on); + if (on) clk_enable(usb_phy0_clk); else clk_disable(usb_phy0_clk); + } -/* -void mvf_set_otghost_vbus_func(driver_vbus_func driver_vbus) -{ - dr_utmi_config.platform_driver_vbus = driver_vbus; -} -*/ + static void _dr_discharge_line(bool enable) { void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + if (enable) { __raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x3), phy_reg + HW_USBPHY_DEBUG_SET); @@ -191,7 +190,6 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) -static u32 low_power_enable_src; /* only useful at otg mode */ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { @@ -233,12 +231,11 @@ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable, int source) { - if (enable) { - low_power_enable_src |= source; + if (enable) enter_phy_lowpower_suspend(pdata, enable); - } else { + else { + pr_debug("phy lowpower disable\n"); enter_phy_lowpower_suspend(pdata, enable); - low_power_enable_src &= ~source; } } @@ -270,10 +267,9 @@ static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, bool on, int source) { - /* otg host and device share the OWIE bit, only when host and device - * all enable the wakeup irq, we can enable the OWIE bit - */ - if (on) { + pr_debug("USB Host %s,on=%d\n", __func__, on); + mdelay(3); + if (on) { otg_wake_up_enable(pdata, on); } else { otg_wake_up_enable(pdata, on); @@ -302,125 +298,167 @@ static void usbotg_wakeup_event_clear(void) } /* End of Common operation for DR port */ + #ifdef CONFIG_USB_EHCI_ARC_OTG -#endif /* CONFIG_USB_EHCI_ARC_OTG */ +/* Beginning of host related operation for DR port */ +static void _host_platform_suspend(struct fsl_usb2_platform_data *pdata) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET); +} -#ifdef CONFIG_USB_GADGET_ARC -/* Beginning of device related operation for DR port */ -static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, +static void _host_platform_resume(struct fsl_usb2_platform_data *pdata) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; + + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); +} + +static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { - __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE); + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST); } -static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata, +static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enable) { - __wakeup_irq_enable(pdata, enable, ENABLED_BY_DEVICE); - if (enable) { - pr_debug("device wakeup enable\n"); + __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST); + + if (enable) device_wakeup_enable(&pdata->pdev->dev); - } else { - pr_debug("device wakeup disable\n"); + else device_wakeup_disable(&pdata->pdev->dev); - } } static enum usb_wakeup_event -_is_device_wakeup(struct fsl_usb2_platform_data *pdata) +_is_host_wakeup(struct fsl_usb2_platform_data *pdata) { - int wakeup_req = USBC0_CTRL & UCTRL_OWIR; + u32 wakeup_req = USBC0_CTRL & UCTRL_OWIR; + u32 otgsc = UOG_OTGSC; - /* if ID=1, it is a device wakeup event */ - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && - (UOG_USBSTS & USBSTS_URI)) { - printk(KERN_INFO "otg udc wakeup, host sends reset signal\n"); - return WAKEUP_EVENT_DPDM; - } - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && \ - ((UOG_USBSTS & USBSTS_PCI) || - (UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME))) { - /* - * When the line state from J to K, the Port Change Detect bit - * in the USBSTS register is also set to '1'. - */ - printk(KERN_INFO "otg udc wakeup, host sends resume signal\n"); - return WAKEUP_EVENT_DPDM; + if (wakeup_req) { + pr_debug("the otgsc is 0x%x, usbsts is 0x%x," + " portsc is 0x%x, wakeup_irq is 0x%x\n", + UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, wakeup_req); } - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && - (UOG_OTGSC & OTGSC_STS_A_VBUS_VALID) && - (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) { - printk(KERN_INFO "otg udc vbus rising wakeup\n"); - return WAKEUP_EVENT_VBUS; + /* if ID change sts, it is a host wakeup event */ + if (wakeup_req && (otgsc & OTGSC_IS_USB_ID)) { + pr_debug("otg host ID wakeup\n"); + /* if host ID wakeup, we must clear the b session change sts */ + otgsc &= (~OTGSC_IS_USB_ID); + return WAKEUP_EVENT_ID; } - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && - !(UOG_OTGSC & OTGSC_STS_A_VBUS_VALID)) { - printk(KERN_INFO "otg udc vbus falling wakeup\n"); - return WAKEUP_EVENT_VBUS; + if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) { + pr_debug("otg host Remote wakeup\n"); + return WAKEUP_EVENT_DPDM; } - - return WAKEUP_EVENT_DPDM; + return WAKEUP_EVENT_INVALID; } -static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata) +static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata) { - _device_phy_lowpower_suspend(pdata, false); - _device_wakeup_enable(pdata, false); + _host_phy_lowpower_suspend(pdata, false); + _host_wakeup_enable(pdata, false); } -/* end of device related operation for DR port */ -#endif /* CONFIG_USB_GADGET_ARC */ + +/* End of host related operation for DR port */ +#endif /* CONFIG_USB_EHCI_ARC_OTG */ + void __init mvf_usb_dr_init(void) { struct platform_device *pdev, *pdev_wakeup; u32 reg; -#ifdef CONFIG_USB_GADGET_ARC - dr_utmi_config.operating_mode = DR_UDC_MODE; - dr_utmi_config.wake_up_enable = _device_wakeup_enable; - dr_utmi_config.platform_suspend = NULL; - dr_utmi_config.platform_resume = NULL; - dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend; - dr_utmi_config.is_wakeup_event = _is_device_wakeup; + +#ifdef CONFIG_USB_EHCI_ARC_OTG + dr_utmi_config.operating_mode = DR_HOST_MODE; + dr_utmi_config.wake_up_enable = _host_wakeup_enable; + dr_utmi_config.platform_suspend = _host_platform_suspend; + dr_utmi_config.platform_resume = _host_platform_resume; + dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend; + dr_utmi_config.is_wakeup_event = _is_host_wakeup; dr_utmi_config.wakeup_pdata = &dr_wakeup_config; - dr_utmi_config.wakeup_handler = device_wakeup_handler; + dr_utmi_config.wakeup_handler = host_wakeup_handler; - pdev = mvf_add_fsl_usb2_udc(&dr_utmi_config); + pdev = mvf_add_fsl_ehci_otg(0, &dr_utmi_config); - dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data; + dr_wakeup_config.usb_pdata[0] = pdev->dev.platform_data; /* register wakeup device */ - pdev_wakeup = mvf_add_fsl_usb2_udc_wakeup(&dr_wakeup_config); + pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(0, &dr_wakeup_config); if (pdev != NULL) ((struct fsl_usb2_platform_data *) (pdev->dev.platform_data))->wakeup_pdata = (struct fsl_usb2_wakeup_platform_data *) (pdev_wakeup->dev.platform_data); - device_set_wakeup_capable(&pdev->dev, true); - __raw_writel(((0x01 << 30) | 0x2), ANADIG_USB1_MISC); - - __raw_writel(0x00000894, USBPHY1_CTRL); - udelay(10); + __raw_writel(0x0220C802, USBPHY1_CTRL); + udelay(20); __raw_writel(0x0, USBPHY1_PWD); - __raw_writel(0x1, USBPHY1_IP); - udelay(20); - __raw_writel(0x7, USBPHY1_IP); reg = __raw_readl(USBPHY1_DEBUG); - reg &= ~0x40000000; /* clear gate clock */ + reg &= ~0x40000000; /* clear clock gate */ __raw_writel(reg, USBPHY1_DEBUG); + reg = __raw_readl(ANADIG_USB1_MISC); + reg |= (0x01 << 30); /* Enable CLK_TO_UTMI */ + __raw_writel(reg, ANADIG_USB1_MISC); + __raw_writel(0x10000007, USBPHY1_TX); + /*__raw_writel(0x100F0F07, USBPHY1_TX);*/ + + /* Enable disconnect detect */ reg = __raw_readl(USBPHY1_CTRL); - reg |= ((0xD1 << 11) | 0x6); + reg &= ~0x040; /* clear OTG ID change IRQ */ + reg |= (0x1 << 14); /* Enable UTMI+ level2 */ + reg |= (0x1 << 9); + reg |= (0x1 << 15); /* Enable UTMI+ level3 */ + reg &= ~((0xD1 << 11) | 0x6); __raw_writel(reg, USBPHY1_CTRL); + __raw_writel(0x1 << 3, USBPHY1_CTRL + 0x8); + /* Disable VBUS and CHARGER detect */ reg = __raw_readl(ANADIG_USB1_VBUS_DETECT); reg |= 0xE8; __raw_writel(reg, ANADIG_USB1_VBUS_DETECT); __raw_writel(0x001c0000, ANADIG_USB1_CHRG_DETECT); + #endif +} + +/* USB HIGH_SPEED disconnect detect on/off */ +void fsl_platform_set_usb0_phy_dis(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + u32 reg; + reg = __raw_readl(USBPHY1_CTRL); + + if (enable) + reg |= ((0xD1 << 11) | 0x6); + else + reg &= ~((0xD1 << 11) | 0x6); + + __raw_writel(reg, USBPHY1_CTRL); + + __raw_writel(0x1 << 3, USBPHY1_CTRL + 0x8); } diff --git a/arch/arm/mach-mvf/usb_dr2.c b/arch/arm/mach-mvf/usb_dr2.c index 67e3fcdbc921..c1d6ebf51791 100644 --- a/arch/arm/mach-mvf/usb_dr2.c +++ b/arch/arm/mach-mvf/usb_dr2.c @@ -32,8 +32,8 @@ #include "regs-anadig.h" #include "usb.h" -static int usbotg2_init_ext(struct platform_device *pdev); -static void usbotg2_uninit_ext(struct platform_device *pdev); +static int usbotg_init_ext(struct platform_device *pdev); +static void usbotg_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); static void usbotg_wakeup_event_clear(void); @@ -49,9 +49,9 @@ static u8 otg2_used; * - operating_mode plugged at run time */ static struct fsl_usb2_platform_data dr_utmi_config = { - .name = "DR", - .init = usbotg2_init_ext, - .exit = usbotg2_uninit_ext, + .name = "DR2", + .init = usbotg_init_ext, + .exit = usbotg_uninit_ext, .phy_mode = FSL_USB2_PHY_UTMI_WIDE, .power_budget = 500, /* 500 mA max power */ .usb_clock_for_pm = usbotg_clock_gate, @@ -120,7 +120,7 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) return 0; } /* Notes: configure USB clock*/ -static int usbotg2_init_ext(struct platform_device *pdev) +static int usbotg_init_ext(struct platform_device *pdev) { struct clk *usb_clk; u32 ret; @@ -148,7 +148,7 @@ static int usbotg2_init_ext(struct platform_device *pdev) return ret; } -static void usbotg2_uninit_ext(struct platform_device *pdev) +static void usbotg_uninit_ext(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; @@ -287,7 +287,7 @@ static void usbotg_wakeup_event_clear(void) int wakeup_req = USBC1_CTRL & UCTRL_OWIR; if (wakeup_req != 0) { - pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC); + pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG2_OTGSC); /* Disable OWIE to clear OWIR, wait 3 clock * cycles of standly clock(32KHz) */ @@ -398,12 +398,12 @@ void __init mvf_usb_dr2_init(void) dr_utmi_config.wakeup_pdata = &dr_wakeup_config; dr_utmi_config.wakeup_handler = host_wakeup_handler; - pdev = mvf_add_fsl_ehci_otg(&dr_utmi_config); + pdev = mvf_add_fsl_ehci_otg(1, &dr_utmi_config); dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data; /* register wakeup device */ - pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(&dr_wakeup_config); + pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(1, &dr_wakeup_config); if (pdev != NULL) ((struct fsl_usb2_platform_data *) (pdev->dev.platform_data))->wakeup_pdata = @@ -446,7 +446,7 @@ void __init mvf_usb_dr2_init(void) } /* USB HIGH_SPEED disconnect detect on/off */ -void fsl_platform_set_usb_phy_dis(struct fsl_usb2_platform_data *pdata, +void fsl_platform_set_usb1_phy_dis(struct fsl_usb2_platform_data *pdata, bool enable) { u32 reg; -- cgit v1.2.3