diff options
author | Adam Lussier <adam.lussier@timesys.com> | 2013-02-25 17:19:04 -0500 |
---|---|---|
committer | Adam Lussier <adam.lussier@timesys.com> | 2013-02-25 17:19:04 -0500 |
commit | f962cbcefdfad22ffff41e19ad4c5ff58815c05c (patch) | |
tree | e9424582f1fdc92d360ff58c831ddf801a268e3f /arch | |
parent | 15f55e0b22f8953b56fb5d6bdf8b770228f2f449 (diff) | |
parent | 16af5ee7d9556c47b332788e4107cbed5ee7ec10 (diff) |
Merge remote-tracking branch 'github/3.0-pcm052' into 3.0-pcm0523.0-pcm052-ts2
Release 3.0-ts2: enable USB support for the phyCORE Vybrid
Diffstat (limited to 'arch')
33 files changed, 2090 insertions, 134 deletions
diff --git a/arch/arm/configs/mvf600_defconfig b/arch/arm/configs/mvf600_defconfig index 23646435c6af..648e8f5e4d13 100644 --- a/arch/arm/configs/mvf600_defconfig +++ b/arch/arm/configs/mvf600_defconfig @@ -178,7 +178,7 @@ CONFIG_INLINE_WRITE_UNLOCK=y CONFIG_INLINE_WRITE_UNLOCK_IRQ=y # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set # CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set +CONFIG_FREEZER=y # # System Type @@ -246,6 +246,7 @@ CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC=y CONFIG_IMX_HAVE_PLATFORM_GPMI_NFC=y CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT=y +CONFIG_IMX_HAVE_PLATFORM_MVF_ADC=y CONFIG_IMX_HAVE_PLATFORM_IMX_SNVS_RTC=y CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y CONFIG_IMX_HAVE_PLATFORM_IMX_SSI=y @@ -325,14 +326,20 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_CACHE_L2X0 is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y CONFIG_ARM_L1_CACHE_SHIFT=5 CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_CPU_HAS_PMU=y # CONFIG_ARM_ERRATA_430973 is not set # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set CONFIG_ARM_ERRATA_743622=y +# CONFIG_ARM_ERRATA_753970 is not set CONFIG_ARM_ERRATA_754322=y CONFIG_ARM_GIC=y @@ -342,6 +349,7 @@ CONFIG_ARM_GIC=y # CONFIG_PCI_SYSCALL is not set # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set +# CONFIG_PL310_ERRATA_769419 is not set # # Kernel Features @@ -419,7 +427,9 @@ CONFIG_CMDLINE_FROM_BOOTLOADER=y # # At least one emulation must be selected # -# CONFIG_VFP is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set # # Userspace binary formats @@ -433,7 +443,9 @@ CONFIG_HAVE_AOUT=y # # Power management options # -# CONFIG_SUSPEND is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y CONFIG_PM_RUNTIME=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set @@ -652,7 +664,41 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set # CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +CONFIG_MVF_ADC=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -748,6 +794,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_KS8851 is not set # CONFIG_KS8851_MLL is not set CONFIG_FEC=y +# CONFIG_FEC1 is not set # CONFIG_FEC_1588 is not set # CONFIG_FTMAC100 is not set # CONFIG_NETDEV_1000 is not set @@ -795,6 +842,7 @@ CONFIG_INPUT_POLLDEV=y # CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y +# CONFIG_TSDEV_COMPATIBLE is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set @@ -858,6 +906,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_ST1232 is not set # CONFIG_TOUCHSCREEN_P1003 is not set # CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_CRTOUCH is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_ATI_REMOTE is not set @@ -975,10 +1024,11 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_ALTERA is not set # CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_MVF_QSPI is not set # CONFIG_SPI_GPIO is not set # CONFIG_SPI_IMX is not set CONFIG_SPI_MVF=y -# CONFIG_SPI_MVF_DSPI_EDMA is not set +CONFIG_SPI_MVF_DSPI_EDMA=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set # CONFIG_SPI_XILINX is not set @@ -1434,7 +1484,8 @@ CONFIG_DMADEVICES=y # DMA Devices # # CONFIG_DW_DMAC is not set -CONFIG_MCF_EDMA=y +CONFIG_MVF_EDMA=y +CONFIG_MVF_EDMA_TEST=m # CONFIG_MXC_PXP is not set # CONFIG_MXC_PXP_V2 is not set # CONFIG_TIMB_DMA is not set @@ -1499,6 +1550,7 @@ CONFIG_CLKSRC_MMIO=y # # MXC Asynchronous Sample Rate Converter support # +CONFIG_MXC_ASRC=y # # MXC Bluetooth support @@ -1758,25 +1810,28 @@ CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_PCOMP2=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set CONFIG_CRYPTO_WORKQUEUE=y # CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_TEST=m -# CONFIG_CRYPTO_CRYPTODEV is not set +CONFIG_CRYPTO_CRYPTODEV=y # # Authenticated Encryption with Associated Data @@ -1788,10 +1843,10 @@ CONFIG_CRYPTO_TEST=m # # Block modes # -CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CBC is not set # CONFIG_CRYPTO_CTR is not set # CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_ECB is not set # CONFIG_CRYPTO_LRW is not set # CONFIG_CRYPTO_PCBC is not set # CONFIG_CRYPTO_XTS is not set @@ -1810,7 +1865,7 @@ CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set -CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_RMD128 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set @@ -1826,7 +1881,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set -CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set @@ -1850,10 +1905,24 @@ CONFIG_CRYPTO_LZO=y # # Random Number Generation # -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y +# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE=7 +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig index 23df64879243..0ef1f8a09d37 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/Makefile b/arch/arm/mach-mvf/Makefile index 07f33a555dcb..fad70a4a9dc7 100644 --- a/arch/arm/mach-mvf/Makefile +++ b/arch/arm/mach-mvf/Makefile @@ -3,9 +3,9 @@ # # 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 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 index 08b071f1dcf7..84bd65623ebb 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,14 +479,15 @@ 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); + #ifdef CONFIG_USB_EHCI_ARC + mvf_usb_dr_init(); mvf_usb_dr2_init(); #endif } diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index 03cc6ad51788..01fd4dc364cc 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -72,6 +72,7 @@ #include <mach/mipi_dsi.h> #include <mach/mipi_csi2.h> #include <mach/fsl_l2_switch.h> +#include <mach/mxc.h> #include <asm/irq.h> #include <asm/setup.h> #include <asm/mach-types.h> @@ -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", @@ -427,16 +426,26 @@ 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); /*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 +} + +static void __init mvf_init_adc(void) +{ + mvf_add_adc(0); } /*! @@ -458,6 +467,12 @@ static void __init mvf_board_init(void) mvf_add_snvs_rtc(); + mvf_init_adc(); + + 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); @@ -482,6 +497,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 25e1079165dd..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; } @@ -1613,6 +1615,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) @@ -1626,6 +1636,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) @@ -1845,6 +1867,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, }; @@ -1890,6 +1935,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), @@ -1902,10 +1948,12 @@ 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]), + _REGISTER_CLOCK(NULL, "caam_clk", caam_clk), }; static void clk_tree_init(void) - { unsigned int reg = 0xffffffff; 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/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index 61792fb34530..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,24 +68,43 @@ 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) \ 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; +#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) \ @@ -142,6 +170,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]) @@ -218,3 +250,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) 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 <linux/linkage.h> +#include <mach/hardware.h> +#include <asm/memory.h> +#include <mach/mvf.h> +#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 <linux/module.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/suspend.h> +#include <linux/iram_alloc.h> +#include <linux/interrupt.h> +#include <asm/tlb.h> +#include <asm/mach/map.h> +#include <mach/hardware.h> +#include <asm/hardware/gic.h> +#include <mach/mxc_uart.h> +#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 <linux/delay.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> -#include <linux/pmic_external.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> #include <asm/io.h> #include <mach/hardware.h> #include <mach/clock.h> @@ -29,6 +30,142 @@ #include <asm/system.h> #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) { diff --git a/arch/arm/mach-mvf/usb_dr.c b/arch/arm/mach-mvf/usb_dr.c index 2467acc1bf28..34377c4c19b3 100644 --- a/arch/arm/mach-mvf/usb_dr.c +++ b/arch/arm/mach-mvf/usb_dr.c @@ -20,6 +20,7 @@ #include <linux/types.h> #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/pm_wakeup.h> #include <linux/fsl_devices.h> #include <linux/delay.h> #include <linux/io.h> @@ -35,11 +36,8 @@ 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. - * usb_phy0_clk only stands for usb uses pll3 as its parent. - */ static struct clk *usb_phy0_clk; static u8 otg_used; @@ -62,19 +60,24 @@ 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) { - 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) @@ -106,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; } @@ -128,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); } @@ -151,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); @@ -183,48 +190,275 @@ 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_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) + 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_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) +{ + 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 = 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 */ +/* 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 -#endif /* CONFIG_USB_GADGET_ARC */ +static void _host_platform_resume(struct fsl_usb2_platform_data *pdata) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; -void __init mvf_usb_dr_init(void) + 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) { - struct platform_device *pdev; - u32 reg; -#ifdef CONFIG_USB_GADGET_ARC - dr_utmi_config.operating_mode = DR_UDC_MODE; - dr_utmi_config.platform_suspend = NULL; - dr_utmi_config.platform_resume = NULL; + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST); +} - pdev = mvf_add_fsl_usb2_udc(&dr_utmi_config); +static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST); - __raw_writel(((0x01 << 30) | 0x2), ANADIG_USB1_MISC); + if (enable) + device_wakeup_enable(&pdata->pdev->dev); + else + device_wakeup_disable(&pdata->pdev->dev); +} - __raw_writel(0x00000894, USBPHY1_CTRL); - udelay(10); +static enum usb_wakeup_event +_is_host_wakeup(struct fsl_usb2_platform_data *pdata) +{ + u32 wakeup_req = USBC0_CTRL & UCTRL_OWIR; + u32 otgsc = UOG_OTGSC; - __raw_writel(0x0, USBPHY1_PWD); - __raw_writel(0x1, USBPHY1_IP); + 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 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_dr_init(void) +{ + 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(0, &dr_utmi_config); + + dr_wakeup_config.usb_pdata[0] = pdev->dev.platform_data; + + /* register wakeup device */ + 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); + + __raw_writel(0x0220C802, USBPHY1_CTRL); udelay(20); - __raw_writel(0x7, USBPHY1_IP); + + __raw_writel(0x0, USBPHY1_PWD); 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 d26cfde125e0..c1d6ebf51791 100644 --- a/arch/arm/mach-mvf/usb_dr2.c +++ b/arch/arm/mach-mvf/usb_dr2.c @@ -20,6 +20,7 @@ #include <linux/types.h> #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/pm_wakeup.h> #include <linux/fsl_devices.h> #include <linux/delay.h> #include <linux/io.h> @@ -31,10 +32,11 @@ #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); static struct clk *usb_phy1_clk; static u8 otg2_used; @@ -47,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, @@ -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); @@ -111,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; @@ -139,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; @@ -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", UOG2_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,21 +331,84 @@ 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(1, &dr_utmi_config); + + dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data; - pdev = mvf_add_fsl_ehci_otg(&dr_utmi_config); + /* register wakeup device */ + 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 = + (struct fsl_usb2_wakeup_platform_data *) + (pdev_wakeup->dev.platform_data); __raw_writel(0x0220C802, USBPHY2_CTRL); udelay(20); @@ -267,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; diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig index de80caba49c3..42a52220383e 100755 --- a/arch/arm/plat-mxc/devices/Kconfig +++ b/arch/arm/plat-mxc/devices/Kconfig @@ -28,6 +28,10 @@ config IMX_HAVE_PLATFORM_IMX21_HCD config IMX_HAVE_PLATFORM_IMX2_WDT bool +config IMX_HAVE_PLATFORM_MVF_ADC + bool + default y if ARCH_MVF + config IMX_HAVE_PLATFORM_IMXDI_RTC bool @@ -37,6 +41,10 @@ config IMX_HAVE_PLATFORM_IMX_SRTC config IMX_HAVE_PLATFORM_IMX_SNVS_RTC bool +config IMX_HAVE_PLATFORM_MVF_CAAM + bool + default y if SOC_MVFA5 + config IMX_HAVE_PLATFORM_IMX_FB bool select HAVE_FB_IMX diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile index 63be99251f08..807de8385db0 100755 --- a/arch/arm/plat-mxc/devices/Makefile +++ b/arch/arm/plat-mxc/devices/Makefile @@ -62,5 +62,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC) += platform-imx-asrc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_DSI) += platform-imx-mipi_dsi.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2) += platform-imx-mipi_csi2.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_SPI) += platform-mvf-spi.o +obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_ADC) += platform-mvf-adc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_DCU) += platform-mvf-dcu.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_SAI) += platform-mvf-sai.o +obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_CAAM) += platform-mvf-caam.o diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c index d50c5b0be550..5d7605421294 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c @@ -18,6 +18,12 @@ .irq = soc ## _INT_USB_OTG, \ } +#define mvf_fsl_usb2_udc_data_entry_single(arch, _id) \ + { \ + .iobase = arch ## _USBC ## _id ## _BASE_ADDR, \ + .irq = arch ## _INT_USB ## _id, \ + } + #ifdef CONFIG_SOC_IMX25 const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst = imx_fsl_usb2_udc_data_entry_single(MX25); @@ -44,9 +50,15 @@ const struct imx_fsl_usb2_udc_data imx6q_fsl_usb2_udc_data __initconst = #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_ARCH_MVF +#ifdef CONFIG_MACH_PCM052 +const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data[] __initconst = { + mvf_fsl_usb2_udc_data_entry_single(MVF, 0), + mvf_fsl_usb2_udc_data_entry_single(MVF, 1), +#else const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data __initconst = { .iobase = MVF_USBC0_BASE_ADDR, .irq = MVF_INT_USBOTG0, +#endif }; #endif diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c index 523c5d4599e1..80c44f48393d 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. * * Copyright (C) 2010 Pengutronix * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> @@ -17,6 +17,13 @@ .irq_core = soc ## _INT_USB_ ## hs, \ } +#define mvf_fsl_usb2_wakeup_data_entry_single(arch, _id) \ + { \ + .id = _id, \ + .irq_phy = arch ## _INT_USB ## _id, \ + .irq_core = arch ## _INT_USB ## _id, \ + } + #ifdef CONFIG_SOC_IMX6Q const struct imx_fsl_usb2_wakeup_data imx6q_fsl_otg_wakeup_data __initconst = imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 0, OTG); @@ -26,6 +33,26 @@ const struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] __initconst = { imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 3, HS3), }; #endif /* ifdef CONFIG_SOC_IMX6Q */ +#ifdef CONFIG_SOC_MVFA5 +const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst = { +#ifdef CONFIG_MACH_PCM052 + mvf_fsl_usb2_wakeup_data_entry_single(MVF, 0), + mvf_fsl_usb2_wakeup_data_entry_single(MVF, 1), +#else + { + .id = 0, + .irq_phy = MVF_INT_USBOTG0, + .irq_core = MVF_INT_USBOTG0, + }, + { + .id = 1, + .irq_phy = MVF_INT_USB2, + .irq_core = MVF_INT_USB2, + } +#endif +}; + +#endif struct platform_device *__init imx_add_fsl_usb2_wakeup( const struct imx_fsl_usb2_wakeup_data *data, diff --git a/arch/arm/plat-mxc/devices/platform-imx-asrc.c b/arch/arm/plat-mxc/devices/platform-imx-asrc.c index c112a9ba8671..a35617d71a0e 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-asrc.c +++ b/arch/arm/plat-mxc/devices/platform-imx-asrc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-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 version 2 as published by the @@ -38,6 +38,22 @@ const struct imx_imx_asrc_data imx6q_imx_asrc_data[] __initconst = { }; #endif /* ifdef CONFIG_SOC_IMX6Q */ +#ifdef CONFIG_SOC_MVFA5 +const struct imx_imx_asrc_data mvf_imx_asrc_data[] __initconst = { + [0] = { + .id = 0, + .iobase = MVF_ASRC_BASE_ADDR, + .iosize = SZ_4K, + .irq = MVF_INT_ASRC, + .dmatx1 = DMA_MUX12_ASRC0_TX + 64, + .dmarx1 = DMA_MUX12_ASRC0_RX + 64, + .dmatx2 = DMA_MUX12_ASRC1_TX + 64, + .dmarx2 = DMA_MUX12_ASRC1_RX + 64, + .dmatx3 = DMA_MUX12_ASRC2_TX + 64, + .dmarx3 = DMA_MUX12_ASRC2_RX + 64, + }, +}; +#endif struct platform_device *__init imx_add_imx_asrc( const struct imx_imx_asrc_data *data, const struct imx_asrc_platform_data *pdata) diff --git a/arch/arm/plat-mxc/devices/platform-imx-pm.c b/arch/arm/plat-mxc/devices/platform-imx-pm.c index f901e18368c2..2b55d0344830 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-pm.c +++ b/arch/arm/plat-mxc/devices/platform-imx-pm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -30,6 +30,11 @@ const struct imx_pm_imx_data imx6q_pm_imx_data[] __initconst = imx_pm_imx_data_entry_single(MX6Q); #endif +#ifdef CONFIG_SOC_MVFA5 +const struct imx_pm_imx_data mvf_pm_imx_data[] __initconst = + imx_pm_imx_data_entry_single(MVF); +#endif + struct platform_device *__init imx_add_pm_imx( const struct imx_pm_imx_data *data, const struct pm_platform_data *pdata) diff --git a/arch/arm/plat-mxc/devices/platform-mvf-adc.c b/arch/arm/plat-mxc/devices/platform-mvf-adc.c new file mode 100644 index 000000000000..38add8b5fd4f --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-mvf-adc.c @@ -0,0 +1,50 @@ +/* + * 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 <asm/sizes.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> +#include <linux/clk.h> +#include <linux/gpio.h> + +#define mvf_adc_data_entry_single(soc, _id, _size) \ + { \ + .id = _id, \ + .iobase = soc ## _ADC ## _id ## _BASE_ADDR, \ + .iosize = _size, \ + .irq = soc ## _INT_ADC ## _id, \ + } +#define mvf_adc_data_entry(soc, _id, _size) \ + [_id] = mvf_adc_data_entry_single(soc, _id, _size) + +#ifdef CONFIG_SOC_MVFA5 +const struct mvf_adc_data mvfa5_adc_data[] __initconst = { + mvf_adc_data_entry(MVF, 0, SZ_4K), +}; +#endif + +struct platform_device *__init mvf_add_adcdev( + const struct mvf_adc_data *data) +{ + struct resource res[] = { + { + .start = data->iobase, + .end = data->iobase + data->iosize - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = data->irq, + .end = data->irq, + .flags = IORESOURCE_IRQ, + }, + }; + + return imx_add_platform_device("mvf-adc", data->id, res, + ARRAY_SIZE(res), NULL, 0); +} diff --git a/arch/arm/plat-mxc/devices/platform-mvf-caam.c b/arch/arm/plat-mxc/devices/platform-mvf-caam.c new file mode 100644 index 000000000000..0f716911698f --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-mvf-caam.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * 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 <asm/sizes.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> + +/* + * security violation interrupt is used as CAAM base _INT_SNVS_SEC + * SNVS consolidated = _INT_SNVS + * JR0 = MXC_INT_CAAM_INT0_NUM + * JR1 = MXC_INT_CAAM_INT1_NUM + */ + +const struct mvf_caam_data mvf_caam_data __initconst = { + .iobase_caam = MVF_CAAM_BASE_ADDR, + .iobase_caam_sm = MVF_CAAM_SECMEM_BASE_ADDR, + .iobase_snvs = MVF_SNVS_BASE_ADDR, + .irq_sec_vio = MVF_INT_SNVS_SEC, + .irq_snvs = MVF_INT_SNVS, + .jr[0].offset_jr = 0x1000, + .jr[0].irq_jr = MVF_INT_CAAM, + .jr[1].offset_jr = 0x2000, + .jr[1].irq_jr = MVF_INT_CAAM, +}; + +struct platform_device *__init mvf_add_caam( + const struct mvf_caam_data *data) +{ + u32 res_count = 0; + struct resource res[] = { + { + /* Define base range for entire CAAM register map */ + .name = "iobase_caam", + .start = data->iobase_caam, + .end = data->iobase_caam + ((SZ_32K + SZ_4K) - 1), + .flags = IORESOURCE_MEM, + }, { + /* Define range for secure memory */ + .name = "iobase_caam_sm", + .start = data->iobase_caam_sm, + .end = data->iobase_caam_sm + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + /* Define range for SNVS */ + .name = "iobase_snvs", + .start = data->iobase_snvs, + .end = data->iobase_snvs + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + /* Define interrupt for security violations */ + .name = "irq_sec_vio", + .start = data->irq_sec_vio, + .end = data->irq_sec_vio, + .flags = IORESOURCE_IRQ, + }, { + /* Define general SNVS interrupt */ + .name = "irq_snvs", + .start = data->irq_snvs, + .end = data->irq_snvs, + .flags = IORESOURCE_IRQ, + }, { + .name = "offset_jr0", + .start = data->jr[0].offset_jr, + .end = data->jr[0].offset_jr, + .flags = IORESOURCE_MEM, + }, { + .name = "irq_jr0", + .start = data->jr[0].irq_jr, + .end = data->jr[0].irq_jr, + .flags = IORESOURCE_IRQ, + }, { + .name = "offset_jr1", + .start = data->jr[1].offset_jr, + .end = data->jr[1].offset_jr, + .flags = IORESOURCE_MEM, + }, { + .name = "irq_jr1", + .start = data->jr[1].irq_jr, + .end = data->jr[1].irq_jr, + .flags = IORESOURCE_IRQ, + }, + }; + + res_count = ARRAY_SIZE(res); + BUG_ON(!res_count); + + return imx_add_platform_device("caam", 0, + res, ARRAY_SIZE(res), NULL, 0); +} diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c index f700d656c3b7..928f3b792e0f 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c @@ -16,6 +16,13 @@ .irq = soc ## _INT_USB_ ## hs, \ } +#define mvf_mxc_ehci_data_entry_single(arch, _id) \ + { \ + .id = _id, \ + .iobase = arch ## _USBC ## _id ## _BASE_ADDR, \ + .irq = arch ## _INT_USB ## _id, \ + } + #ifdef CONFIG_SOC_IMX25 const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst = imx_mxc_ehci_data_entry_single(MX25, 0, OTG); @@ -59,12 +66,18 @@ const struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] __initconst = { #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_ARCH_MVF +#ifdef CONFIG_MACH_PCM052 +const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data[] __initconst = { + mvf_mxc_ehci_data_entry_single(MVF, 0), + mvf_mxc_ehci_data_entry_single(MVF, 1), +#else const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data __initconst = { .id = 0, .iobase = MVF_USBC1_BASE_ADDR, .irq = MVF_INT_USB2, -}; #endif +}; +#endif /* ifdef CONFIG_ARCH_MVF */ struct platform_device *__init imx_add_mxc_ehci( const struct imx_mxc_ehci_data *data, diff --git a/arch/arm/plat-mxc/include/mach/arc_otg.h b/arch/arm/plat-mxc/include/mach/arc_otg.h index 51945e0fa957..af06f51759e5 100755 --- a/arch/arm/plat-mxc/include/mach/arc_otg.h +++ b/arch/arm/plat-mxc/include/mach/arc_otg.h @@ -31,7 +31,7 @@ extern void __iomem *imx_otg_base; #define USB_OTGREGS_BASE MVF_IO_ADDRESS(0x40034000) #define USB_OTG2REGS_BASE MVF_IO_ADDRESS(0x400B4000) -#define USB_H1REGS_BASE MVF_IO_ADDRESS(0x400B4000) +#define USB_H1REGS_BASE MVF_IO_ADDRESS(0x40034000) /* dummy h2regs for MVF */ #define USB_H2REGS_BASE MVF_IO_ADDRESS(0x400B4000) #define USBC0_OTHERREGS_BASE MVF_IO_ADDRESS(0x40034800) diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index a8a8034c1010..0e2a2a1d13e9 100755 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -89,6 +89,15 @@ struct imx_imx2_wdt_data { struct platform_device *__init imx_add_imx2_wdt( const struct imx_imx2_wdt_data *data); +struct mvf_adc_data { + int id; + resource_size_t iobase; + resource_size_t iosize; + resource_size_t irq; +}; +struct platform_device *__init mvf_add_adcdev( + const struct mvf_adc_data *data); + struct imx_imxdi_rtc_data { resource_size_t iobase; resource_size_t irq; @@ -672,3 +681,20 @@ struct imx_rngb_data { struct platform_device *__init imx_add_rngb( const struct imx_rngb_data *data); + +struct mvf_caam_jr_data { + resource_size_t offset_jr; + resource_size_t irq_jr; +}; + +struct mvf_caam_data { + resource_size_t iobase_caam; /* entirety of CAAM register map */ + resource_size_t iobase_caam_sm; /* base of secure memory */ + resource_size_t iobase_snvs; /* base of SNVS */ + resource_size_t irq_sec_vio; /* SNVS security violation */ + resource_size_t irq_snvs; /* SNVS consolidated (incl. RTC) */ + struct mvf_caam_jr_data jr[4]; /* offset+IRQ for each possible ring */ +}; + +struct platform_device *__init mvf_add_caam( + const struct mvf_caam_data *data); diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index a838e0bbead9..eb093e2c0f7f 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -40,9 +40,8 @@ typedef enum iomux_config { #define NON_MUX_I 0x3FF #define NON_PAD_I 0x7FF -#define MVF600_SDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH | \ - PAD_CTL_DSE_20ohm | PAD_CTL_OBE_IBE_ENABLE) +#define MVF600_SDHC_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_50ohm | PAD_CTL_OBE_IBE_ENABLE) #define MVF600_ENET_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ PAD_CTL_DSE_50ohm) @@ -196,16 +195,19 @@ typedef enum iomux_config { MVF600_ENET_PAD_CTRL | PAD_CTL_OBE_ENABLE) /*USB0/1 VBUS, using the GPIO*/ -#define MVF600_PAD134_PTA7__USB0_VBUS_EN \ +#define MVF600_PAD134_PTA7__USB_VBUS_EN \ IOMUX_PAD(0x0218, 0x0218, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE) + PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_25ohm | \ + PAD_CTL_SPEED_LOW | PAD_CTL_OBE_ENABLE) #define MVF600_PAD6_PTA16__USB0_VBUS_EN \ IOMUX_PAD(0x0018, 0x0018, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE) - + PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_25ohm | \ + PAD_CTL_SPEED_LOW | PAD_CTL_OBE_ENABLE) #define MVF600_PAD7_PTA17__USB_OC_N \ IOMUX_PAD(0x001C, 0x001C, 2, 0x0000, 0, \ - PAD_CTL_DSE_20ohm | PAD_CTL_IBE_ENABLE) + PAD_CTL_HYS | PAD_CTL_IBE_ENABLE) /*ESAI0(share with FEC1)*/ #define MVF600_PAD54_PTC9__ESAI_SCKT \ diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index 9ef4de35d4c0..4a47636fa741 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -53,8 +53,7 @@ * IRAM */ #define MVF_IRAM_BASE_ADDR 0x3F000000 /* internal ram */ -#define MVF_IRAM_PARTITIONS 2 -#define MVF_IRAM_SIZE (MVF_IRAM_PARTITIONS * SZ_256K) /* 512KB */ +#define MVF_IRAM_SIZE (SZ_256K) /* 256KB */ #ifdef CONFIG_MXC_VPU_IRAM @@ -146,7 +145,7 @@ #define MVF_PIT_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00037000) #define MVF_FTM0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00038000) #define MVF_FTM1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00039000) -#define MVF_ADC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003B000) +#define MVF_ADC0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003B000) #define MVF_TCON0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003D000) #define MVF_WDOG1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003E000) #define MVF_LPTMR_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00040000) @@ -169,24 +168,29 @@ #define MVF_EWM_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00065000) #define MVF_I2C0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00066000) #define MVF_I2C1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00067000) -#define MVF_WKUP_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006A000) +#define MVF_WKPU_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006A000) #define MVF_CCM_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006B000) -#define MVF_GPC_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006C000) -#define MVF_VREG_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006D000) -#define MVF_SRC_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006E000) +#define MVF_GPC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006C000) +#define MVF_VREG_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006D000) +#define MVF_SRC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006E000) #define MVF_CMU_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006F000) +#define MVF_CAAM_SECMEM_BASE_ADDR \ + (MVF_AIPS0_BASE_ADDR + 0x0007C000) +#define MVF_CAAM_SECMEM_END_ADDR \ + (MVF_AIPS0_BASE_ADDR + 0x0007FFFF) + #define L2_BASE_ADDR MVF_L2C_BASE_ADDR -#define MVF_USBC0_CTRL_BASE_ADDR 0x40034800 -#define MVF_USBC1_CTRL_BASE_ADDR 0x400B4800 -#define MVF_USBC0_PHY_BASE_ADDR 0x40034818 -#define MVF_USBC1_PHY_BASE_ADDR 0x400B4818 +#define MVF_USBC0_CTRL_BASE_ADDR 0x40035800 +#define MVF_USBC1_CTRL_BASE_ADDR 0x400B5800 +#define MVF_USBC0_PHY_BASE_ADDR 0x40035818 +#define MVF_USBC1_PHY_BASE_ADDR 0x400B5818 #define MVF_USBC0_BASE_ADDR 0x40034000 #define MVF_USBC1_BASE_ADDR 0x400B4000 #define MVF_USBPHY0_BASE_ADDR 0x40050800 -#define MVF_USBPHY1_BASE_ADDR 0x40050B00 +#define MVF_USBPHY1_BASE_ADDR 0x40050C00 #define MVF_MSCM_INT_ROUTER_BASE (MVF_MSCM_BASE_ADDR + 0x800) @@ -283,6 +287,12 @@ #define MVF_PGC_GPU_PGCR (MVF_PGC_GPU_BASE + 0x0) #define MVF_PGC_GPU_PGSR (MVF_PGC_GPU_BASE + 0xC) +/* Voltage Regulators */ +#define MVF_VREG_BASE (MVF_IO_ADDRESS(MVF_VREG_BASE_ADDR)) + +/* WKPU */ +#define MVF_WKPU_BASE (MVF_IO_ADDRESS(MVF_WKPU_BASE_ADDR)) + /* * defines for SPBA modules */ @@ -543,8 +553,13 @@ #define MVF_INT_I2C1 104 #define MVF_INT_I2C2 105 #define MVF_INT_I2C3 106 -#define MVF_INT_USBOTG0 107 -#define MVF_INT_USB2 108 + +#ifdef CONFIG_MACH_PCM052 +#define MVF_INT_USB0 107 +#define MVF_INT_USB1 108 +#else +#endif + #define MVF_INT_ENET_MAC0 110 #define MVF_INT_ENET_MAC1 111 #define MVF_INT_1588_TIMER0 112 @@ -558,15 +573,16 @@ #define MVF_INT_ESAI_BIFIFO 120 #define MVF_INT_SPDIF 121 #define MVF_INT_ASRC 122 -#define MVF_INT_CMU 123 +#define MVF_INT_CMU 123 #define MVF_INT_WKPU0 124 #define MVF_INT_WKPU1 125 -#define MVF_INT_CCM 126 +#define MVF_INT_CCM 126 -#define MVF_INT_SRC 128 -#define MVF_INT_PDB 129 -#define MVF_INT_EWM 130 +#define MVF_INT_SRC 128 +#define MVF_INT_PDB 129 +#define MVF_INT_EWM 130 #define MVF_INT_SNVS 132 +#define MVF_INT_SNVS_SEC 133 #define MVF_INT_CAAM 134 diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index afcf1255150b..b291d9015025 100755 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -257,6 +257,15 @@ struct cpu_op { u32 cpu_podf; }; +#ifdef CONFIG_SOC_MVFA5 +enum mvf_cpu_pwr_mode { + RUN_MODE, + LOW_POWER_RUN, + WAIT_MODE, + STOP_MODE, + LOW_POWER_STOP, +}; +#else enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ WAIT_UNCLOCKED, /* WAIT */ @@ -265,10 +274,15 @@ enum mxc_cpu_pwr_mode { STOP_POWER_OFF, /* STOP + SRPG */ ARM_POWER_OFF, /* STOP + SRPG + ARM power off */ }; +#endif int tzic_enable_wake(int is_idle); +#ifdef CONFIG_SOC_MVFA5 +extern void mvf_cpu_lp_set(enum mvf_cpu_pwr_mode mode); +#else extern void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode); +#endif extern int tzic_enable_wake(int is_idle); #endif diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c index 0aa3d590d1d2..96cede81d319 100755 --- a/arch/arm/plat-mxc/usb_common.c +++ b/arch/arm/plat-mxc/usb_common.c @@ -1049,6 +1049,9 @@ EXPORT_SYMBOL(usb_debounce_id_vbus); int usb_event_is_otg_wakeup(struct fsl_usb2_platform_data *pdata) { +#ifdef CONFIG_ARCH_MVF + return false; +#endif return (USBCTRL & UCTRL_OWIR) ? true : false; } EXPORT_SYMBOL(usb_event_is_otg_wakeup); diff --git a/arch/arm/plat-mxc/usb_wakeup.c b/arch/arm/plat-mxc/usb_wakeup.c index 4704eae91a51..7187eff67426 100755 --- a/arch/arm/plat-mxc/usb_wakeup.c +++ b/arch/arm/plat-mxc/usb_wakeup.c @@ -36,7 +36,8 @@ struct wakeup_ctrl { struct task_struct *thread; struct completion event; }; -static struct wakeup_ctrl *g_ctrl; +static struct wakeup_ctrl *g_ctrl[2]; +static unsigned int g_ctrls; extern int usb_event_is_otg_wakeup(struct fsl_usb2_platform_data *pdata); extern void usb_debounce_id_vbus(void); @@ -166,7 +167,7 @@ static int wakeup_dev_probe(struct platform_device *pdev) int status; unsigned long interrupt_flag; - printk(KERN_INFO "IMX usb wakeup probe\n"); + printk(KERN_INFO "IMX usb wakeup probe. id=%d\n", pdev->id); if (!pdev || !pdev->dev.platform_data) return -ENODEV; @@ -192,11 +193,12 @@ static int wakeup_dev_probe(struct platform_device *pdev) if (status) goto error1; - ctrl->thread = kthread_run(wakeup_event_thread, (void *)ctrl, "usb_wakeup thread"); + ctrl->thread = kthread_run(wakeup_event_thread, (void *)ctrl, + "usb_wakeup:%d", pdev->id); status = IS_ERR(ctrl->thread) ? -1 : 0; if (status) goto error2; - g_ctrl = ctrl; + g_ctrl[g_ctrls++] = ctrl; printk(KERN_DEBUG "the wakeup pdata is 0x%p\n", pdata); return 0; @@ -209,12 +211,17 @@ error1: static int wakeup_dev_exit(struct platform_device *pdev) { - if (g_ctrl->thread) { - complete(&g_ctrl->event); - kthread_stop(g_ctrl->thread); + int i; + for (i = 0; i < g_ctrls; i++) { + if (g_ctrl[i]->thread) { + complete(&g_ctrl[i]->event); + kthread_stop(g_ctrl[i]->thread); + } + free_irq(g_ctrl[i]->wakeup_irq, (void *)g_ctrl[i]); + kfree(g_ctrl[i]); + g_ctrl[i] = NULL; + g_ctrls = 0; } - free_irq(g_ctrl->wakeup_irq, (void *)g_ctrl); - kfree(g_ctrl); return 0; } static struct platform_driver wakeup_d = { |