diff options
author | Xinyu Chen <xinyu.chen@freescale.com> | 2012-11-30 11:59:33 +0800 |
---|---|---|
committer | Xinyu Chen <xinyu.chen@freescale.com> | 2012-11-30 11:59:33 +0800 |
commit | 08c473f52af7434b09214fedcfce222fb9821033 (patch) | |
tree | 555dc016292a132bd55096d42c945c61c6394174 /arch | |
parent | 9ae3b66a8ea648d977cbcebf02209f21cc9be3a4 (diff) | |
parent | 57ade285e32285186879f96c346dd5b45a7f0dd6 (diff) |
Merge remote-tracking branch 'fsl-linux-sdk/imx_3.0.35_1.1.0' into imx_3.0.35_android
Conflicts:
arch/arm/mach-mx6/board-mx6q_sabrelite.c
arch/arm/mach-mx6/board-mx6q_sabresd.c
arch/arm/plat-mxc/cpufreq.c
Diffstat (limited to 'arch')
45 files changed, 910 insertions, 384 deletions
diff --git a/arch/arm/configs/imx6_android_defconfig b/arch/arm/configs/imx6_android_defconfig index 5f8803d2bba9..0d0e0a3ac67a 100644 --- a/arch/arm/configs/imx6_android_defconfig +++ b/arch/arm/configs/imx6_android_defconfig @@ -338,6 +338,7 @@ CONFIG_MACH_MX6Q_SABREAUTO=y # # CONFIG_IMX_PCIE is not set CONFIG_USB_EHCI_ARC_H1=y +CONFIG_USB_FSL_ARC_OTG=y # CONFIG_MX6_INTER_LDO_BYPASS is not set CONFIG_MX6_CLK_FOR_BOOTUI_TRANS=y CONFIG_ISP1504_MXC=y @@ -1388,6 +1389,7 @@ CONFIG_TOUCHSCREEN_MAX11801=y # CONFIG_TOUCHSCREEN_TOUCHWIN is not set # CONFIG_TOUCHSCREEN_WM97XX is not set # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_NOVATEK is not set # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set # CONFIG_TOUCHSCREEN_TSC2005 is not set # CONFIG_TOUCHSCREEN_TSC2007 is not set diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig index 55cc89c7d735..6f30e36a0f5a 100644 --- a/arch/arm/configs/imx6_defconfig +++ b/arch/arm/configs/imx6_defconfig @@ -316,6 +316,7 @@ CONFIG_MACH_MX6Q_SABREAUTO=y # # CONFIG_IMX_PCIE is not set CONFIG_USB_EHCI_ARC_H1=y +CONFIG_USB_FSL_ARC_OTG=y # CONFIG_MX6_INTER_LDO_BYPASS is not set # CONFIG_MX6_CLK_FOR_BOOTUI_TRANS is not set CONFIG_ISP1504_MXC=y @@ -2698,6 +2699,7 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y 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/configs/imx6_updater_defconfig b/arch/arm/configs/imx6_updater_defconfig index 06ffbc56eee5..8c58f193c8f8 100644 --- a/arch/arm/configs/imx6_updater_defconfig +++ b/arch/arm/configs/imx6_updater_defconfig @@ -325,6 +325,7 @@ CONFIG_MACH_MX6Q_SABREAUTO=y # MX6 Options: # # CONFIG_IMX_PCIE is not set +CONFIG_USB_FSL_ARC_OTG=y # CONFIG_MX6_INTER_LDO_BYPASS is not set # CONFIG_MX6_CLK_FOR_BOOTUI_TRANS is not set CONFIG_ISP1504_MXC=y diff --git a/arch/arm/configs/imx6s_defconfig b/arch/arm/configs/imx6s_defconfig index 41f43e5c0d63..0c980c9e5f77 100644 --- a/arch/arm/configs/imx6s_defconfig +++ b/arch/arm/configs/imx6s_defconfig @@ -322,6 +322,7 @@ CONFIG_MACH_MX6Q_SABRESD=y # # CONFIG_IMX_PCIE is not set CONFIG_USB_EHCI_ARC_H1=y +CONFIG_USB_FSL_ARC_OTG=y CONFIG_MX6_INTER_LDO_BYPASS=y CONFIG_ISP1504_MXC=y # CONFIG_MXC_IRQ_PRIOR is not set diff --git a/arch/arm/configs/imx6s_updater_defconfig b/arch/arm/configs/imx6s_updater_defconfig index bd227b39c4e5..b80f40128dfc 100644 --- a/arch/arm/configs/imx6s_updater_defconfig +++ b/arch/arm/configs/imx6s_updater_defconfig @@ -326,6 +326,7 @@ CONFIG_MACH_MX6Q_SABREAUTO=y # MX6 Options: # # CONFIG_IMX_PCIE is not set +CONFIG_USB_FSL_ARC_OTG=y CONFIG_MX6_INTER_LDO_BYPASS=y CONFIG_ISP1504_MXC=y # CONFIG_MXC_IRQ_PRIOR is not set diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index 97262dced063..2ffd90d06a06 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -261,6 +261,9 @@ config USB_EHCI_ARC_H1 tristate "USB Host 1 support" depends on USB_EHCI_ARC +config USB_FSL_ARC_OTG + tristate "FSL USB OTG support" + config MX6_INTER_LDO_BYPASS bool "Internal LDO in MX6Q/DL bypass" depends on REGULATOR_PFUZE100 && CPU_FREQ_IMX && ARCH_MX6 diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile index 05dc62dac468..c929f2e56cfc 100644 --- a/arch/arm/mach-mx6/Makefile +++ b/arch/arm/mach-mx6/Makefile @@ -3,7 +3,7 @@ # # Object file lists. -obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h2.o usb_h3.o\ +obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_h2.o usb_h3.o\ pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \ mx6_mmdc.o mx6_ddr_freq.o mx6sl_ddr.o mx6sl_wfi.o etm.o @@ -18,3 +18,4 @@ obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_IMX_PCIE) += pcie.o obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o +obj-$(CONFIG_USB_FSL_ARC_OTG) += usb_dr.o
\ No newline at end of file diff --git a/arch/arm/mach-mx6/board-mx6dl_sabresd.h b/arch/arm/mach-mx6/board-mx6dl_sabresd.h index 7e6a26143a49..fe278e82491f 100644 --- a/arch/arm/mach-mx6/board-mx6dl_sabresd.h +++ b/arch/arm/mach-mx6/board-mx6dl_sabresd.h @@ -263,8 +263,8 @@ static iomux_v3_cfg_t mx6dl_sabresd_pads[] = { /* ACCL_INT_INT */ MX6DL_PAD_SD1_CMD__GPIO_1_18, - /* USR_DEF_GRN_LED */ - MX6DL_PAD_GPIO_1__GPIO_1_1, + /*WDOG_B to reset pmic*/ + MX6DL_PAD_GPIO_1__WDOG2_WDOG_B, /* USR_DEF_RED_LED */ MX6DL_PAD_GPIO_2__GPIO_1_2, }; diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index 12f87b526253..cc38ebaa412b 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -174,7 +174,6 @@ extern char *gp_reg_id; extern char *soc_reg_id; extern char *pu_reg_id; extern int epdc_enabled; -extern void mx6_cpu_regulator_init(void); static int max17135_regulator_init(struct max17135 *max17135); enum sd_pad_mode { @@ -1245,7 +1244,7 @@ static void __init mx6_arm2_init_usb(void) mxc_iomux_set_gpr_register(1, 13, 1, 1); mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus); - mx6_usb_dr_init(); + #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); mx6_usb_h3_init(); @@ -2191,7 +2190,6 @@ static void __init mx6_arm2_init(void) mx6_arm2_init_usb(); mx6_arm2_init_audio(); platform_device_register(&arm2_vmmc_reg_devices); - mx6_cpu_regulator_init(); imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c index 6caaa708d4a9..3142f4fe3cf1 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c @@ -409,7 +409,12 @@ static struct mtd_partition m25p32_partitions[] = { { .name = "bootloader", .offset = 0, - .size = 0x00100000, + .size = SZ_256K, + }, { + .name = "bootenv", + .offset = MTDPART_OFS_APPEND, + .size = SZ_8K, + .mask_flags = MTD_WRITEABLE, }, { .name = "kernel", .offset = MTDPART_OFS_APPEND, @@ -439,17 +444,28 @@ static void spi_device_init(void) spi_register_board_info(m25p32_spi0_board_info, ARRAY_SIZE(m25p32_spi0_board_info)); } + static struct mtd_partition mxc_nor_partitions[] = { { - .name = "Bootloader", + .name = "bootloader", .offset = 0, - .size = 0x00080000, + .size = SZ_256K, + }, { + .name = "bootenv", + .offset = MTDPART_OFS_APPEND, + .size = SZ_256K, + .mask_flags = MTD_WRITEABLE, }, { - .name = "nor.Kernel", + .name = "kernel", .offset = MTDPART_OFS_APPEND, + .size = SZ_4M, + }, { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, .size = MTDPART_SIZ_FULL, }, }; + static struct resource nor_flash_resource = { .start = CS0_BASE_ADDR, .end = CS0_BASE_ADDR + 0x02000000 - 1, @@ -770,7 +786,6 @@ static void __init imx6q_sabreauto_init_usb(void) mxc_iomux_set_gpr_register(1, 13, 1, 0); mx6_set_otghost_vbus_func(imx6q_sabreauto_usbotg_vbus); - mx6_usb_dr_init(); mx6_set_host1_vbus_func(imx6q_sabreauto_usbhost1_vbus); #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); @@ -1280,9 +1295,8 @@ static struct mxc_mlb_platform_data mx6_sabreauto_mlb150_data = { }; static struct mxc_dvfs_platform_data sabreauto_dvfscore_data = { - .reg_id = "cpu_vddgp", - .soc_id = "cpu_vddsoc", - .pu_id = "cpu_vddvpu", + .reg_id = "VDDCORE", + .soc_id = "VDDSOC", .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, @@ -1535,7 +1549,6 @@ static void __init mx6_board_init(void) gp_reg_id = sabreauto_dvfscore_data.reg_id; soc_reg_id = sabreauto_dvfscore_data.soc_id; - pu_reg_id = sabreauto_dvfscore_data.pu_id; mx6q_sabreauto_init_uart(); imx6q_add_mipi_csi2(&mipi_csi2_pdata); if (cpu_is_mx6dl()) { @@ -1613,7 +1626,6 @@ static void __init mx6_board_init(void) imx6q_add_vpu(); imx6q_init_audio(); platform_device_register(&sabreauto_vmmc_reg_devices); - mx6_cpu_regulator_init(); imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); imx6q_add_asrc(&imx_asrc_data); diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c index 14ea0a638d94..d68af73a61b6 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c +++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c @@ -104,10 +104,10 @@ static struct clk *sata_clk; extern char *gp_reg_id; extern char *soc_reg_id; extern char *pu_reg_id; +static int caam_enabled; extern struct regulator *(*get_cpu_regulator)(void); extern void (*put_cpu_regulator)(void); -extern void mx6_cpu_regulator_init(void); static iomux_v3_cfg_t mx6q_sabrelite_pads[] = { /* AUDMUX */ @@ -671,7 +671,6 @@ static void __init imx6q_sabrelite_init_usb(void) mxc_iomux_set_gpr_register(1, 13, 1, 1); mx6_set_otghost_vbus_func(imx6q_sabrelite_usbotg_vbus); - mx6_usb_dr_init(); } /* HW Initialization, if return 0, initialization is successful. */ @@ -1175,6 +1174,13 @@ static int __init imx6x_add_ram_console(void) #define imx6x_add_ram_console() do {} while (0) #endif +static int __init caam_setup(char *__unused) +{ + caam_enabled = 1; + return 1; +} +early_param("caam", caam_setup); + /*! * Board specific initialization. */ @@ -1219,7 +1225,8 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_mipi_csi2(&mipi_csi2_pdata); imx6q_add_imx_snvs_rtc(); - imx6q_add_imx_caam(); + if (1 == caam_enabled) + imx6q_add_imx_caam(); imx6q_add_imx_i2c(0, &mx6q_sabrelite_i2c_data); imx6q_add_imx_i2c(1, &mx6q_sabrelite_i2c_data); @@ -1267,7 +1274,6 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_dma(); imx6q_add_dvfs_core(&sabrelite_dvfscore_data); - mx6_cpu_regulator_init(); imx6q_add_ion(0, &imx_ion_data, sizeof(imx_ion_data) + sizeof(struct ion_platform_heap)); diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index 258f2a7228ae..aee782ff0d91 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -205,7 +205,7 @@ static int mma8451_position; static int mag3110_position = 1; static int max11801_mode = 1; static int enable_lcd_ldb; - +static int caam_enabled; extern char *gp_reg_id; extern char *soc_reg_id; @@ -1119,7 +1119,7 @@ static void __init imx6q_sabresd_init_usb(void) mxc_iomux_set_gpr_register(1, 13, 1, 0); mx6_set_otghost_vbus_func(imx6q_sabresd_usbotg_vbus); - mx6_usb_dr_init(); + } /* HW Initialization, if return 0, initialization is successful. */ @@ -1634,14 +1634,8 @@ static struct platform_pwm_backlight_data mx6_sabresd_pwm_backlight_data = { }; static struct mxc_dvfs_platform_data sabresd_dvfscore_data = { -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .reg_id = "VDDCORE", .soc_id = "VDDSOC", -#else - .reg_id = "cpu_vddgp", - .soc_id = "cpu_vddsoc", - .pu_id = "cpu_vddvpu", -#endif .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, @@ -1720,6 +1714,13 @@ static struct mipi_csi2_platform_data mipi_csi2_pdata = { .pixel_clk = "emi_clk", }; +static int __init caam_setup(char *__unused) +{ + caam_enabled = 1; + return 1; +} +early_param("caam", caam_setup); + #define SNVS_LPCR 0x38 static void mx6_snvs_poweroff(void) { @@ -1795,7 +1796,6 @@ static void __init mx6_sabresd_board_init(void) gp_reg_id = sabresd_dvfscore_data.reg_id; soc_reg_id = sabresd_dvfscore_data.soc_id; - pu_reg_id = sabresd_dvfscore_data.pu_id; mx6q_sabresd_init_uart(); imx6x_add_ram_console(); @@ -1835,7 +1835,8 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_mipi_csi2(&mipi_csi2_pdata); imx6q_add_imx_snvs_rtc(); - imx6q_add_imx_caam(); + if (1 == caam_enabled) + imx6q_add_imx_caam(); if (board_is_mx6_reva()) { strcpy(mxc_i2c0_board_info[0].type, "wm8958"); @@ -1914,13 +1915,11 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_dma(); imx6q_add_dvfs_core(&sabresd_dvfscore_data); -#ifndef CONFIG_MX6_INTER_LDO_BYPASS - mx6_cpu_regulator_init(); -#endif if (imx_ion_data.heaps[0].size) imx6q_add_ion(0, &imx_ion_data, sizeof(imx_ion_data) + sizeof(struct ion_platform_heap)); + imx6q_add_device_buttons(); /* enable sensor 3v3 and 1v8 */ diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.h b/arch/arm/mach-mx6/board-mx6q_sabresd.h index da26cd9e0c83..a1f5cd9166a3 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.h +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.h @@ -30,7 +30,7 @@ static iomux_v3_cfg_t mx6q_sabresd_pads[] = { /* CAN1 */ MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE, /* MX6Q_PAD_KEY_COL2__CAN1_TXCAN, */ - MX6Q_PAD_GPIO_1__GPIO_1_1, /* user defiend green led */ + MX6Q_PAD_GPIO_1__WDOG2_WDOG_B, /*WDOG_B to reset pmic*/ MX6Q_PAD_GPIO_2__GPIO_1_2, /* user defined red led */ MX6Q_PAD_GPIO_7__GPIO_1_7, /* NERR */ diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c index c69fe8e35217..e8cb14b91e54 100755 --- a/arch/arm/mach-mx6/board-mx6sl_arm2.c +++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c @@ -582,14 +582,8 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { }; static struct mxc_dvfs_platform_data mx6sl_arm2_dvfscore_data = { -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .reg_id = "VDDCORE", .soc_id = "VDDSOC", -#else - .reg_id = "cpu_vddgp", - .soc_id = "cpu_vddsoc", - .pu_id = "cpu_vddvpu", -#endif .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, @@ -1079,7 +1073,6 @@ static void __init mx6_arm2_init_usb(void) gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1); mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus); - mx6_usb_dr_init(); #ifdef CONFIG_USB_EHCI_ARC_HSIC mxc_iomux_set_specialbits_register(MX6SL_PAD_HSIC_DAT, PAD_CTL_DDR_SEL_DDR3, PAD_CTL_DDR_SEL_MASK); @@ -1219,15 +1212,8 @@ static void __init mx6_arm2_init(void) elan_ts_init(); -#ifdef CONFIG_MX6_INTER_LDO_BYPASS - gp_reg_id = mx6sl_arm2_dvfscore_data.reg_id; - soc_reg_id = mx6sl_arm2_dvfscore_data.soc_id; -#else gp_reg_id = mx6sl_arm2_dvfscore_data.reg_id; soc_reg_id = mx6sl_arm2_dvfscore_data.soc_id; - pu_reg_id = mx6sl_arm2_dvfscore_data.pu_id; - mx6_cpu_regulator_init(); -#endif imx6q_add_imx_snvs_rtc(); diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h index a6e5e909c6a9..1170cb631ed3 100644 --- a/arch/arm/mach-mx6/board-mx6sl_common.h +++ b/arch/arm/mach-mx6/board-mx6sl_common.h @@ -461,6 +461,7 @@ static iomux_v3_cfg_t suspend_enter_pads[] = { MX6SL_PAD_SD1_DAT5__GPIO_5_9, MX6SL_PAD_SD1_DAT6__GPIO_5_7, MX6SL_PAD_SD1_DAT7__GPIO_5_10, + MX6SL_PAD_SD2_CLK__GPIO_5_5, MX6SL_PAD_SD2_CMD__GPIO_5_4, MX6SL_PAD_SD2_DAT0__GPIO_5_1, @@ -469,18 +470,19 @@ static iomux_v3_cfg_t suspend_enter_pads[] = { MX6SL_PAD_SD2_DAT3__GPIO_4_28, MX6SL_PAD_SD2_DAT4__GPIO_5_2, MX6SL_PAD_SD2_DAT5__GPIO_4_31, - MX6SL_PAD_SD2_DAT6__GPIO_4_29, - MX6SL_PAD_SD2_DAT7__GPIO_5_0, + MX6SL_PAD_SD3_CLK__GPIO_5_18, MX6SL_PAD_SD3_CMD__GPIO_5_21, MX6SL_PAD_SD3_DAT0__GPIO_5_19, MX6SL_PAD_SD3_DAT1__GPIO_5_20, MX6SL_PAD_SD3_DAT2__GPIO_5_16, MX6SL_PAD_SD3_DAT3__GPIO_5_17, + /* USBOTG ID pin */ MX6SL_PAD_EPDC_PWRCOM__GPIO_2_11, MX6SL_PAD_HSIC_STROBE__GPIO_3_20, MX6SL_PAD_HSIC_DAT__GPIO_3_19, + /* Key row/column */ MX6SL_PAD_KEY_COL0__GPIO_3_24, MX6SL_PAD_KEY_COL1__GPIO_3_26, diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c index 47e8a8954c7d..46bacc1dc457 100644 --- a/arch/arm/mach-mx6/board-mx6sl_evk.c +++ b/arch/arm/mach-mx6/board-mx6sl_evk.c @@ -758,14 +758,8 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { }; static struct mxc_dvfs_platform_data mx6sl_evk_dvfscore_data = { -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .reg_id = "VDDCORE", .soc_id = "VDDSOC", -#else - .reg_id = "cpu_vddgp", - .soc_id = "cpu_vddsoc", - .pu_id = "cpu_vddvpu", -#endif .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, @@ -1264,7 +1258,7 @@ static void __init mx6_evk_init_usb(void) gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1); mx6_set_otghost_vbus_func(imx6_evk_usbotg_vbus); - mx6_usb_dr_init(); + #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); #endif @@ -1461,15 +1455,8 @@ static void __init mx6_evk_init(void) elan_ts_init(); -#ifdef CONFIG_MX6_INTER_LDO_BYPASS gp_reg_id = mx6sl_evk_dvfscore_data.reg_id; soc_reg_id = mx6sl_evk_dvfscore_data.soc_id; -#else - gp_reg_id = mx6sl_evk_dvfscore_data.reg_id; - soc_reg_id = mx6sl_evk_dvfscore_data.soc_id; - pu_reg_id = mx6sl_evk_dvfscore_data.pu_id; - mx6_cpu_regulator_init(); -#endif imx6q_add_imx_snvs_rtc(); diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 1a8636e6eb45..b8b7b7bfa9a7 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -4245,7 +4245,7 @@ static struct clk caam_clk[] = { __INIT_CLK_DEBUG(caam_ipg_clk) .id = 2, .enable_reg = MXC_CCM_CCGR0, - .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, .enable = _clk_enable, .disable = _clk_disable, .parent = &mmdc_ch0_axi_clk[0], diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c index fbb3827668e0..7a874da254f0 100644 --- a/arch/arm/mach-mx6/cpu.c +++ b/arch/arm/mach-mx6/cpu.c @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <mach/hardware.h> +#include <mach/system.h> #include <asm/io.h> #include <asm/mach/map.h> @@ -33,7 +34,8 @@ struct cpu_op *(*get_cpu_op)(int *op); bool enable_wait_mode = true; -u32 arm_max_freq = CPU_AT_1GHz; +u32 enable_ldo_mode = LDO_MODE_DEFAULT; +u32 arm_max_freq = CPU_AT_1_2GHz; bool mem_clk_on_in_wait; int chip_rev; @@ -245,6 +247,19 @@ static int __init arm_core_max(char *p) early_param("arm_freq", arm_core_max); +static int __init enable_ldo(char *p) +{ + if (memcmp(p, "on", 2) == 0) { + enable_ldo_mode = LDO_MODE_ENABLED; + p += 2; + } else if (memcmp(p, "off", 3) == 0) { + enable_ldo_mode = LDO_MODE_BYPASSED; + p += 3; + } + return 0; +} +early_param("ldo_active", enable_ldo); + static int __init enable_mem_clk_in_wait(char *p) { mem_clk_on_in_wait = true; diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c index e6ef0261a285..5124c5ee5985 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.c +++ b/arch/arm/mach-mx6/cpu_op-mx6.c @@ -13,10 +13,12 @@ #include <linux/types.h> #include <linux/kernel.h> +#include <asm/io.h> #include <mach/hardware.h> #include <mach/mxc_dvfs.h> #include "cpu_op-mx6.h" +#define OCOTP_SPEED_BIT_OFFSET (16) extern struct cpu_op *(*get_cpu_op)(int *op); extern struct dvfs_op *(*get_dvfs_core_op)(int *wp); extern void (*set_num_cpu_op)(int num); @@ -33,6 +35,13 @@ static struct cpu_op mx6q_cpu_op_1_2G[] = { .soc_voltage = 1275000, .cpu_voltage = 1275000,}, { + .pll_rate = 996000000, + .cpu_rate = 996000000, + .cpu_podf = 0, + .pu_voltage = 1250000, + .soc_voltage = 1250000, + .cpu_voltage = 1250000,}, + { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, @@ -153,8 +162,8 @@ static struct cpu_op mx6dl_cpu_op_1_2G[] = { .pll_rate = 1200000000, .cpu_rate = 1200000000, .cpu_podf = 0, - .pu_voltage = 1275000, - .soc_voltage = 1275000, + .pu_voltage = 1175000, + .soc_voltage = 1175000, .cpu_voltage = 1275000,}, { .pll_rate = 792000000, @@ -177,9 +186,9 @@ static struct cpu_op mx6dl_cpu_op_1G[] = { .pll_rate = 996000000, .cpu_rate = 996000000, .cpu_podf = 0, - .pu_voltage = 1275000, - .soc_voltage = 1275000, - .cpu_voltage = 1275000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1250000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, @@ -331,6 +340,20 @@ void mx6_set_num_cpu_op(int num) void mx6_cpu_op_init(void) { + unsigned int reg; + void __iomem *base; + if (cpu_is_mx6q()) { + /*read fuse bit to know the max cpu freq : offset 0x440 + * bit[17:16]:SPEED_GRADING[1:0]*/ + base = IO_ADDRESS(OCOTP_BASE_ADDR); + reg = __raw_readl(base + 0x440); + reg &= (0x3 << OCOTP_SPEED_BIT_OFFSET); + reg >>= OCOTP_SPEED_BIT_OFFSET; + /*choose the little value to run lower max cpufreq*/ + arm_max_freq = (reg > arm_max_freq) ? arm_max_freq : reg; + } else + arm_max_freq = CPU_AT_1GHz;/*mx6dl/sl max freq is 1Ghz*/ + printk(KERN_INFO "arm_max_freq=%x\n", arm_max_freq); get_cpu_op = mx6_get_cpu_op; set_num_cpu_op = mx6_set_num_cpu_op; diff --git a/arch/arm/mach-mx6/cpu_op-mx6.h b/arch/arm/mach-mx6/cpu_op-mx6.h index b5ca58ecb3b3..310cbb375ced 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.h +++ b/arch/arm/mach-mx6/cpu_op-mx6.h @@ -10,9 +10,9 @@ * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html */ - +/*The below value aligned with SPEED_GRADING bits in 0x440 fuse offset */ #define CPU_AT_800MHz 0 -#define CPU_AT_1GHz 1 -#define CPU_AT_1_2GHz 2 +#define CPU_AT_1GHz 2 +#define CPU_AT_1_2GHz 3 void mx6_cpu_op_init(void); diff --git a/arch/arm/mach-mx6/cpu_regulator-mx6.c b/arch/arm/mach-mx6/cpu_regulator-mx6.c index 8eb976d2eefd..d905132e98b1 100644 --- a/arch/arm/mach-mx6/cpu_regulator-mx6.c +++ b/arch/arm/mach-mx6/cpu_regulator-mx6.c @@ -20,11 +20,14 @@ #if defined(CONFIG_CPU_FREQ) #include <linux/cpufreq.h> #endif +#include <linux/io.h> #include <asm/cpu.h> #include <mach/clock.h> #include <mach/hardware.h> - +#include <mach/system.h> +#include "regs-anadig.h" +#include "crm_regs.h" struct regulator *cpu_regulator; struct regulator *soc_regulator; struct regulator *pu_regulator; @@ -37,6 +40,7 @@ static struct cpu_op *cpu_op_tbl; extern struct cpu_op *(*get_cpu_op)(int *op); extern unsigned long loops_per_jiffy; +extern u32 enable_ldo_mode; int external_pureg; static inline unsigned long mx6_cpu_jiffies(unsigned long old, u_int div, @@ -57,15 +61,31 @@ static inline unsigned long mx6_cpu_jiffies(unsigned long old, u_int div, #endif } - void mx6_cpu_regulator_init(void) { int cpu; u32 curr_cpu = 0; + unsigned int reg; #ifndef CONFIG_SMP unsigned long old_loops_per_jiffy; #endif + void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); external_pureg = 0; + /*If internal ldo actived, use internal cpu_* regulator to replace the + *regulator ids from board file. If internal ldo bypassed, use the + *regulator ids which defined in board file and source from extern pmic + *power rails. + *If you want to use ldo bypass,you should do: + *1.set enable_ldo_mode=LDO_MODE_BYPASSED in your board file by default + * or set in commandline from u-boot + *2.set your extern pmic regulator name in your board file. + */ + if (enable_ldo_mode != LDO_MODE_BYPASSED) { + gp_reg_id = "cpu_vddgp"; + soc_reg_id = "cpu_vddsoc"; + pu_reg_id = "cpu_vddgpu"; + } + printk(KERN_INFO "cpu regulator init ldo=%x\n", enable_ldo_mode); cpu_regulator = regulator_get(NULL, gp_reg_id); if (IS_ERR(cpu_regulator)) printk(KERN_ERR "%s: failed to get cpu regulator\n", __func__); @@ -81,6 +101,21 @@ void mx6_cpu_regulator_init(void) regulator_set_voltage(cpu_regulator, cpu_op_tbl[0].cpu_voltage, cpu_op_tbl[0].cpu_voltage); + if (enable_ldo_mode == LDO_MODE_BYPASSED) { + /*digital bypass VDDPU/VDDSOC/VDDARM*/ + reg = __raw_readl(ANADIG_REG_CORE); + reg &= ~BM_ANADIG_REG_CORE_REG0_TRG; + reg |= BF_ANADIG_REG_CORE_REG0_TRG(0x1f); + reg &= ~BM_ANADIG_REG_CORE_REG1_TRG; + reg |= BF_ANADIG_REG_CORE_REG1_TRG(0x1f); + reg &= ~BM_ANADIG_REG_CORE_REG2_TRG; + reg |= BF_ANADIG_REG_CORE_REG2_TRG(0x1f); + __raw_writel(reg, ANADIG_REG_CORE); + /* Mask the ANATOP brown out interrupt in the GPC. */ + reg = __raw_readl(gpc_base + 0x14); + reg |= 0x80000000; + __raw_writel(reg, gpc_base + 0x14); + } clk_set_rate(cpu_clk, cpu_op_tbl[0].cpu_rate); /*Fix loops-per-jiffy */ @@ -112,7 +147,7 @@ void mx6_cpu_regulator_init(void) pu_regulator = regulator_get(NULL, pu_reg_id); if (IS_ERR(pu_regulator)) printk(KERN_ERR "%s: failed to get pu regulator\n", __func__); - /*If enable CONFIG_MX6_INTER_LDO_BYPASS and VDDPU_IN is single supplied + /*If use ldo bypass and VDDPU_IN is single supplied *by external pmic, it means VDDPU_IN can be turned off if GPU/VPU driver *not running.In this case we should set external_pureg which can be used *in pu_enable/pu_disable of arch/arm/mach-mx6/mx6_anatop_regulator.c to @@ -122,11 +157,11 @@ void mx6_cpu_regulator_init(void) *In this case external_pureg should be 0 and can't turn off extern pmic *regulator, but can turn off VDDPU by internal anatop power gate. * - *If disable CONFIG_MX6_INTER_LDO_BYPASS, external_pureg will be 0, and + *If enable internal ldo , external_pureg will be 0, and *VDDPU can be turned off by internal anatop anatop power gate. * */ - else if (!IS_ERR(pu_regulator) && strcmp(pu_reg_id, "cpu_vddvpu")) + else if (!IS_ERR(pu_regulator) && strcmp(pu_reg_id, "cpu_vddgpu")) external_pureg = 1; } diff --git a/arch/arm/mach-mx6/irq.c b/arch/arm/mach-mx6/irq.c index 5863b951f01f..1a4e59c1fd42 100644 --- a/arch/arm/mach-mx6/irq.c +++ b/arch/arm/mach-mx6/irq.c @@ -103,9 +103,6 @@ void mx6_init_irq(void) void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); struct irq_desc *desc; unsigned int i; -#ifdef CONFIG_MX6_INTER_LDO_BYPASS - u32 reg; -#endif /* start offset if private timer irq id, which is 29. * ID table: @@ -124,12 +121,6 @@ void mx6_init_irq(void) __raw_writel(0x20000000, gpc_base + 0x10); } -#ifdef CONFIG_MX6_INTER_LDO_BYPASS - /* Mask the ANATOP brown out interrupt in the GPC. */ - reg = __raw_readl(gpc_base + 0x14); - reg |= 0x80000000; - __raw_writel(reg, gpc_base + 0x14); -#endif for (i = MXC_INT_START; i <= MXC_INT_END; i++) { desc = irq_to_desc(i); diff --git a/arch/arm/mach-mx6/mx6_anatop_regulator.c b/arch/arm/mach-mx6/mx6_anatop_regulator.c index 9599a5439e54..02ee982964ed 100644 --- a/arch/arm/mach-mx6/mx6_anatop_regulator.c +++ b/arch/arm/mach-mx6/mx6_anatop_regulator.c @@ -34,6 +34,7 @@ #include <linux/clk.h> #include <mach/clock.h> +#include <mach/system.h> #include "crm_regs.h" #include "regs-anadig.h" @@ -55,6 +56,7 @@ static struct clk *gpu3d_clk, *gpu3d_shade_clk, *gpu2d_clk, *gpu2d_axi_clk; static struct clk *openvg_axi_clk, *vpu_clk; extern int external_pureg; extern struct regulator *pu_regulator; +extern u32 enable_ldo_mode; static int get_voltage(struct anatop_regulator *sreg) @@ -185,13 +187,12 @@ static int pu_enable(struct anatop_regulator *sreg) reg = __raw_readl(ANA_MISC2_BASE_ADDR); reg |= ANADIG_ANA_MISC2_REG1_BO_EN; __raw_writel(reg, ANA_MISC2_BASE_ADDR); - -#ifndef CONFIG_MX6_INTER_LDO_BYPASS - /* Unmask the ANATOP brown out interrupt in the GPC. */ - reg = __raw_readl(gpc_base + 0x14); - reg &= ~0x80000000; - __raw_writel(reg, gpc_base + 0x14); -#endif + if (enable_ldo_mode != LDO_MODE_BYPASSED) { + /* Unmask the ANATOP brown out interrupt in the GPC. */ + reg = __raw_readl(gpc_base + 0x14); + reg &= ~0x80000000; + __raw_writel(reg, gpc_base + 0x14); + } pu_is_enabled = 1; if (get_clk) { if (!cpu_is_mx6sl()) { @@ -229,12 +230,12 @@ static int pu_disable(struct anatop_regulator *sreg) /* Wait for power down to complete. */ while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1) ; -#ifndef CONFIG_MX6_INTER_LDO_BYPASS - /* Mask the ANATOP brown out interrupt in the GPC. */ - reg = __raw_readl(gpc_base + 0x14); - reg |= 0x80000000; - __raw_writel(reg, gpc_base + 0x14); -#endif + if (enable_ldo_mode != LDO_MODE_BYPASSED) { + /* Mask the ANATOP brown out interrupt in the GPC. */ + reg = __raw_readl(gpc_base + 0x14); + reg |= 0x80000000; + __raw_writel(reg, gpc_base + 0x14); + } if (external_pureg) { /*disable extern PU regulator*/ diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S index f712700a8e68..e8642f8e1e66 100644 --- a/arch/arm/mach-mx6/mx6_suspend.S +++ b/arch/arm/mach-mx6/mx6_suspend.S @@ -1105,11 +1105,9 @@ set ddr iomux to low power mode ldr r1, =CCM_BASE_ADDR add r1, r1, #PERIPBASE_VIRT ldr r0, [r1] -#ifdef CONFIG_MX6_INTER_LDO_BYPASS ldr r1, =ANATOP_BASE_ADDR add r1, r1, #PERIPBASE_VIRT ldr r0, [r1] -#endif /* Do a DSB to drain the buffers. */ dsb @@ -1239,14 +1237,21 @@ rbc_loop: cmp r4, #0x0 bne rbc_loop -#ifdef CONFIG_MX6_INTER_LDO_BYPASS + /*if internal ldo(VDDARM) bypassed,analog bypass it for DSM(0x1e) and + *restore it when resume(0x1f). + */ ldr r1, =ANATOP_BASE_ADDR add r1, r1, #PERIPBASE_VIRT ldr r4, [r1, #0x140] + and r4, r4, #0x1f + cmp r4, #0x1f + bne ldo_check_done1 +ldo_analog_bypass: + ldr r4, [r1, #0x140] bic r4, r4, #0x1f orr r4, r4, #0x1e str r4, [r1, #0x140] -#endif +ldo_check_done1: /**************************************************************** execute a wfi instruction to let SOC go into stop mode. ****************************************************************/ @@ -1261,14 +1266,18 @@ execute a wfi instruction to let SOC go into stop mode. if go here, means there is a wakeup irq pending, we should resume system immediately. ****************************************************************/ -#ifdef CONFIG_MX6_INTER_LDO_BYPASS + /*restore it with 0x1f if use ldo bypass mode.*/ ldr r1, =ANATOP_BASE_ADDR add r1, r1, #PERIPBASE_VIRT ldr r3, [r1, #0x140] + and r3, r3, #0x1f + cmp r3, #0x1e + bne ldo_check_done2 +ldo_bypass_restore: + ldr r3, [r1, #0x140] orr r3, r3, #0x1f str r3, [r1, #0x140] -#endif - +ldo_check_done2: mov r0, r2 /* get suspend_iram_base */ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */ @@ -1387,19 +1396,23 @@ poll_dvfs_clear_1: mcr p15, 0, r1, c1, c0, 0 b out /* exit standby */ + .ltorg /**************************************************************** when SOC exit stop mode, arm core restart from here, currently are running with MMU off. ****************************************************************/ resume: - -#ifdef CONFIG_MX6_INTER_LDO_BYPASS + /*restore it with 0x1f if use ldo bypass mode.*/ ldr r1, =ANATOP_BASE_ADDR ldr r3, [r1, #0x140] + and r3, r3, #0x1f + cmp r3, #0x1e + bne ldo_check_done3 + ldr r3, [r1, #0x140] orr r3, r3, #0x1f str r3, [r1, #0x140] -#endif +ldo_check_done3: /* Invalidate L1 I-cache first */ mov r1, #0x0 mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache diff --git a/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c index 3987777d56ff..671233f3340b 100644 --- a/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c @@ -26,6 +26,7 @@ #include <linux/mfd/pfuze.h> #include <linux/io.h> #include <mach/irqs.h> +#include <mach/system.h> #include "crm_regs.h" #include "regs-anadig.h" #include "cpu_op-mx6.h" @@ -57,16 +58,17 @@ #define PFUZE100_SW1CCON_SPEED_M (0x3<<6) extern u32 arm_max_freq; +extern u32 enable_ldo_mode; static struct regulator_consumer_supply sw1a_consumers[] = { { - .supply = "P1V325_VDDARM_SW1AB", + .supply = "VDDCORE", } }; static struct regulator_consumer_supply sw1c_consumers[] = { { - .supply = "P1V325_VDDSOC_SW1C", + .supply = "VDDSOC", } }; @@ -397,8 +399,12 @@ static struct regulator_init_data vgen6_init = { static int pfuze100_init(struct mc_pfuze *pfuze) { int ret, i; - unsigned int reg; unsigned char value; + + /*use default mode(ldo bypass) if no param from cmdline*/ + if (enable_ldo_mode == LDO_MODE_DEFAULT) + enable_ldo_mode = LDO_MODE_ENABLED; + /*read Device ID*/ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value); if (ret) @@ -441,39 +447,59 @@ static int pfuze100_init(struct mc_pfuze *pfuze) } } + /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/ if (arm_max_freq == CPU_AT_1_2GHz) { - /*VDDARM_IN 1.475V*/ + /*VDDARM_IN 1.425*/ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, PFUZE100_SW1AVOL_VSEL_M, - 0x2f); + 0x2d); if (ret) goto err; - /*VDDSOC_IN 1.475V*/ + /*VDDSOC_IN 1.425V*/ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, PFUZE100_SW1CVOL_VSEL_M, - 0x2f); + 0x2d); + if (ret) + goto err; + enable_ldo_mode = LDO_MODE_ENABLED; + } else if (enable_ldo_mode == LDO_MODE_BYPASSED) { + /*decrease VDDARM_IN/VDDSOC_IN,since we will use ldo bypass mode*/ + /*VDDARM_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*VDDSOC_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, + PFUZE100_SW1ACON_SPEED_M, + PFUZE100_SW1ACON_SPEED_VAL); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; + } else if (enable_ldo_mode != LDO_MODE_BYPASSED) { + /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x2b); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x2b); if (ret) goto err; - /*set VDDSOC&VDDPU to 1.25V*/ - reg = __raw_readl(ANADIG_REG_CORE); - reg &= ~BM_ANADIG_REG_CORE_REG2_TRG; - reg |= BF_ANADIG_REG_CORE_REG2_TRG(0x16); - reg &= ~BM_ANADIG_REG_CORE_REG1_TRG; - reg |= BF_ANADIG_REG_CORE_REG1_TRG(0x16); - __raw_writel(reg, ANADIG_REG_CORE); - } - /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, - PFUZE100_SW1ACON_SPEED_M, - PFUZE100_SW1ACON_SPEED_VAL); - if (ret) - goto err; - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, - PFUZE100_SW1CCON_SPEED_M, - PFUZE100_SW1CCON_SPEED_VAL); - if (ret) - goto err; return 0; err: printk(KERN_ERR "pfuze100 init error!\n"); diff --git a/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c index 6b38bd000bc0..c18a01433c4f 100644 --- a/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c @@ -26,6 +26,7 @@ #include <linux/mfd/pfuze.h> #include <linux/io.h> #include <mach/irqs.h> +#include <mach/system.h> #include "crm_regs.h" #include "regs-anadig.h" #include "cpu_op-mx6.h" @@ -57,8 +58,8 @@ #define PFUZE100_SW1CCON_SPEED_M (0x3<<6) extern u32 arm_max_freq; +extern u32 enable_ldo_mode; -#ifdef CONFIG_MX6_INTER_LDO_BYPASS static struct regulator_consumer_supply sw1_consumers[] = { { .supply = "VDDCORE", @@ -69,7 +70,6 @@ static struct regulator_consumer_supply sw1c_consumers[] = { .supply = "VDDSOC", }, }; -#endif static struct regulator_consumer_supply sw2_consumers[] = { { @@ -152,10 +152,8 @@ static struct regulator_init_data sw1a_init = { }, }, -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), .consumer_supplies = sw1_consumers, -#endif }; static struct regulator_init_data sw1b_init = { @@ -186,10 +184,8 @@ static struct regulator_init_data sw1c_init = { .enabled = 1, }, }, -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers), .consumer_supplies = sw1c_consumers, -#endif }; static struct regulator_init_data sw2_init = { @@ -390,8 +386,10 @@ static struct regulator_init_data vgen6_init = { static int pfuze100_init(struct mc_pfuze *pfuze) { int ret, i; - unsigned int reg; unsigned char value; + /*use default mode(ldo bypass) if no param from cmdline*/ + if (enable_ldo_mode == LDO_MODE_DEFAULT) + enable_ldo_mode = LDO_MODE_BYPASSED; /*read Device ID*/ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value); if (ret) @@ -434,40 +432,59 @@ static int pfuze100_init(struct mc_pfuze *pfuze) } } - + /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/ if (arm_max_freq == CPU_AT_1_2GHz) { - /*VDDARM_IN 1.475V*/ + /*VDDARM_IN 1.425*/ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, PFUZE100_SW1AVOL_VSEL_M, - 0x2f); + 0x2d); if (ret) goto err; - /*VDDSOC_IN 1.475V*/ + /*VDDSOC_IN 1.425V*/ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, PFUZE100_SW1CVOL_VSEL_M, - 0x2f); + 0x2d); + if (ret) + goto err; + enable_ldo_mode = LDO_MODE_ENABLED; + } else if (enable_ldo_mode == LDO_MODE_BYPASSED) { + /*decrease VDDARM_IN/VDDSOC_IN,since we will use ldo bypass mode*/ + /*VDDARM_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*VDDSOC_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, + PFUZE100_SW1ACON_SPEED_M, + PFUZE100_SW1ACON_SPEED_VAL); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; + } else if (enable_ldo_mode != LDO_MODE_BYPASSED) { + /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x2b); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x2b); if (ret) goto err; - /*set VDDSOC&VDDPU to 1.25V*/ - reg = __raw_readl(ANADIG_REG_CORE); - reg &= ~BM_ANADIG_REG_CORE_REG2_TRG; - reg |= BF_ANADIG_REG_CORE_REG2_TRG(0x16); - reg &= ~BM_ANADIG_REG_CORE_REG1_TRG; - reg |= BF_ANADIG_REG_CORE_REG1_TRG(0x16); - __raw_writel(reg, ANADIG_REG_CORE); - } - /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, - PFUZE100_SW1ACON_SPEED_M, - PFUZE100_SW1ACON_SPEED_VAL); - if (ret) - goto err; - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, - PFUZE100_SW1CCON_SPEED_M, - PFUZE100_SW1CCON_SPEED_VAL); - if (ret) - goto err; return 0; err: printk(KERN_ERR "pfuze100 init error!\n"); diff --git a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c index 55a802b76b68..7cebb8f2fd3f 100644 --- a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c @@ -25,6 +25,8 @@ #include <linux/regulator/machine.h> #include <linux/mfd/pfuze.h> #include <mach/irqs.h> +#include <mach/system.h> +#include "cpu_op-mx6.h" /* * Convenience conversion. @@ -47,9 +49,14 @@ #define PFUZE100_SW1CCON 49 #define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */ #define PFUZE100_SW1CCON_SPEED_M (0x3<<6) +#define PFUZE100_SW1AVOL 32 +#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0) +#define PFUZE100_SW1CVOL 46 +#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0) +extern u32 enable_ldo_mode; +extern u32 arm_max_freq; -#ifdef CONFIG_MX6_INTER_LDO_BYPASS static struct regulator_consumer_supply sw1_consumers[] = { { .supply = "VDDCORE", @@ -60,7 +67,6 @@ static struct regulator_consumer_supply sw1c_consumers[] = { .supply = "VDDSOC", }, }; -#endif static struct regulator_consumer_supply sw2_consumers[] = { { @@ -143,10 +149,8 @@ static struct regulator_init_data sw1a_init = { .enabled = 1, }, }, -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), .consumer_supplies = sw1_consumers, -#endif }; static struct regulator_init_data sw1b_init = { @@ -177,10 +181,8 @@ static struct regulator_init_data sw1c_init = { .enabled = 1, }, }, - #ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers), .consumer_supplies = sw1c_consumers, - #endif }; static struct regulator_init_data sw2_init = { @@ -383,8 +385,11 @@ static struct regulator_init_data vgen6_init = { static int pfuze100_init(struct mc_pfuze *pfuze) { int ret, i; - unsigned int reg; unsigned char value; + + /*use default mode(ldo bypass) if no param from cmdline*/ + if (enable_ldo_mode == LDO_MODE_DEFAULT) + enable_ldo_mode = LDO_MODE_BYPASSED; /*read Device ID*/ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value); if (ret) @@ -427,17 +432,60 @@ static int pfuze100_init(struct mc_pfuze *pfuze) } } - /*set SW1AB/SW1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, - PFUZE100_SW1ACON_SPEED_M, - PFUZE100_SW1ACON_SPEED_VAL); - if (ret) - goto err; - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, - PFUZE100_SW1CCON_SPEED_M, - PFUZE100_SW1CCON_SPEED_VAL); - if (ret) - goto err; + /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/ + if (arm_max_freq == CPU_AT_1_2GHz) { + /*VDDARM_IN 1.47*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x2f); + if (ret) + goto err; + /*VDDSOC_IN 1.475V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x2f); + if (ret) + goto err; + enable_ldo_mode = LDO_MODE_ENABLED; + } else if (enable_ldo_mode == LDO_MODE_BYPASSED) { + /*decrease VDDARM_IN/VDDSOC_IN,since we will use dynamic ldo bypass + *mode or ldo bypass mode here.*/ + /*VDDARM_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*VDDSOC_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*set SW1AB/SW1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, + PFUZE100_SW1ACON_SPEED_M, + PFUZE100_SW1ACON_SPEED_VAL); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; + } else if (enable_ldo_mode != LDO_MODE_BYPASSED) { + /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x2b); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x2b); + if (ret) + goto err; + } return 0; err: printk(KERN_ERR "pfuze100 init error!\n"); diff --git a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c index bfd5fafc1d1b..14bd33ffe00c 100644 --- a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c @@ -25,6 +25,8 @@ #include <linux/regulator/machine.h> #include <linux/mfd/pfuze.h> #include <mach/irqs.h> +#include <mach/system.h> +#include "cpu_op-mx6.h" /* * Convenience conversion. @@ -47,8 +49,13 @@ #define PFUZE100_SW1CCON 49 #define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */ #define PFUZE100_SW1CCON_SPEED_M (0x3<<6) +#define PFUZE100_SW1AVOL 32 +#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0) +#define PFUZE100_SW1CVOL 46 +#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0) -#ifdef CONFIG_MX6_INTER_LDO_BYPASS +extern u32 enable_ldo_mode; +extern u32 arm_max_freq; static struct regulator_consumer_supply sw1_consumers[] = { { .supply = "VDDCORE", @@ -59,7 +66,6 @@ static struct regulator_consumer_supply sw1c_consumers[] = { .supply = "VDDSOC", }, }; -#endif static struct regulator_consumer_supply sw2_consumers[] = { { @@ -146,10 +152,8 @@ static struct regulator_init_data sw1a_init = { .enabled = 1, }, }, -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), .consumer_supplies = sw1_consumers, -#endif }; static struct regulator_init_data sw1b_init = { @@ -180,10 +184,8 @@ static struct regulator_init_data sw1c_init = { .enabled = 1, }, }, -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers), .consumer_supplies = sw1c_consumers, -#endif }; static struct regulator_init_data sw2_init = { @@ -388,8 +390,10 @@ static struct regulator_init_data vgen6_init = { static int pfuze100_init(struct mc_pfuze *pfuze) { int ret, i; - unsigned int reg; unsigned char value; + /*use default mode(ldo bypass) if no param from cmdline*/ + if (enable_ldo_mode == LDO_MODE_DEFAULT) + enable_ldo_mode = LDO_MODE_BYPASSED; /*read Device ID*/ ret = pfuze_reg_read(pfuze, PFUZE100_DEVICEID, &value); if (ret) @@ -432,18 +436,61 @@ static int pfuze100_init(struct mc_pfuze *pfuze) } } + /*use ldo active mode if use 1.2GHz,otherwise use ldo bypass mode*/ + if (arm_max_freq == CPU_AT_1_2GHz) { + /*VDDARM_IN 1.47*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x2f); + if (ret) + goto err; + /*VDDSOC_IN 1.475V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x2f); + if (ret) + goto err; + enable_ldo_mode = LDO_MODE_ENABLED; + } else if (enable_ldo_mode == LDO_MODE_BYPASSED) { + /*decrease VDDARM_IN/VDDSOC_IN,since we will use dynamic ldo bypass + *mode or ldo bypass mode here.*/ + /*VDDARM_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x28); + if (ret) + goto err; + /*VDDSOC_IN 1.3V*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x28); + if (ret) + goto err; - /*set SW1AB/SW1CDVSPEED as 25mV step each 4us,quick than 16us before.*/ - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, - PFUZE100_SW1ACON_SPEED_M, - PFUZE100_SW1ACON_SPEED_VAL); - if (ret) - goto err; - ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, - PFUZE100_SW1CCON_SPEED_M, - PFUZE100_SW1CCON_SPEED_VAL); - if (ret) - goto err; + /*set SW1AB/SW1CDVSPEED as 25mV step each 4us,quick than 16us before.*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, + PFUZE100_SW1ACON_SPEED_M, + PFUZE100_SW1ACON_SPEED_VAL); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; + } else if (enable_ldo_mode != LDO_MODE_BYPASSED) { + /*Increase VDDARM_IN/VDDSOC_IN to 1.375V in ldo active mode*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1AVOL, + PFUZE100_SW1AVOL_VSEL_M, + 0x2b); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CVOL, + PFUZE100_SW1CVOL_VSEL_M, + 0x2b); + if (ret) + goto err; + } return 0; err: printk(KERN_ERR "pfuze100 init error!\n"); diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c index a2a2798f93a0..998051d1f5b5 100644 --- a/arch/arm/mach-mx6/pm.c +++ b/arch/arm/mach-mx6/pm.c @@ -79,10 +79,6 @@ static struct regulator *vdd3p0_regulator; static struct pm_platform_data *pm_data; -#ifdef CONFIG_MX6_INTER_LDO_BYPASS -void mxc_cpufreq_suspend(void); -void mxc_cpufreq_resume(void); -#endif #if defined(CONFIG_CPU_FREQ) extern int set_cpu_freq(int wp); #endif @@ -436,23 +432,14 @@ static void mx6_suspend_finish(void) } } -#ifdef CONFIG_MX6_INTER_LDO_BYPASS static int mx6_suspend_begin(suspend_state_t state) { - mxc_cpufreq_suspend(); return 0; } -#endif /* * Called after devices are re-setup, but before processes are thawed. */ -static void mx6_suspend_end(void) -{ -#ifdef CONFIG_MX6_INTER_LDO_BYPASS - mxc_cpufreq_resume(); -#endif -} static int mx6_pm_valid(suspend_state_t state) { @@ -461,13 +448,10 @@ static int mx6_pm_valid(suspend_state_t state) struct platform_suspend_ops mx6_suspend_ops = { .valid = mx6_pm_valid, -#ifdef CONFIG_MX6_INTER_LDO_BYPASS .begin = mx6_suspend_begin, -#endif .prepare = mx6_suspend_prepare, .enter = mx6_suspend_enter, .finish = mx6_suspend_finish, - .end = mx6_suspend_end, }; static int __devinit mx6_pm_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-mx6/usb.h b/arch/arm/mach-mx6/usb.h index f796e7dad87c..b57104b03fff 100644 --- a/arch/arm/mach-mx6/usb.h +++ b/arch/arm/mach-mx6/usb.h @@ -27,8 +27,6 @@ extern int fsl_usb_host_init(struct platform_device *pdev); extern void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata); extern int gpio_usbotg_utmi_active(void); extern void gpio_usbotg_utmi_inactive(void); - -extern void __init mx6_usb_dr_init(void); extern bool usb_icbug_swfix_need(void); extern void __init mx6_usb_h2_init(void); extern void __init mx6_usb_h3_init(void); @@ -38,7 +36,8 @@ extern void mx6_set_host3_vbus_func(driver_vbus_func); extern void mx6_set_host2_vbus_func(driver_vbus_func); extern void mx6_set_host1_vbus_func(driver_vbus_func); extern void mx6_set_otghost_vbus_func(driver_vbus_func); -extern void mx6_set_usb_host1_vbus_func(driver_vbus_func *driver_vbus); +extern void mx6_get_otghost_vbus_func(driver_vbus_func *driver_vbus); +extern void mx6_get_host1_vbus_func(driver_vbus_func *driver_vbus); extern struct platform_device anatop_thermal_device; extern struct platform_device mxc_usbdr_otg_device; extern struct platform_device mxc_usbdr_udc_device; @@ -73,3 +72,13 @@ extern void __iomem *imx_otg_base; .iobase = soc ## _USB_ ## hs ## _BASE_ADDR, \ .irq = soc ## _INT_USB_ ## hs, \ } +#define imx_fsl_usb2_otg_data_entry_single(soc) \ + { \ + .iobase = soc ## _USB_OTG_BASE_ADDR, \ + .irq = soc ## _INT_USB_OTG, \ + } +#define imx_fsl_usb2_udc_data_entry_single(soc) \ + { \ + .iobase = soc ## _USB_OTG_BASE_ADDR, \ + .irq = soc ## _INT_USB_OTG, \ + } diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c index 7b79d98c7d5c..cf84cf2b1296 100644 --- a/arch/arm/mach-mx6/usb_dr.c +++ b/arch/arm/mach-mx6/usb_dr.c @@ -35,6 +35,8 @@ static void usbotg_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); extern bool usb_icbug_swfix_need(void); +static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, \ + bool enable); /* The usb_phy1_clk do not have enable/disable function at clock.c * and PLL output for usb1's phy should be always enabled. @@ -190,8 +192,8 @@ static int usbotg_init_ext(struct platform_device *pdev) return ret; } if (!otg_used) { - usbotg_internal_phy_clock_gate(true); usb_phy_enable(pdev->dev.platform_data); + enter_phy_lowpower_suspend(pdev->dev.platform_data, false); /*after the phy reset,can not read the readingvalue for id/vbus at * the register of otgsc ,cannot read at once ,need delay 3 ms */ @@ -204,16 +206,17 @@ static int usbotg_init_ext(struct platform_device *pdev) static void usbotg_uninit_ext(struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - - clk_disable(usb_phy1_clk); - clk_put(usb_phy1_clk); + otg_used--; + if (!otg_used) { + enter_phy_lowpower_suspend(pdev->dev.platform_data, true); + mdelay(3); - clk_disable(usb_oh3_clk); - clk_put(usb_oh3_clk); + clk_disable(usb_phy1_clk); + clk_put(usb_phy1_clk); - usbotg_uninit(pdata); - otg_used--; + clk_disable(usb_oh3_clk); + clk_put(usb_oh3_clk); + } } static void usbotg_clock_gate(bool on) @@ -236,10 +239,6 @@ static void dr_platform_phy_power_on(void) anatop_base_addr + HW_ANADIG_ANA_MISC0_SET); } -void mx6_set_otghost_vbus_func(driver_vbus_func driver_vbus) -{ - dr_utmi_config.platform_driver_vbus = driver_vbus; -} static void _dr_discharge_line(bool enable) { @@ -604,18 +603,45 @@ static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata) /* end of device related operation for DR port */ #endif /* CONFIG_USB_GADGET_ARC */ -void __init mx6_usb_dr_init(void) +static struct platform_device *pdev[3], *pdev_wakeup; +static driver_vbus_func mx6_set_usb_otg_vbus; +static int devnum; +static int __init mx6_usb_dr_init(void) { - struct platform_device *pdev, *pdev_wakeup; + int i = 0; void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); + struct imx_fsl_usb2_wakeup_data imx6q_fsl_otg_wakeup_data = + imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 0, OTG); + struct imx_mxc_ehci_data imx6q_mxc_ehci_otg_data = + imx_mxc_ehci_data_entry_single(MX6Q, 0, OTG); + struct imx_fsl_usb2_udc_data imx6q_fsl_usb2_udc_data = + imx_fsl_usb2_udc_data_entry_single(MX6Q); + struct imx_fsl_usb2_otg_data imx6q_fsl_usb2_otg_data = + imx_fsl_usb2_otg_data_entry_single(MX6Q); + + /* Some phy and power's special controls for otg + * 1. The external charger detector needs to be disabled + * or the signal at DP will be poor + * 2. The EN_USB_CLKS is always enabled. + * The PLL's power is controlled by usb and others who + * use pll3 too. + */ + __raw_writel(BM_ANADIG_USB1_CHRG_DETECT_EN_B \ + | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B, \ + anatop_base_addr + HW_ANADIG_USB1_CHRG_DETECT); + __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS, + anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET); + mx6_get_otghost_vbus_func(&mx6_set_usb_otg_vbus); + dr_utmi_config.platform_driver_vbus = mx6_set_usb_otg_vbus; #ifdef CONFIG_USB_OTG /* wake_up_enable is useless, just for usb_register_remote_wakeup execution*/ dr_utmi_config.wake_up_enable = _device_wakeup_enable; dr_utmi_config.operating_mode = FSL_USB2_DR_OTG; dr_utmi_config.wakeup_pdata = &dr_wakeup_config; - pdev = imx6q_add_fsl_usb2_otg(&dr_utmi_config); - dr_wakeup_config.usb_pdata[0] = pdev->dev.platform_data; + pdev[i] = imx6q_add_fsl_usb2_otg(&dr_utmi_config); + dr_wakeup_config.usb_pdata[i] = pdev[i]->dev.platform_data; + i++; #endif #ifdef CONFIG_USB_EHCI_ARC_OTG dr_utmi_config.operating_mode = DR_HOST_MODE; @@ -633,8 +659,9 @@ void __init mx6_usb_dr_init(void) dr_utmi_config.wakeup_pdata = &dr_wakeup_config; dr_utmi_config.wakeup_handler = host_wakeup_handler; dr_utmi_config.platform_phy_power_on = dr_platform_phy_power_on; - pdev = imx6q_add_fsl_ehci_otg(&dr_utmi_config); - dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data; + pdev[i] = imx6q_add_fsl_ehci_otg(&dr_utmi_config); + dr_wakeup_config.usb_pdata[i] = pdev[i]->dev.platform_data; + i++; #endif #ifdef CONFIG_USB_GADGET_ARC dr_utmi_config.operating_mode = DR_UDC_MODE; @@ -648,25 +675,38 @@ void __init mx6_usb_dr_init(void) dr_utmi_config.wakeup_handler = device_wakeup_handler; dr_utmi_config.charger_base_addr = anatop_base_addr; dr_utmi_config.platform_phy_power_on = dr_platform_phy_power_on; - pdev = imx6q_add_fsl_usb2_udc(&dr_utmi_config); - dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data; + pdev[i] = imx6q_add_fsl_usb2_udc(&dr_utmi_config); + dr_wakeup_config.usb_pdata[i] = pdev[i]->dev.platform_data; + i++; #endif + devnum = i; /* register wakeup device */ pdev_wakeup = imx6q_add_fsl_usb2_otg_wakeup(&dr_wakeup_config); - if (pdev != NULL) - ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata = + for (i = 0; i < devnum; i++) { + platform_device_add(pdev[i]); + ((struct fsl_usb2_platform_data *)(pdev[i]->dev.platform_data))->wakeup_pdata = (struct fsl_usb2_wakeup_platform_data *)(pdev_wakeup->dev.platform_data); + } + + return 0; +} +module_init(mx6_usb_dr_init); + +static void __exit mx6_usb_dr_exit(void) +{ + int i; + void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); + + for (i = 0; i < devnum; i++) + platform_device_del(pdev[devnum-i-1]); + platform_device_unregister(pdev_wakeup); + otg_used = 0; - /* Some phy and power's special controls for otg - * 1. The external charger detector needs to be disabled - * or the signal at DP will be poor - * 2. The EN_USB_CLKS is always enabled. - * The PLL's power is controlled by usb and others who - * use pll3 too. - */ - __raw_writel(BM_ANADIG_USB1_CHRG_DETECT_EN_B \ - | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B, \ - anatop_base_addr + HW_ANADIG_USB1_CHRG_DETECT); __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS, - anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET); + anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_CLR); + return ; } +module_exit(mx6_usb_dr_exit); + +MODULE_AUTHOR("Freescale Semiconductor"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c index f86a4f42b0bd..eb79bf35b16c 100644 --- a/arch/arm/mach-mx6/usb_h1.c +++ b/arch/arm/mach-mx6/usb_h1.c @@ -400,7 +400,7 @@ static int __init mx6_usb_h1_init(void) struct imx_mxc_ehci_data imx6sl_mxc_ehci_hs_data[] = { imx_mxc_ehci_data_entry_single(MX6SL, 1, HS1)}; - mx6_set_usb_host1_vbus_func(&mx6_set_usb_host1_vbus); + mx6_get_host1_vbus_func(&mx6_set_usb_host1_vbus); if (mx6_set_usb_host1_vbus) mx6_set_usb_host1_vbus(true); @@ -438,6 +438,7 @@ static int __init mx6_usb_h1_init(void) pdev_wakeup = imx6sl_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config); else pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config); + platform_device_add(pdev); ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata = (struct fsl_usb2_wakeup_platform_data *)(pdev_wakeup->dev.platform_data); return 0; diff --git a/arch/arm/mach-mx6/usb_h2.c b/arch/arm/mach-mx6/usb_h2.c index 37cad034d173..be092ab8c97c 100644 --- a/arch/arm/mach-mx6/usb_h2.c +++ b/arch/arm/mach-mx6/usb_h2.c @@ -237,6 +237,7 @@ void __init mx6_usb_h2_init(void) pdev_wakeup = imx6sl_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config); else pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config); + platform_device_add(pdev); ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata = pdev_wakeup->dev.platform_data; /* Some phy and power's special controls for host2 diff --git a/arch/arm/mach-mx6/usb_h3.c b/arch/arm/mach-mx6/usb_h3.c index 820ecd903d25..e25c01621b52 100644 --- a/arch/arm/mach-mx6/usb_h3.c +++ b/arch/arm/mach-mx6/usb_h3.c @@ -227,6 +227,7 @@ void __init mx6_usb_h3_init(void) pdev = imx6q_add_fsl_ehci_hs(3, &usbh3_config); usbh3_wakeup_config.usb_pdata[0] = pdev->dev.platform_data; pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(3, &usbh3_wakeup_config); + platform_device_add(pdev); ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata = pdev_wakeup->dev.platform_data; diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index c43d8307bb2d..feacdf71ef3b 100755 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -23,6 +23,7 @@ #include <linux/regulator/consumer.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/suspend.h> #include <asm/smp_plat.h> #include <asm/cpu.h> @@ -32,15 +33,6 @@ #define CLK32_FREQ 32768 #define NANOSECOND (1000 * 1000 * 1000) -/*If using cpu internal ldo bypass,we need config pmic by I2C in suspend -interface, but cpufreq driver as sys_dev is more later to suspend than I2C -driver, so we should implement another I2C operate function which isolated -with kernel I2C driver, these code is copied from u-boot*/ -#ifdef CONFIG_MX6_INTER_LDO_BYPASS -/*0:normal; 1: in the middle of suspend or resume; 2: suspended*/ -static int cpu_freq_suspend_in; -static struct mutex set_cpufreq_lock; -#endif static int cpu_freq_khz_min; static int cpu_freq_khz_max; @@ -56,6 +48,8 @@ static u32 pre_suspend_rate; #ifdef CONFIG_ARCH_MX5 int cpufreq_suspended; #endif +static bool cpufreq_suspend; +static struct mutex set_cpufreq_lock; extern struct regulator *cpu_regulator; extern struct regulator *soc_regulator; @@ -63,14 +57,16 @@ extern struct regulator *pu_regulator; extern int dvfs_core_is_active; extern struct cpu_op *(*get_cpu_op)(int *op); extern void bus_freq_update(struct clk *clk, bool flag); +extern void mx6_arm_regulator_bypass(void); +extern void mx6_soc_pu_regulator_bypass(void); int set_cpu_freq(int freq) { int i, ret = 0; int org_cpu_rate; - int gp_volt = 0; - int soc_volt = 0; - int pu_volt = 0; + int gp_volt = 0, org_gp_volt = 0; + int soc_volt = 0, org_soc_volt = 0; + int pu_volt = 0, org_pu_volt = 0; org_cpu_rate = clk_get_rate(cpu_clk); if (org_cpu_rate == freq) @@ -82,15 +78,14 @@ int set_cpu_freq(int freq) soc_volt = cpu_op_tbl[i].soc_voltage; pu_volt = cpu_op_tbl[i].pu_voltage; } + if (org_cpu_rate == cpu_op_tbl[i].cpu_rate) { + org_gp_volt = cpu_op_tbl[i].cpu_voltage; + org_soc_volt = cpu_op_tbl[i].soc_voltage; + org_pu_volt = cpu_op_tbl[i].pu_voltage; + } } - if (gp_volt == 0) return ret; -#ifdef CONFIG_MX6_INTER_LDO_BYPASS - /*Do not change cpufreq if system enter suspend flow*/ - if (cpu_freq_suspend_in == 2) - return -1; -#endif /*Set the voltage for the GP domain. */ if (freq > org_cpu_rate) { /* Check if the bus freq needs to be increased first */ @@ -100,9 +95,9 @@ int set_cpu_freq(int freq) ret = regulator_set_voltage(soc_regulator, soc_volt, soc_volt); if (ret < 0) { - printk(KERN_DEBUG + printk(KERN_ERR "COULD NOT SET SOC VOLTAGE!!!!\n"); - return ret; + goto err1; } } /*if pu_regulator is enabled, it will be tracked with VDDARM*/ @@ -111,39 +106,39 @@ int set_cpu_freq(int freq) ret = regulator_set_voltage(pu_regulator, pu_volt, pu_volt); if (ret < 0) { - printk(KERN_DEBUG + printk(KERN_ERR "COULD NOT SET PU VOLTAGE!!!!\n"); - return ret; + goto err2; } } ret = regulator_set_voltage(cpu_regulator, gp_volt, gp_volt); if (ret < 0) { - printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n"); - return ret; + printk(KERN_ERR "COULD NOT SET GP VOLTAGE!!!!\n"); + goto err3; } udelay(50); } ret = clk_set_rate(cpu_clk, freq); if (ret != 0) { - printk(KERN_DEBUG "cannot set CPU clock rate\n"); - return ret; + printk(KERN_ERR "cannot set CPU clock rate\n"); + goto err4; } if (freq < org_cpu_rate) { ret = regulator_set_voltage(cpu_regulator, gp_volt, gp_volt); if (ret < 0) { - printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n"); - return ret; + printk(KERN_ERR "COULD NOT SET GP VOLTAGE!!!!\n"); + goto err5; } if (!IS_ERR(soc_regulator)) { ret = regulator_set_voltage(soc_regulator, soc_volt, soc_volt); if (ret < 0) { - printk(KERN_DEBUG + printk(KERN_ERR "COULD NOT SET SOC VOLTAGE BACK!!!!\n"); - return ret; + goto err6; } } /*if pu_regulator is enabled, it will be tracked with VDDARM*/ @@ -152,9 +147,9 @@ int set_cpu_freq(int freq) ret = regulator_set_voltage(pu_regulator, pu_volt, pu_volt); if (ret < 0) { - printk(KERN_DEBUG + printk(KERN_ERR "COULD NOT SET PU VOLTAGE!!!!\n"); - return ret; + goto err7; } } /* Check if the bus freq can be decreased.*/ @@ -162,6 +157,56 @@ int set_cpu_freq(int freq) } return ret; + /*Restore back if any regulator or clock rate set fail.*/ +err7: + ret = regulator_set_voltage(soc_regulator, org_soc_volt, + org_soc_volt); + if (ret < 0) { + printk(KERN_ERR "COULD NOT RESTORE SOC VOLTAGE!!!!\n"); + goto err7; + } + +err6: + ret = regulator_set_voltage(cpu_regulator, org_gp_volt, org_gp_volt); + if (ret < 0) { + printk(KERN_ERR "COULD NOT RESTORE GP VOLTAGE!!!!\n"); + goto err6; + } + +err5: + ret = clk_set_rate(cpu_clk, org_cpu_rate); + if (ret != 0) { + printk(KERN_ERR "cannot restore CPU clock rate\n"); + goto err5; + } + return -1; + +err4: + ret = regulator_set_voltage(cpu_regulator, org_gp_volt, org_gp_volt); + if (ret < 0) { + printk(KERN_ERR "COULD NOT RESTORE GP VOLTAGE!!!!\n"); + goto err4; + } + +err3: + if (!IS_ERR(pu_regulator) && + regulator_is_enabled(pu_regulator)) { + ret = regulator_set_voltage(pu_regulator, org_pu_volt, org_pu_volt); + if (ret < 0) { + printk(KERN_ERR "COULD NOT RESTORE PU VOLTAGE!!!!\n"); + goto err3; + } + } +err2: + ret = regulator_set_voltage(soc_regulator, org_soc_volt, + org_soc_volt); + if (ret < 0) { + printk(KERN_ERR "COULD NOT RESTORE SOC VOLTAGE!!!!\n"); + goto err2; + } +err1: + return -1; + } static int mxc_verify_speed(struct cpufreq_policy *policy) @@ -211,6 +256,11 @@ static int mxc_set_target(struct cpufreq_policy *policy, return ret; } + mutex_lock(&set_cpufreq_lock); + if (cpufreq_suspend) { + mutex_unlock(&set_cpufreq_lock); + return ret; + } cpufreq_frequency_table_target(policy, imx_freq_table, target_freq, relation, &index); freq_Hz = imx_freq_table[index].frequency * 1000; @@ -219,18 +269,23 @@ static int mxc_set_target(struct cpufreq_policy *policy, freqs.new = freq_Hz / 1000; freqs.cpu = policy->cpu; freqs.flags = 0; - for (i = 0; i < num_cpus; i++) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } - #ifdef CONFIG_MX6_INTER_LDO_BYPASS - mutex_lock(&set_cpufreq_lock); - ret = set_cpu_freq(freq_Hz); - mutex_unlock(&set_cpufreq_lock); - #else ret = set_cpu_freq(freq_Hz); - #endif + if (ret) { + /*restore cpufreq and tell cpufreq core if set fail*/ + freqs.old = clk_get_rate(cpu_clk) / 1000; + freqs.new = freqs.old; + freqs.cpu = policy->cpu; + freqs.flags = 0; + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + goto Set_finish; + } #ifdef CONFIG_SMP /* Loops per jiffy is not updated by the CPUFREQ driver for SMP systems. * So update it for all CPUs. @@ -244,71 +299,16 @@ static int mxc_set_target(struct cpufreq_policy *policy, * as all CPUs are running at same freq */ loops_per_jiffy = per_cpu(cpu_data, 0).loops_per_jiffy; #endif +Set_finish: for (i = 0; i < num_cpus; i++) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } - - return ret; -} -#ifdef CONFIG_MX6_INTER_LDO_BYPASS -void mxc_cpufreq_suspend(void) -{ - mutex_lock(&set_cpufreq_lock); - pre_suspend_rate = clk_get_rate(cpu_clk); - /*set flag and raise up cpu frequency if needed*/ - cpu_freq_suspend_in = 1; - if (pre_suspend_rate != (imx_freq_table[0].frequency * 1000)) { - set_cpu_freq(imx_freq_table[0].frequency * 1000); - loops_per_jiffy = cpufreq_scale(loops_per_jiffy, - pre_suspend_rate / 1000, imx_freq_table[0].frequency); - } - cpu_freq_suspend_in = 2; mutex_unlock(&set_cpufreq_lock); + return ret; } -void mxc_cpufreq_resume(void) -{ - mutex_lock(&set_cpufreq_lock); - cpu_freq_suspend_in = 1; - if (clk_get_rate(cpu_clk) != pre_suspend_rate) { - set_cpu_freq(pre_suspend_rate); - loops_per_jiffy = cpufreq_scale(loops_per_jiffy, - imx_freq_table[0].frequency, pre_suspend_rate / 1000); - } - cpu_freq_suspend_in = 0; - mutex_unlock(&set_cpufreq_lock); -} - - -#else -static int mxc_cpufreq_suspend(struct cpufreq_policy *policy) -{ -#ifndef CONFIG_ARCH_MX5 - pre_suspend_rate = clk_get_rate(cpu_clk); - if (pre_suspend_rate != (imx_freq_table[0].frequency * 1000)) { - set_cpu_freq(imx_freq_table[0].frequency * 1000); - loops_per_jiffy = cpufreq_scale(loops_per_jiffy, - pre_suspend_rate / 1000, imx_freq_table[0].frequency); - } -#endif - return 0; -} - -static int mxc_cpufreq_resume(struct cpufreq_policy *policy) -{ -#ifndef CONFIG_ARCH_MX5 - if (clk_get_rate(cpu_clk) != pre_suspend_rate) { - set_cpu_freq(pre_suspend_rate); - loops_per_jiffy = cpufreq_scale(loops_per_jiffy, - imx_freq_table[0].frequency, pre_suspend_rate / 1000); - } -#endif - return 0; -} -#endif - static int __devinit mxc_cpufreq_init(struct cpufreq_policy *policy) { int ret; @@ -411,21 +411,118 @@ static struct cpufreq_driver mxc_driver = { .get = mxc_get_speed, .init = mxc_cpufreq_init, .exit = mxc_cpufreq_exit, -#ifndef CONFIG_MX6_INTER_LDO_BYPASS - .suspend = mxc_cpufreq_suspend, - .resume = mxc_cpufreq_resume, -#endif .name = "imx", .attr = imx_cpufreq_attr, }; +static int cpufreq_pm_notify(struct notifier_block *nb, unsigned long event, + void *dummy) +{ + unsigned int i; + int num_cpus; + int ret; + struct cpufreq_freqs freqs; + + num_cpus = num_possible_cpus(); + mutex_lock(&set_cpufreq_lock); + if (event == PM_SUSPEND_PREPARE) { + pre_suspend_rate = clk_get_rate(cpu_clk); + if (pre_suspend_rate != (imx_freq_table[0].frequency * 1000)) { + /*notify cpufreq core will raise up cpufreq to highest*/ + freqs.old = pre_suspend_rate / 1000; + freqs.new = imx_freq_table[0].frequency; + freqs.flags = 0; + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + ret = set_cpu_freq(imx_freq_table[0].frequency * 1000); + /*restore cpufreq and tell cpufreq core if set fail*/ + if (ret) { + freqs.old = clk_get_rate(cpu_clk)/1000; + freqs.new = freqs.old; + freqs.flags = 0; + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + goto Notify_finish;/*if update freq error,return*/ + } +#ifdef CONFIG_SMP + for_each_possible_cpu(i) + per_cpu(cpu_data, i).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, + pre_suspend_rate / 1000, imx_freq_table[0].frequency); + loops_per_jiffy = per_cpu(cpu_data, 0).loops_per_jiffy; +#else + loops_per_jiffy = cpufreq_scale(loops_per_jiffy, + pre_suspend_rate / 1000, imx_freq_table[0].frequency); +#endif + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + } + cpufreq_suspend = true; + } else if (event == PM_POST_SUSPEND) { + if (clk_get_rate(cpu_clk) != pre_suspend_rate) { + /*notify cpufreq core will restore rate before suspend*/ + freqs.old = imx_freq_table[0].frequency; + freqs.new = pre_suspend_rate / 1000; + freqs.flags = 0; + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + ret = set_cpu_freq(pre_suspend_rate); + /*restore cpufreq and tell cpufreq core if set fail*/ + if (ret) { + freqs.old = clk_get_rate(cpu_clk)/1000; + freqs.new = freqs.old; + freqs.flags = 0; + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + goto Notify_finish;/*if update freq error,return*/ + } +#ifdef CONFIG_SMP + for_each_possible_cpu(i) + per_cpu(cpu_data, i).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, + imx_freq_table[0].frequency, pre_suspend_rate / 1000); + loops_per_jiffy = per_cpu(cpu_data, 0).loops_per_jiffy; +#else + loops_per_jiffy = cpufreq_scale(loops_per_jiffy, + imx_freq_table[0].frequency, pre_suspend_rate / 1000); +#endif + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + } + cpufreq_suspend = false; + } + mutex_unlock(&set_cpufreq_lock); + return NOTIFY_OK; + +Notify_finish: + for (i = 0; i < num_cpus; i++) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + mutex_unlock(&set_cpufreq_lock); + return NOTIFY_OK; +} +static struct notifier_block imx_cpufreq_pm_notifier = { + .notifier_call = cpufreq_pm_notify, +}; extern void mx6_cpu_regulator_init(void); static int __init mxc_cpufreq_driver_init(void) { - #ifdef CONFIG_MX6_INTER_LDO_BYPASS mx6_cpu_regulator_init(); mutex_init(&set_cpufreq_lock); - #endif + register_pm_notifier(&imx_cpufreq_pm_notifier); return cpufreq_register_driver(&mxc_driver); } diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-otg.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-otg.c index f32593c27ccd..da7b22140293 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-otg.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-otg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * Based on Uwe Kleine-Koenig's platform-fsl-usb2-udc.c * Copyright (C) 2010 Pengutronix @@ -39,7 +39,51 @@ struct platform_device *__init imx_add_fsl_usb2_otg( .flags = IORESOURCE_IRQ, }, }; - return imx_add_platform_device_dmamask("fsl-usb2-otg", -1, - res, ARRAY_SIZE(res), - pdata, sizeof(*pdata), DMA_BIT_MASK(32)); + + int ret = -ENOMEM; + const char *name = "fsl-usb2-otg"; + int id = -1; + unsigned int num_resources = ARRAY_SIZE(res); + size_t size_data = sizeof(*pdata); + u64 dmamask = DMA_BIT_MASK(32); + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + ret = platform_device_add_resources(pdev, res, num_resources); + if (ret) + goto err; + + if (data) { + ret = platform_device_add_data(pdev, pdata, size_data); + if (ret) + goto err; + } + + return pdev; +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); } +EXPORT_SYMBOL(imx_add_fsl_usb2_otg); 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 34e522a06247..4c54e1109f9d 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * Copyright (C) 2010 Pengutronix * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> @@ -58,7 +58,52 @@ struct platform_device *__init imx_add_fsl_usb2_udc( .flags = IORESOURCE_IRQ, }, }; - return imx_add_platform_device_dmamask("fsl-usb2-udc", -1, - res, ARRAY_SIZE(res), - pdata, sizeof(*pdata), DMA_BIT_MASK(32)); + + int ret = -ENOMEM; + const char *name = "fsl-usb2-udc"; + int id = -1; + unsigned int num_resources = ARRAY_SIZE(res); + size_t size_data = sizeof(*pdata); + u64 dmamask = DMA_BIT_MASK(32); + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + ret = platform_device_add_resources(pdev, res, num_resources); + if (ret) + goto err; + + if (data) { + ret = platform_device_add_data(pdev, pdata, size_data); + if (ret) + goto err; + } + + return pdev; + +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); } +EXPORT_SYMBOL(imx_add_fsl_usb2_udc); diff --git a/arch/arm/plat-mxc/devices/platform-imx_vpu.c b/arch/arm/plat-mxc/devices/platform-imx_vpu.c index c36439138778..83faed6e7b6a 100755 --- a/arch/arm/plat-mxc/devices/platform-imx_vpu.c +++ b/arch/arm/plat-mxc/devices/platform-imx_vpu.c @@ -167,6 +167,15 @@ struct platform_device *__init imx_add_vpu( pdata.iram_enable = data->iram_enable; pdata.iram_size = data->iram_size; +#ifdef CONFIG_SOC_IMX6Q + if (cpu_is_mx6dl() || cpu_is_mx6q()) { + #define HW_OCOTP_CFGn(n) (0x00000410 + (n) * 0x10) + unsigned int vpu_disable; + vpu_disable = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_CFGn(3)); + if (vpu_disable & 0x00008000) + return ERR_PTR(-ENODEV); + } +#endif if (cpu_is_mx6dl()) pdata.iram_enable = false; diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c index 2b9cdff2ff97..984fa296951f 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c @@ -101,8 +101,52 @@ struct platform_device *__init imx_add_fsl_ehci( .flags = IORESOURCE_IRQ, }, }; - return imx_add_platform_device_dmamask("fsl-ehci", data->id, - res, ARRAY_SIZE(res), - pdata, sizeof(*pdata), DMA_BIT_MASK(32)); + int ret = -ENOMEM; + const char *name = "fsl-ehci"; + int id = data->id; + unsigned int num_resources = ARRAY_SIZE(res); + size_t size_data = sizeof(*pdata); + u64 dmamask = DMA_BIT_MASK(32); + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + ret = platform_device_add_resources(pdev, res, num_resources); + if (ret) + goto err; + + if (data) { + ret = platform_device_add_data(pdev, pdata, size_data); + if (ret) + goto err; + } + + return pdev; + +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); + } EXPORT_SYMBOL(imx_add_fsl_ehci); diff --git a/arch/arm/plat-mxc/devices/platform-mxc_mlb.c b/arch/arm/plat-mxc/devices/platform-mxc_mlb.c index a1ede415ed81..661595fd5f38 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc_mlb.c +++ b/arch/arm/plat-mxc/devices/platform-mxc_mlb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-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 @@ -40,9 +40,12 @@ struct platform_device *__init imx_add_mlb( #endif /* ifdef CONFIG_SOC_IMX53 */ #ifdef CONFIG_SOC_IMX6Q + struct platform_device *__init imx_add_mlb( const struct mxc_mlb_platform_data *pdata) { +#define HW_OCOTP_CFGn(n) (0x00000410 + (n) * 0x10) + unsigned int mlb_disable = 0; struct resource res[] = { { .start = MLB_BASE_ADDR, @@ -65,6 +68,10 @@ struct platform_device *__init imx_add_mlb( .flags = IORESOURCE_IRQ, }, }; + + mlb_disable = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_CFGn(2)); + if (mlb_disable & 0x04000000) + return ERR_PTR(-ENODEV); return imx_add_platform_device("mxc_mlb150", 0, res, ARRAY_SIZE(res), pdata, sizeof(*pdata)); } diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h index df528bc4f028..e2740ffce210 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h @@ -58,6 +58,9 @@ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_HYS) +#define MX6DL_ENET_REF_CLK_PAD_CTRL (PAD_CTL_PUE | \ + PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) #define MX6DL_I2C_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ @@ -2257,7 +2260,7 @@ IOMUX_PAD(0x05BC, 0x01EC, 6, 0x0000, 0, NO_PAD_CTRL) #define MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK \ - IOMUX_PAD(0x05C0, 0x01F0, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) + IOMUX_PAD(0x05C0, 0x01F0, 1, 0x0000, 0, MX6DL_ENET_REF_CLK_PAD_CTRL) #define MX6DL_PAD_ENET_REF_CLK__ESAI1_FSR \ IOMUX_PAD(0x05C0, 0x01F0, 2, 0x082C, 0, NO_PAD_CTRL) #define MX6DL_PAD_ENET_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 \ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h index fe107cffca7b..cdff32032825 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h @@ -57,6 +57,10 @@ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_HYS) +#define MX6Q_ENET_REF_CLK_PAD_CTRL (PAD_CTL_PUE | \ + PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) + #define MX6Q_GPIO_16_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_HYS) @@ -5216,7 +5220,7 @@ #define MX6Q_PAD_ENET_REF_CLK__RESERVED_RESERVED \ (_MX6Q_PAD_ENET_REF_CLK__RESERVED_RESERVED | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK \ - (_MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(MX6Q_ENET_PAD_CTRL)) + (_MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(MX6Q_ENET_REF_CLK_PAD_CTRL)) #define MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR \ (_MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR | MUX_PAD_CTRL(MX6Q_ESAI_PAD_CTRL)) #define MX6Q_PAD_ENET_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 \ diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h index c1dfe258a477..649a97ceca7f 100755 --- a/arch/arm/plat-mxc/include/mach/system.h +++ b/arch/arm/plat-mxc/include/mach/system.h @@ -20,6 +20,9 @@ #include <mach/hardware.h> #include <mach/common.h> +#define LDO_MODE_DEFAULT 0 +#define LDO_MODE_BYPASSED 1 +#define LDO_MODE_ENABLED 2 extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode); void arch_idle(void); diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c index cc9a7e63565f..650391c7d2dd 100644 --- a/arch/arm/plat-mxc/system.c +++ b/arch/arm/plat-mxc/system.c @@ -33,6 +33,7 @@ #include <asm/mach-types.h> static void __iomem *wdog_base; +extern u32 enable_ldo_mode; extern int dvfs_core_is_active; extern void stop_dvfs(void); @@ -58,11 +59,14 @@ void arch_reset(char mode, const char *cmd) #ifdef CONFIG_ARCH_MX6 /* wait for reset to assert... */ - #ifdef CONFIG_MX6_INTER_LDO_BYPASS - wcr_enable = 0x14; /*reset system by extern pmic*/ - #else - wcr_enable = (1 << 2); - #endif + if (enable_ldo_mode == LDO_MODE_BYPASSED) { + /*On Sabresd board use WDOG2 to reset external PMIC, so here do + * more WDOG2 reset.*/ + wcr_enable = 0x14; + __raw_writew(wcr_enable, IO_ADDRESS(MX6Q_WDOG2_BASE_ADDR)); + __raw_writew(wcr_enable, IO_ADDRESS(MX6Q_WDOG2_BASE_ADDR)); + } else + wcr_enable = (1 << 2); __raw_writew(wcr_enable, wdog_base); /* errata TKT039676, SRS bit may be missed when SRC sample it, need to write the wdog controller diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c index 97d963a54a54..a327d3016619 100755 --- a/arch/arm/plat-mxc/usb_common.c +++ b/arch/arm/plat-mxc/usb_common.c @@ -52,7 +52,8 @@ typedef void (*driver_vbus_func)(bool); void __iomem *imx_otg_base; -static driver_vbus_func s_driver_vbus; +static driver_vbus_func s_h1_driver_vbus; +static driver_vbus_func s_otg_driver_vbus; EXPORT_SYMBOL(imx_otg_base); @@ -73,14 +74,26 @@ EXPORT_SYMBOL(usb_icbug_swfix_need); void mx6_set_host1_vbus_func(driver_vbus_func driver_vbus) { - s_driver_vbus = driver_vbus; + s_h1_driver_vbus = driver_vbus; } -void mx6_set_usb_host1_vbus_func(driver_vbus_func *driver_vbus) +void mx6_get_host1_vbus_func(driver_vbus_func *driver_vbus) { - *driver_vbus = s_driver_vbus; + *driver_vbus = s_h1_driver_vbus; } -EXPORT_SYMBOL(mx6_set_usb_host1_vbus_func); +EXPORT_SYMBOL(mx6_get_host1_vbus_func); + +void mx6_set_otghost_vbus_func(driver_vbus_func driver_vbus) +{ + s_otg_driver_vbus = driver_vbus; +} + +void mx6_get_otghost_vbus_func(driver_vbus_func *driver_vbus) +{ + *driver_vbus = s_otg_driver_vbus; +} +EXPORT_SYMBOL(mx6_get_otghost_vbus_func); + enum fsl_usb2_modes get_usb_mode(struct fsl_usb2_platform_data *pdata) |