summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx6
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx6')
-rw-r--r--arch/arm/mach-mx6/Kconfig2
-rw-r--r--arch/arm/mach-mx6/Makefile2
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.c36
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.h4
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_arm2.c2
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_common.h46
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_evk.c263
-rw-r--r--arch/arm/mach-mx6/board-mx6solo_sabreauto.h4
-rw-r--r--arch/arm/mach-mx6/bus_freq.c6
-rw-r--r--arch/arm/mach-mx6/clock.c3
-rwxr-xr-xarch/arm/mach-mx6/clock_mx6sl.c10
-rw-r--r--arch/arm/mach-mx6/cpu.c8
-rw-r--r--arch/arm/mach-mx6/cpu_op-mx6.c12
-rw-r--r--arch/arm/mach-mx6/cpu_regulator-mx6.c18
-rw-r--r--arch/arm/mach-mx6/devices-imx6q.h12
-rw-r--r--arch/arm/mach-mx6/etm.c110
-rw-r--r--arch/arm/mach-mx6/mx6_anatop_regulator.c140
-rw-r--r--arch/arm/mach-mx6/mx6_suspend.S547
-rw-r--r--arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c6
-rw-r--r--arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c8
-rw-r--r--arch/arm/mach-mx6/mx6sl_wfi.S163
-rw-r--r--arch/arm/mach-mx6/pm.c133
-rw-r--r--arch/arm/mach-mx6/system.c128
-rw-r--r--arch/arm/mach-mx6/usb.h3
-rw-r--r--arch/arm/mach-mx6/usb_dr.c27
-rw-r--r--arch/arm/mach-mx6/usb_h1.c21
26 files changed, 1368 insertions, 346 deletions
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig
index d50f1a795a09..97262dced063 100644
--- a/arch/arm/mach-mx6/Kconfig
+++ b/arch/arm/mach-mx6/Kconfig
@@ -7,6 +7,7 @@ config ARCH_MX6Q
select ARCH_MXC_AUDMUX_V2
select ARM_GIC
select ARCH_HAS_CPUFREQ
+ select OC_ETM
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_FEC
select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
@@ -136,6 +137,7 @@ config MACH_MX6SL_EVK
select IMX_HAVE_PLATFORM_IMX_EPDC
select IMX_HAVE_PLATFORM_IMX_SPDC
select IMX_HAVE_PLATFORM_IMX_PXP
+ select IMX_HAVE_PLATFORM_IMX_FSL_CSI
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_IMX_DCP
select IMX_HAVE_PLATFORM_RANDOM_RNGC
diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile
index 49b5f86a6920..05dc62dac468 100644
--- a/arch/arm/mach-mx6/Makefile
+++ b/arch/arm/mach-mx6/Makefile
@@ -5,7 +5,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\
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
+mx6_mmdc.o mx6_ddr_freq.o mx6sl_ddr.o mx6sl_wfi.o etm.o
obj-$(CONFIG_ARCH_MX6) += clock.o mx6_suspend.o clock_mx6sl.o
obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
index 61d595cddb79..a15daef0c4bb 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
@@ -103,7 +103,6 @@
#define SABREAUTO_DISP0_PWR IMX_GPIO_NR(3, 24)
#define SABREAUTO_DISP0_I2C_EN IMX_GPIO_NR(3, 28)
#define SABREAUTO_DISP0_DET_INT IMX_GPIO_NR(3, 31)
-#define SABREAUTO_CSI0_RST IMX_GPIO_NR(4, 5)
#define SABREAUTO_DISP0_RESET IMX_GPIO_NR(5, 0)
#define SABREAUTO_I2C3_STEER IMX_GPIO_NR(5, 4)
#define SABREAUTO_WEIM_NOR_WDOG1 IMX_GPIO_NR(4, 29)
@@ -111,7 +110,6 @@
#define SABREAUTO_PMIC_INT IMX_GPIO_NR(5, 16)
#define SABREAUTO_ALS_INT IMX_GPIO_NR(5, 17)
#define SABREAUTO_SD1_WP IMX_GPIO_NR(5, 20)
-#define SABREAUTO_CSI0_PWN IMX_GPIO_NR(5, 23)
#define SABREAUTO_USB_HOST1_OC IMX_GPIO_NR(5, 0)
#define SABREAUTO_SD3_CD IMX_GPIO_NR(6, 15)
@@ -603,18 +601,6 @@ static struct pca953x_platform_data max7310_u43_platdata = {
.setup = max7310_u43_setup,
};
-static struct fsl_mxc_camera_platform_data camera_data = {
- .analog_regulator = "DA9052_LDO7",
- .core_regulator = "DA9052_LDO9",
- .mclk = 24000000,
- .csi = 0,
-};
-
-static struct fsl_mxc_camera_platform_data ov5640_mipi_data = {
- .mclk = 24000000,
- .csi = 0,
-};
-
static void adv7180_pwdn(int pwdn)
{
int status = -1;
@@ -672,10 +658,6 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
I2C_BOARD_INFO("adv7180", 0x21),
.platform_data = (void *)&adv7180_data,
}, {
- I2C_BOARD_INFO("ov3640", 0x3c),
- .platform_data = (void *)&camera_data,
- },
- {
I2C_BOARD_INFO("isl29023", 0x44),
.irq = gpio_to_irq(SABREAUTO_ALS_INT),
.platform_data = &ls_data,
@@ -693,17 +675,13 @@ static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
}, {
I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
}, {
- I2C_BOARD_INFO("ov5640_mipi", 0x3c),
- .platform_data = (void *)&ov5640_mipi_data,
- }, {
I2C_BOARD_INFO("cs42888", 0x48),
.platform_data = (void *)&cs42888_data,
- },
- {
+ }, {
I2C_BOARD_INFO("si4763_i2c", 0x63),
},
-
};
+
struct platform_device mxc_si4763_audio_device = {
.name = "imx-tuner-si4763",
.id = 0,
@@ -1316,16 +1294,6 @@ early_param("can0", early_enable_can0);
static inline void __init mx6q_csi0_io_init(void)
{
- /* Camera reset */
- gpio_request(SABREAUTO_CSI0_RST, "cam-reset");
- gpio_direction_output(SABREAUTO_CSI0_RST, 1);
-
- /* Camera power down */
- gpio_request(SABREAUTO_CSI0_PWN, "cam-pwdn");
- gpio_direction_output(SABREAUTO_CSI0_PWN, 1);
- msleep(1);
- gpio_set_value(SABREAUTO_CSI0_PWN, 0);
-
if (cpu_is_mx6q())
mxc_iomux_set_gpr_register(1, 19, 1, 1);
else if (cpu_is_mx6dl())
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.h b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
index c087de6fb789..9b5af3c2a68c 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabreauto.h
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
@@ -207,10 +207,6 @@ static iomux_v3_cfg_t mx6q_sabreauto_pads[] = {
/* HDMI */
MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE,
- /* camera reset */
- MX6Q_PAD_GPIO_19__GPIO_4_5,
- MX6Q_PAD_EIM_D24__GPIO_3_24,
-
/* MLB150 */
MX6Q_PAD_ENET_TXD1__MLB_MLBCLK,
MX6Q_PAD_GPIO_6__MLB_MLBSIG,
diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c
index 419b2447e215..2959d0de6263 100755
--- a/arch/arm/mach-mx6/board-mx6sl_arm2.c
+++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c
@@ -610,7 +610,7 @@ static struct mxc_dvfs_platform_data mx6sl_arm2_dvfscore_data = {
};
static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
- .reserved_mem_size = SZ_128M,
+ .reserved_mem_size = SZ_32M,
};
void __init early_console_setup(unsigned long base, struct clk *clk);
diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h
index d005e02cb6ac..4a04cbea0694 100644
--- a/arch/arm/mach-mx6/board-mx6sl_common.h
+++ b/arch/arm/mach-mx6/board-mx6sl_common.h
@@ -20,6 +20,8 @@
#define _BOARD_MX6SL_COMMON_H
#include <mach/iomux-mx6sl.h>
+#define MX6_BRD_LCD_RESET IMX_GPIO_NR(2, 19) /* LCD_REST */
+
#define MX6_BRD_USBOTG1_PWR IMX_GPIO_NR(4, 0) /* KEY_COL4 */
#define MX6_BRD_USBOTG2_PWR IMX_GPIO_NR(4, 2) /* KEY_COL5 */
#define MX6_BRD_LCD_PWR_EN IMX_GPIO_NR(4, 3) /* KEY_ROW5 */
@@ -31,6 +33,10 @@
#define MX6_BRD_SD2_CD IMX_GPIO_NR(5, 0) /* SD2_DAT7 */
#define MX6_BRD_SD3_CD IMX_GPIO_NR(3, 22) /* REF_CLK_32K */
#define MX6_BRD_FEC_PWR_EN IMX_GPIO_NR(4, 21) /* FEC_TX_CLK */
+#define MX6_BRD_CHG_FLT IMX_GPIO_NR(4, 14) /* ECSPI2_MISO */
+#define MX6_BRD_CHG_UOK IMX_GPIO_NR(4, 13) /* ECSPI2_MOSI */
+#define MX6_BRD_CHG_DOK IMX_GPIO_NR(4, 13) /* ECSPI2_MOSI */
+#define MX6_BRD_CHG_STATUS IMX_GPIO_NR(4, 15) /* ECSPI2_SS0 */
/* EPDC GPIO pins */
#define MX6SL_BRD_EPDC_SDDO_0 IMX_GPIO_NR(1, 7)
@@ -76,6 +82,9 @@
#define MX6SL_BRD_ELAN_CE IMX_GPIO_NR(2, 9)
#define MX6SL_BRD_ELAN_INT IMX_GPIO_NR(2, 10)
#define MX6SL_BRD_ELAN_RST IMX_GPIO_NR(4, 4)
+/* CSI */
+#define MX6SL_BRD_CSI_PWDN IMX_GPIO_NR(1, 25)
+#define MX6SL_BRD_CSI_RST IMX_GPIO_NR(1, 26)
static iomux_v3_cfg_t mx6sl_brd_pads[] = {
@@ -89,6 +98,9 @@ static iomux_v3_cfg_t mx6sl_brd_pads[] = {
/* Audio Codec */
MX6SL_PAD_FEC_RX_ER__GPIO_4_19, /* HEADPHONE_DET */
+ /* SPDIF TX */
+ MX6SL_PAD_SD2_DAT4__SPDIF_OUT1,
+
/* UART1 */
MX6SL_PAD_UART1_RXD__UART1_RXD,
MX6SL_PAD_UART1_TXD__UART1_TXD,
@@ -213,6 +225,11 @@ static iomux_v3_cfg_t mx6sl_brd_pads[] = {
/* WDOG */
MX6SL_PAD_WDOG_B__WDOG1_WDOG_B,
+
+ /* Charge */
+ MX6SL_PAD_ECSPI2_MISO__GPIO_4_14, /* CHG_FLT */
+ MX6SL_PAD_ECSPI2_SS0__GPIO_4_15, /* CHG_STATUS */
+ MX6SL_PAD_ECSPI2_MOSI__GPIO_4_13, /* CHG_UOK ,CHG_DOK*/
};
static iomux_v3_cfg_t mx6sl_brd_epdc_enable_pads[] = {
@@ -372,11 +389,40 @@ static iomux_v3_cfg_t mx6sl_brd_spdc_disable_pads[] = {
MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
};
+static iomux_v3_cfg_t mx6sl_brd_csi_enable_pads[] = {
+ MX6SL_PAD_EPDC_GDRL__CSI_MCLK,
+ MX6SL_PAD_EPDC_SDCE3__I2C3_SDA,
+ MX6SL_PAD_EPDC_SDCE2__I2C3_SCL,
+ MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK,
+ MX6SL_PAD_EPDC_GDSP__CSI_VSYNC,
+ MX6SL_PAD_EPDC_GDOE__CSI_HSYNC,
+ MX6SL_PAD_EPDC_SDLE__CSI_D_9,
+ MX6SL_PAD_EPDC_SDCLK__CSI_D_8,
+ MX6SL_PAD_EPDC_D7__CSI_D_7,
+ MX6SL_PAD_EPDC_D6__CSI_D_6,
+ MX6SL_PAD_EPDC_D5__CSI_D_5,
+ MX6SL_PAD_EPDC_D4__CSI_D_4,
+ MX6SL_PAD_EPDC_D3__CSI_D_3,
+ MX6SL_PAD_EPDC_D2__CSI_D_2,
+ MX6SL_PAD_EPDC_D1__CSI_D_1,
+ MX6SL_PAD_EPDC_D0__CSI_D_0,
+
+ MX6SL_PAD_EPDC_SDSHR__GPIO_1_26, /* CMOS_RESET_B GPIO */
+ MX6SL_PAD_EPDC_SDOE__GPIO_1_25, /* CMOS_PWDN GPIO */
+};
+
static iomux_v3_cfg_t mx6sl_brd_elan_pads[] = {
MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10, /* INT */
MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9, /* CE */
MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */
};
+ /* uart2 pins */
+static iomux_v3_cfg_t mx6sl_uart2_pads[] = {
+ MX6SL_PAD_SD2_DAT5__UART2_TXD,
+ MX6SL_PAD_SD2_DAT4__UART2_RXD,
+ MX6SL_PAD_SD2_DAT6__UART2_RTS,
+ MX6SL_PAD_SD2_DAT7__UART2_CTS,
+};
#define MX6SL_USDHC_8BIT_PAD_SETTING(id, speed) \
mx6sl_sd##id##_##speed##mhz[] = { \
diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c
index 81654a0c99fd..e656638c31d6 100644
--- a/arch/arm/mach-mx6/board-mx6sl_evk.c
+++ b/arch/arm/mach-mx6/board-mx6sl_evk.c
@@ -52,6 +52,7 @@
#include <linux/mfd/max17135.h>
#include <sound/wm8962.h>
#include <sound/pcm.h>
+#include <linux/power/sabresd_battery.h>
#include <mach/common.h>
#include <mach/hardware.h>
@@ -83,12 +84,21 @@ extern char *soc_reg_id;
extern char *pu_reg_id;
extern int __init mx6sl_evk_init_pfuze100(u32 int_gpio);
+static int csi_enabled;
+
enum sd_pad_mode {
SD_PAD_MODE_LOW_SPEED,
SD_PAD_MODE_MED_SPEED,
SD_PAD_MODE_HIGH_SPEED,
};
+static int __init csi_setup(char *__unused)
+{
+ csi_enabled = 1;
+ return 1;
+}
+__setup("csi", csi_setup);
+
static int plt_sd_pad_change(unsigned int index, int clock)
{
/* LOW speed is the default state of SD pads */
@@ -556,6 +566,115 @@ static int __init imx6q_init_audio(void)
return 0;
}
+static int spdif_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long rate_actual;
+ rate_actual = clk_round_rate(clk, rate);
+ clk_set_rate(clk, rate_actual);
+ return 0;
+}
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 1,
+ .spdif_clk_48000 = -1,
+ .spdif_div_44100 = 23,
+ .spdif_clk_set_rate = spdif_clk_set_rate,
+ .spdif_clk = NULL,
+};
+
+int hdmi_enabled;
+static int __init hdmi_setup(char *__unused)
+{
+ hdmi_enabled = 1;
+ return 1;
+}
+__setup("hdmi", hdmi_setup);
+
+static iomux_v3_cfg_t mx6sl_sii902x_hdmi_pads_enabled[] = {
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10,
+};
+
+static int sii902x_get_pins(void)
+{
+ /* Sii902x HDMI controller */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_sii902x_hdmi_pads_enabled, \
+ ARRAY_SIZE(mx6sl_sii902x_hdmi_pads_enabled));
+
+ /* Reset Pin */
+ gpio_request(MX6_BRD_LCD_RESET, "disp0-reset");
+ gpio_direction_output(MX6_BRD_LCD_RESET, 1);
+
+ /* Interrupter pin GPIO */
+ gpio_request(MX6SL_BRD_EPDC_PWRCTRL3, "disp0-detect");
+ gpio_direction_input(MX6SL_BRD_EPDC_PWRCTRL3);
+ return 1;
+}
+
+static void sii902x_put_pins(void)
+{
+ gpio_free(MX6_BRD_LCD_RESET);
+ gpio_free(MX6SL_BRD_EPDC_PWRCTRL3);
+}
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX6_BRD_LCD_RESET, 0);
+ msleep(10);
+ gpio_set_value(MX6_BRD_LCD_RESET, 1);
+ msleep(10);
+}
+
+static struct fsl_mxc_lcd_platform_data sii902x_hdmi_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .reset = sii902x_hdmi_reset,
+ .get_pins = sii902x_get_pins,
+ .put_pins = sii902x_put_pins,
+};
+
+static void mx6sl_csi_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_csi_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_csi_enable_pads));
+
+ /* Camera reset */
+ gpio_request(MX6SL_BRD_CSI_RST, "cam-reset");
+ gpio_direction_output(MX6SL_BRD_CSI_RST, 1);
+
+ /* Camera power down */
+ gpio_request(MX6SL_BRD_CSI_PWDN, "cam-pwdn");
+ gpio_direction_output(MX6SL_BRD_CSI_PWDN, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 0);
+ msleep(1);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+}
+
+static void mx6sl_csi_cam_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+ else
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+
+ msleep(2);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .mclk = 24000000,
+ .io_init = mx6sl_csi_io_init,
+ .pwdn = mx6sl_csi_cam_powerdown,
+ .core_regulator = "VGEN2_1V5",
+ .analog_regulator = "VGEN6_2V8",
+};
+
static struct imxi2c_platform_data mx6_evk_i2c0_data = {
.bitrate = 100000,
};
@@ -565,7 +684,7 @@ static struct imxi2c_platform_data mx6_evk_i2c1_data = {
};
static struct imxi2c_platform_data mx6_evk_i2c2_data = {
- .bitrate = 400000,
+ .bitrate = 100000,
};
static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
@@ -585,10 +704,17 @@ static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
I2C_BOARD_INFO("wm8962", 0x1a),
.platform_data = &wm8962_config_data,
},
+ {
+ I2C_BOARD_INFO("sii902x", 0),
+ .platform_data = &sii902x_hdmi_data,
+ .irq = gpio_to_irq(MX6SL_BRD_EPDC_PWRCTRL3)
+ },
};
static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
{
+ I2C_BOARD_INFO("ov5640", 0x3c),
+ .platform_data = (void *)&camera_data,
},
};
@@ -623,11 +749,17 @@ static struct mxc_dvfs_platform_data mx6sl_evk_dvfscore_data = {
};
static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
- .reserved_mem_size = SZ_128M,
+ .reserved_mem_size = SZ_32M,
};
void __init early_console_setup(unsigned long base, struct clk *clk);
+static const struct imxuart_platform_data mx6sl_evk_uart1_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS | IMXUART_SDMA,
+ .dma_req_rx = MX6Q_DMA_REQ_UART2_RX,
+ .dma_req_tx = MX6Q_DMA_REQ_UART2_TX,
+};
+
static inline void mx6_evk_init_uart(void)
{
imx6q_add_imx_uart(0, NULL); /* DEBUG UART1 */
@@ -1105,7 +1237,7 @@ static struct platform_pwm_backlight_data mx6_evk_pwm_backlight_data = {
.dft_brightness = 128,
.pwm_period_ns = 50000,
};
-static struct fb_videomode video_modes[] = {
+static struct fb_videomode wvga_video_modes[] = {
{
/* 800x480 @ 57 Hz , pixel clk @ 32MHz */
"SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10,
@@ -1114,12 +1246,12 @@ static struct fb_videomode video_modes[] = {
0,},
};
-static struct mxc_fb_platform_data fb_data[] = {
+static struct mxc_fb_platform_data wvga_fb_data[] = {
{
.interface_pix_fmt = V4L2_PIX_FMT_RGB24,
.mode_str = "SEIKO-WVGA",
- .mode = video_modes,
- .num_modes = ARRAY_SIZE(video_modes),
+ .mode = wvga_video_modes,
+ .num_modes = ARRAY_SIZE(wvga_video_modes),
},
};
@@ -1127,6 +1259,24 @@ static struct platform_device lcd_wvga_device = {
.name = "lcd_seiko",
};
+static struct fb_videomode hdmi_video_modes[] = {
+ {
+ /* 1920x1080 @ 60 Hz , pixel clk @ 148MHz */
+ "sii9022x_1080p60", 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data hdmi_fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "1920x1080M@60",
+ .mode = hdmi_video_modes,
+ .num_modes = ARRAY_SIZE(hdmi_video_modes),
+ },
+};
+
static int mx6sl_evk_keymap[] = {
KEY(0, 0, KEY_SELECT),
KEY(0, 1, KEY_BACK),
@@ -1174,6 +1324,33 @@ static void __init elan_ts_init(void)
gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
}
+/*
+ *Usually UOK and DOK should have separate
+ *line to differentiate its behaviour (with different
+ * GPIO irq),because connect max8903 pin UOK to
+ *pin DOK from hardware design,cause software cannot
+ *process and distinguish two interrupt, so default
+ *enable dc_valid for ac charger
+ */
+static struct max8903_pdata charger1_data = {
+ .dok = MX6_BRD_CHG_DOK,
+ .uok = MX6_BRD_CHG_UOK,
+ .chg = MX6_BRD_CHG_STATUS,
+ .flt = MX6_BRD_CHG_FLT,
+ .dcm_always_high = true,
+ .dc_valid = true,
+ .usb_valid = false,
+ .feature_flag = 1,
+};
+
+static struct platform_device evk_max8903_charger_1 = {
+ .name = "max8903-charger",
+ .dev = {
+ .platform_data = &charger1_data,
+ },
+};
+
+
#define SNVS_LPCR 0x38
static void mx6_snvs_poweroff(void)
{
@@ -1185,11 +1362,27 @@ static void mx6_snvs_poweroff(void)
writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
}
+static int uart2_enabled;
+static int __init uart2_setup(char * __unused)
+{
+ uart2_enabled = 1;
+ return 1;
+}
+__setup("bluetooth", uart2_setup);
+
+static void __init uart2_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_uart2_pads,
+ ARRAY_SIZE(mx6sl_uart2_pads));
+ imx6sl_add_imx_uart(1, &mx6sl_evk_uart1_data);
+}
/*!
* Board specific initialization.
*/
static void __init mx6_evk_init(void)
{
+ u32 i;
+
mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads,
ARRAY_SIZE(mx6sl_brd_pads));
@@ -1211,11 +1404,25 @@ static void __init mx6_evk_init(void)
imx6q_add_imx_i2c(1, &mx6_evk_i2c1_data);
i2c_register_board_info(0, mxc_i2c0_board_info,
ARRAY_SIZE(mxc_i2c0_board_info));
+
+ /* setting sii902x address when hdmi enabled */
+ if (hdmi_enabled) {
+ for (i = 0; i < ARRAY_SIZE(mxc_i2c1_board_info); i++) {
+ if (!strcmp(mxc_i2c1_board_info[i].type, "sii902x")) {
+ mxc_i2c1_board_info[i].addr = 0x39;
+ break;
+ }
+ }
+ }
+
i2c_register_board_info(1, mxc_i2c1_board_info,
ARRAY_SIZE(mxc_i2c1_board_info));
- imx6q_add_imx_i2c(2, &mx6_evk_i2c2_data);
- i2c_register_board_info(2, mxc_i2c2_board_info,
- ARRAY_SIZE(mxc_i2c2_board_info));
+ /* only camera on I2C3, that's why we can do so */
+ if (csi_enabled == 1) {
+ imx6q_add_imx_i2c(2, &mx6_evk_i2c2_data);
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+ }
/* SPI */
imx6q_add_ecspi(0, &mx6_evk_spi_data);
@@ -1243,24 +1450,37 @@ static void __init mx6_evk_init(void)
imx6q_add_otp();
imx6q_add_mxc_pwm(0);
imx6q_add_mxc_pwm_backlight(0, &mx6_evk_pwm_backlight_data);
- imx6dl_add_imx_elcdif(&fb_data[0]);
- gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
- gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
- mxc_register_device(&lcd_wvga_device, NULL);
+ if (hdmi_enabled) {
+ imx6dl_add_imx_elcdif(&hdmi_fb_data[0]);
+ } else {
+ imx6dl_add_imx_elcdif(&wvga_fb_data[0]);
+
+ gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
+ gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
+ mxc_register_device(&lcd_wvga_device, NULL);
+ }
imx6dl_add_imx_pxp();
imx6dl_add_imx_pxp_client();
mxc_register_device(&max17135_sensor_device, NULL);
setup_spdc();
- if (!spdc_sel)
- imx6dl_add_imx_epdc(&epdc_data);
- else
- imx6sl_add_imx_spdc(&spdc_data);
+ if (csi_enabled) {
+ imx6sl_add_fsl_csi();
+ } else {
+ if (!spdc_sel)
+ imx6dl_add_imx_epdc(&epdc_data);
+ else
+ imx6sl_add_imx_spdc(&spdc_data);
+ }
imx6q_add_dvfs_core(&mx6sl_evk_dvfscore_data);
imx6q_init_audio();
+ /* uart2 for bluetooth */
+ if (uart2_enabled)
+ uart2_init();
+
imx6q_add_viim();
imx6q_add_imx2_wdt(0, NULL);
@@ -1271,10 +1491,17 @@ static void __init mx6_evk_init(void)
imx6sl_add_rngb();
imx6sl_add_imx_pxp_v4l2();
+ mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0", NULL);
+ clk_put(mxc_spdif_data.spdif_core_clk);
+ imx6q_add_spdif(&mxc_spdif_data);
+ imx6q_add_spdif_dai();
+ imx6q_add_spdif_audio_device();
+
imx6q_add_perfmon(0);
imx6q_add_perfmon(1);
imx6q_add_perfmon(2);
-
+ /* Register charger chips */
+ platform_device_register(&evk_max8903_charger_1);
pm_power_off = mx6_snvs_poweroff;
}
diff --git a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
index 9111e6bc9b19..b752faae33ba 100644
--- a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
+++ b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
@@ -207,10 +207,6 @@ static iomux_v3_cfg_t mx6dl_sabreauto_pads[] = {
/* HDMI */
MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE,
- /* camera reset */
- MX6DL_PAD_GPIO_19__GPIO_4_5,
- MX6DL_PAD_EIM_D24__GPIO_3_24,
-
/* MLB150 */
MX6DL_PAD_ENET_TXD1__MLB_MLBCLK,
MX6DL_PAD_GPIO_6__MLB_MLBSIG,
diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c
index 9d18423c85c5..d96ac6a1e928 100644
--- a/arch/arm/mach-mx6/bus_freq.c
+++ b/arch/arm/mach-mx6/bus_freq.c
@@ -412,7 +412,7 @@ void bus_freq_update(struct clk *clk, bool flag)
*/
high_cpu_freq = 1;
if (low_bus_freq_mode || audio_bus_freq_mode)
- set_high_bus_freq(0);
+ set_high_bus_freq(1);
} else {
/* Update count */
if (clk->flags & AHB_HIGH_SET_POINT)
@@ -471,7 +471,7 @@ void bus_freq_update(struct clk *clk, bool flag)
/* Set to either high or
* medium setpoint.
*/
- set_high_bus_freq(0);
+ set_high_bus_freq(1);
}
}
}
@@ -506,7 +506,7 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev,
#else
bus_freq_scaling_is_active = 1;
#endif
- set_high_bus_freq(0);
+ set_high_bus_freq(1);
/* Make sure system can enter low bus mode if it should be in
low bus mode */
if (low_freq_bus_used() && !low_bus_freq_mode)
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c
index 5c3f053ce5fd..0c05c37f81d5 100644
--- a/arch/arm/mach-mx6/clock.c
+++ b/arch/arm/mach-mx6/clock.c
@@ -4854,7 +4854,7 @@ static struct clk usboh3_clk[] = {
.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
.disable = _clk_disable,
.secondary = &usboh3_clk[1],
- .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
},
{
.parent = &mmdc_ch0_axi_clk[0],
@@ -5304,6 +5304,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "mlb150_clk", mlb150_clk),
_REGISTER_CLOCK(NULL, "anaclk_1", anaclk_1),
_REGISTER_CLOCK(NULL, "anaclk_2", anaclk_2),
+ _REGISTER_CLOCK(NULL, "apb_pclk", dummy_clk),
};
static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c
index 616099180008..6de15622eede 100755
--- a/arch/arm/mach-mx6/clock_mx6sl.c
+++ b/arch/arm/mach-mx6/clock_mx6sl.c
@@ -1945,8 +1945,8 @@ static unsigned long _clk_ipu_round_rate(struct clk *clk,
}
static struct clk ipu1_clk = {
- __INIT_CLK_DEBUG(ipu1_clk)
- .parent = &pll2_pfd2_400M,
+ __INIT_CLK_DEBUG(csi_clk)
+ .parent = &osc_clk,
.enable_reg = MXC_CCM_CCGR3,
.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
.enable = _clk_enable,
@@ -4065,9 +4065,9 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc,
3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR1);
__raw_writel(1 << MXC_CCM_CCGRx_CG12_OFFSET |
1 << MXC_CCM_CCGRx_CG11_OFFSET |
- 1 << MXC_CCM_CCGRx_CG10_OFFSET |
- 1 << MXC_CCM_CCGRx_CG9_OFFSET |
- 1 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
+ 3 << MXC_CCM_CCGRx_CG10_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
__raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET |
3 << MXC_CCM_CCGRx_CG13_OFFSET |
3 << MXC_CCM_CCGRx_CG12_OFFSET |
diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c
index be5011aeab34..fbb3827668e0 100644
--- a/arch/arm/mach-mx6/cpu.c
+++ b/arch/arm/mach-mx6/cpu.c
@@ -119,8 +119,14 @@ static int __init post_cpu_init(void)
{
unsigned int reg;
void __iomem *base;
+ u32 iram_size;
- iram_init(MX6Q_IRAM_BASE_ADDR, MX6Q_IRAM_SIZE);
+ if (cpu_is_mx6q())
+ iram_size = MX6Q_IRAM_SIZE;
+ else
+ iram_size = MX6DL_MX6SL_IRAM_SIZE;
+
+ iram_init(MX6Q_IRAM_BASE_ADDR, iram_size);
base = ioremap(AIPS1_ON_BASE_ADDR, PAGE_SIZE);
__raw_writel(0x0, base + 0x40);
diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c
index 7e054c1d743c..99336d873756 100644
--- a/arch/arm/mach-mx6/cpu_op-mx6.c
+++ b/arch/arm/mach-mx6/cpu_op-mx6.c
@@ -162,7 +162,7 @@ static struct cpu_op mx6dl_cpu_op_1_2G[] = {
.cpu_podf = 0,
.pu_voltage = 1175000,
.soc_voltage = 1175000,
- .cpu_voltage = 1150000,},
+ .cpu_voltage = 1175000,},
{
.pll_rate = 396000000,
.cpu_rate = 396000000,
@@ -177,16 +177,16 @@ static struct cpu_op mx6dl_cpu_op_1G[] = {
.pll_rate = 996000000,
.cpu_rate = 996000000,
.cpu_podf = 0,
- .pu_voltage = 1250000,
- .soc_voltage = 1250000,
- .cpu_voltage = 1250000,},
+ .pu_voltage = 1275000,
+ .soc_voltage = 1275000,
+ .cpu_voltage = 1275000,},
{
.pll_rate = 792000000,
.cpu_rate = 792000000,
.cpu_podf = 0,
.pu_voltage = 1175000,
.soc_voltage = 1175000,
- .cpu_voltage = 1150000,},
+ .cpu_voltage = 1175000,},
{
.pll_rate = 396000000,
.cpu_rate = 396000000,
@@ -202,7 +202,7 @@ static struct cpu_op mx6dl_cpu_op[] = {
.cpu_podf = 0,
.pu_voltage = 1175000,
.soc_voltage = 1175000,
- .cpu_voltage = 1150000,},
+ .cpu_voltage = 1175000,},
{
.pll_rate = 396000000,
.cpu_rate = 396000000,
diff --git a/arch/arm/mach-mx6/cpu_regulator-mx6.c b/arch/arm/mach-mx6/cpu_regulator-mx6.c
index cb08cad48204..5019f8bedff2 100644
--- a/arch/arm/mach-mx6/cpu_regulator-mx6.c
+++ b/arch/arm/mach-mx6/cpu_regulator-mx6.c
@@ -37,6 +37,7 @@ static struct cpu_op *cpu_op_tbl;
extern struct cpu_op *(*get_cpu_op)(int *op);
extern unsigned long loops_per_jiffy;
+int external_pureg;
static inline unsigned long mx6_cpu_jiffies(unsigned long old, u_int div,
u_int mult)
@@ -62,6 +63,7 @@ void mx6_cpu_regulator_init(void)
int cpu;
u32 curr_cpu = 0;
+ external_pureg = 0;
cpu_regulator = regulator_get(NULL, gp_reg_id);
if (IS_ERR(cpu_regulator))
printk(KERN_ERR "%s: failed to get cpu regulator\n", __func__);
@@ -108,5 +110,21 @@ 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
+ *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
+ *enable or disable external VDDPU regulator from pmic. But for FSL
+ *reference boards, VDDSOC_IN connect with VDDPU_IN, so we didn't set
+ *pu_reg_id to the external pmic regulator supply name in the board file.
+ *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
+ *VDDPU can be turned off by internal anatop anatop power gate.
+ *
+ */
+ else if (!IS_ERR(pu_regulator) && strcmp(pu_reg_id, "cpu_vddvpu"))
+ external_pureg = 1;
}
diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h
index bd948cecbcd2..4525e29a472a 100644
--- a/arch/arm/mach-mx6/devices-imx6q.h
+++ b/arch/arm/mach-mx6/devices-imx6q.h
@@ -23,6 +23,10 @@ extern const struct imx_imx_uart_1irq_data imx6q_imx_uart_data[] __initconst;
#define imx6q_add_imx_uart(id, pdata) \
imx_add_imx_uart_1irq(&imx6q_imx_uart_data[id], pdata)
+extern const struct imx_imx_uart_1irq_data imx6sl_imx_uart_data[] __initconst;
+#define imx6sl_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx6sl_imx_uart_data[id], pdata)
+
extern const struct imx_snvs_rtc_data imx6q_imx_snvs_rtc_data __initconst;
#define imx6q_add_imx_snvs_rtc() \
imx_add_snvs_rtc(&imx6q_imx_snvs_rtc_data)
@@ -36,8 +40,8 @@ imx6q_anatop_thermal_imx_data __initconst;
#define imx6q_add_anatop_thermal_imx(id, pdata) \
imx_add_anatop_thermal_imx(&imx6q_anatop_thermal_imx_data, pdata)
-extern const struct imx_dma_data imx6q_dma_data __initconst;
-#define imx6q_add_dma() imx_add_dma(&imx6q_dma_data);
+extern const struct imx_dma_res_data imx6q_dma_res_data __initconst;
+#define imx6q_add_dma() imx_add_dma(&imx6q_dma_res_data);
#define imx6q_add_gpmi(platform_data) imx_add_gpmi(platform_data);
@@ -219,6 +223,10 @@ extern const struct imx_pxp_data imx6dl_pxp_data __initconst;
#define imx6sl_add_imx_pxp_v4l2() \
imx_add_imx_pxp_v4l2()
+extern const struct imx_fsl_csi_data imx6sl_csi_data __initconst;
+#define imx6sl_add_fsl_csi() \
+ imx_add_fsl_csi(&imx6sl_csi_data)
+
extern const struct imx_epdc_data imx6dl_epdc_data __initconst;
#define imx6dl_add_imx_epdc(pdata) \
imx_add_imx_epdc(&imx6dl_epdc_data, pdata)
diff --git a/arch/arm/mach-mx6/etm.c b/arch/arm/mach-mx6/etm.c
new file mode 100644
index 000000000000..8f328608ebfd
--- /dev/null
+++ b/arch/arm/mach-mx6/etm.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/iram_alloc.h>
+#include <linux/delay.h>
+#include <linux/amba/bus.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/coresight.h>
+
+static struct __init amba_device mx6_etb_device = {
+ .dev = {
+ .init_name = "etb",
+ },
+ .res = {
+ .start = MX6Q_ETB_BASE_ADDR,
+ .end = MX6Q_ETB_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .periphid = 0x3bb907,
+};
+
+static struct __init amba_device mx6_etm_device[] = {
+ {
+ .dev = {
+ .init_name = "etm.0",
+ },
+ .res = {
+ .start = MX6Q_PTM0_BASE_ADDR,
+ .end = MX6Q_PTM0_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.1",
+ },
+ .res = {
+ .start = MX6Q_PTM1_BASE_ADDR,
+ .end = MX6Q_PTM1_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.2",
+ },
+ .res = {
+ .start = MX6Q_PTM2_BASE_ADDR,
+ .end = MX6Q_PTM2_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.3",
+ },
+ .res = {
+ .start = MX6Q_PTM3_BASE_ADDR,
+ .end = MX6Q_PTM3_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+};
+
+#define FUNNEL_CTL 0
+static int __init etm_init(void)
+{
+ int i;
+ __iomem void *base;
+ base = ioremap(0x02144000, SZ_4K);
+ /*Unlock Funnel*/
+ __raw_writel(UNLOCK_MAGIC, base + CSMR_LOCKACCESS);
+ /*Enable all funnel port*/
+ __raw_writel(__raw_readl(base + FUNNEL_CTL) | 0xFF,
+ base + FUNNEL_CTL);
+ /*Lock Funnel*/
+ __raw_writel(0, base + CSMR_LOCKACCESS);
+ iounmap(base);
+
+ amba_device_register(&mx6_etb_device, &iomem_resource);
+ for (i = 0; i < num_possible_cpus(); i++)
+ amba_device_register(mx6_etm_device + i, &iomem_resource);
+
+ return 0;
+}
+
+subsys_initcall(etm_init);
diff --git a/arch/arm/mach-mx6/mx6_anatop_regulator.c b/arch/arm/mach-mx6/mx6_anatop_regulator.c
index 945adbdb759a..f2c2ebf600b3 100644
--- a/arch/arm/mach-mx6/mx6_anatop_regulator.c
+++ b/arch/arm/mach-mx6/mx6_anatop_regulator.c
@@ -22,6 +22,7 @@
* mx6_anatop_regulator.c -- i.MX6 Driver for Anatop regulators
*/
#include <linux/device.h>
+#include <linux/err.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/regulator/anatop-regulator.h>
@@ -30,6 +31,9 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/clk.h>
+
+#include <mach/clock.h>
#include "crm_regs.h"
#include "regs-anadig.h"
@@ -41,8 +45,17 @@ extern struct platform_device sgtl5000_vdda_reg_devices;
extern struct platform_device sgtl5000_vddio_reg_devices;
extern struct platform_device sgtl5000_vddd_reg_devices;
extern void __iomem *gpc_base;
-/* Default PU voltage value set to 1.1V */
-static unsigned int org_ldo = 0x2000;
+/* we use the below flag to keep PU regulator state, because enable/disable
+of PU regulator share with the same register as voltage set of PU regulator.
+PU voltage set by cpufreq driver if the flag is set, and enable/disable by
+GPU/VPU driver*/
+static unsigned int pu_is_enabled;
+static unsigned int get_clk;
+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;
+
static int get_voltage(struct anatop_regulator *sreg)
{
@@ -90,17 +103,56 @@ static int set_voltage(struct anatop_regulator *sreg, int uv)
static int pu_enable(struct anatop_regulator *sreg)
{
- unsigned int reg;
+ unsigned int reg, vddsoc;
+ int ret = 0;
+ /*get PU related clk to finish PU regulator power up*/
+ if (!get_clk) {
+ if (!cpu_is_mx6sl()) {
+ gpu3d_clk = clk_get(NULL, "gpu3d_clk");
+ if (IS_ERR(gpu3d_clk))
+ printk(KERN_ERR "%s: failed to get gpu3d_clk!\n"
+ , __func__);
+ gpu3d_shade_clk = clk_get(NULL, "gpu3d_shader_clk");
+ if (IS_ERR(gpu3d_shade_clk))
+ printk(KERN_ERR "%s: failed to get shade_clk!\n"
+ , __func__);
+ if (IS_ERR(vpu_clk))
+ printk(KERN_ERR "%s: failed to get vpu_clk!\n",
+ __func__);
+ }
+ gpu2d_clk = clk_get(NULL, "gpu2d_clk");
+ if (IS_ERR(gpu2d_clk))
+ printk(KERN_ERR "%s: failed to get gpu2d_clk!\n",
+ __func__);
+ gpu2d_axi_clk = clk_get(NULL, "gpu2d_axi_clk");
+ if (IS_ERR(gpu2d_axi_clk))
+ printk(KERN_ERR "%s: failed to get gpu2d_axi_clk!\n",
+ __func__);
+ openvg_axi_clk = clk_get(NULL, "openvg_axi_clk");
+ if (IS_ERR(openvg_axi_clk))
+ printk(KERN_ERR "%s: failed to get openvg_axi_clk!\n",
+ __func__);
+ get_clk = 1;
- /* Do not enable PU LDO if it is already enabled */
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
- << ANADIG_REG1_PU_TARGET_OFFSET);
- if (reg != 0)
- return 0;
-
- /* Set the voltage of VDDPU as in normal mode. */
- __raw_writel(org_ldo | (__raw_readl(ANADIG_REG_CORE) &
- (~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET))), ANADIG_REG_CORE);
+ }
+ if (external_pureg) {
+ /*enable extern PU regulator*/
+ ret = regulator_enable(pu_regulator);
+ if (ret < 0)
+ printk(KERN_ERR "%s: enable pu error!\n", __func__);
+ } else {
+ /*Track the voltage of VDDPU with VDDSOC if use internal PU
+ *regulator.
+ */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ vddsoc = reg & (ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG2_SOC_TARGET_OFFSET);
+ reg &= ~(ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG1_PU_TARGET_OFFSET);
+ reg |= vddsoc >> (ANADIG_REG2_SOC_TARGET_OFFSET
+ -ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ }
/* Need to wait for the regulator to come back up */
/*
@@ -109,7 +161,17 @@ static int pu_enable(struct anatop_regulator *sreg)
* 25mV step.
*/
udelay(150);
-
+ /*enable gpu clock to powerup GPU right.*/
+ if (get_clk) {
+ if (!cpu_is_mx6sl()) {
+ clk_enable(gpu3d_clk);
+ clk_enable(gpu3d_shade_clk);
+ clk_enable(vpu_clk);
+ }
+ clk_enable(gpu2d_clk);
+ clk_enable(gpu2d_axi_clk);
+ clk_enable(openvg_axi_clk);
+ }
/* enable power up request */
reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
__raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
@@ -119,7 +181,6 @@ static int pu_enable(struct anatop_regulator *sreg)
/* Wait for the power up bit to clear */
while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x2)
;
-
/* Enable the Brown Out detection. */
reg = __raw_readl(ANA_MISC2_BASE_ADDR);
reg |= ANADIG_ANA_MISC2_REG1_BO_EN;
@@ -131,19 +192,24 @@ static int pu_enable(struct anatop_regulator *sreg)
reg &= ~0x80000000;
__raw_writel(reg, gpc_base + 0x14);
#endif
-
+ pu_is_enabled = 1;
+ if (get_clk) {
+ if (!cpu_is_mx6sl()) {
+ clk_disable(gpu3d_clk);
+ clk_disable(gpu3d_shade_clk);
+ clk_disable(vpu_clk);
+ }
+ clk_disable(gpu2d_clk);
+ clk_disable(gpu2d_axi_clk);
+ clk_disable(openvg_axi_clk);
+ }
return 0;
}
static int pu_disable(struct anatop_regulator *sreg)
{
unsigned int reg;
-
- /* Do not disable PU LDO if it is not enabled */
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
- << ANADIG_REG1_PU_TARGET_OFFSET);
- if (reg == 0)
- return 0;
+ int ret = 0;
/* Disable the brown out detection since we are going to be
* disabling the LDO.
@@ -163,7 +229,6 @@ 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);
@@ -171,12 +236,19 @@ static int pu_disable(struct anatop_regulator *sreg)
__raw_writel(reg, gpc_base + 0x14);
#endif
- /* PU power gating. */
- reg = __raw_readl(ANADIG_REG_CORE);
- org_ldo = reg & (ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- __raw_writel(reg, ANADIG_REG_CORE);
-
+ if (external_pureg) {
+ /*disable extern PU regulator*/
+ ret = regulator_disable(pu_regulator);
+ if (ret < 0)
+ printk(KERN_ERR "%s: disable pu error!\n", __func__);
+ } else {
+ /* PU power gating. */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ reg &= ~(ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ }
+ pu_is_enabled = 0;
/* Clear the BO interrupt in the ANATOP. */
reg = __raw_readl(ANADIG_MISC1_REG);
reg |= 0x80000000;
@@ -185,14 +257,7 @@ static int pu_disable(struct anatop_regulator *sreg)
}
static int is_pu_enabled(struct anatop_regulator *sreg)
{
- unsigned int reg;
-
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
- << ANADIG_REG1_PU_TARGET_OFFSET);
- if (reg == 0)
- return 0;
- else
- return 1;
+ return pu_is_enabled;
}
static int enable(struct anatop_regulator *sreg)
{
@@ -447,6 +512,9 @@ static int __init regulators_init(void)
anatop_register_regulator(&vdd1p1_reg, ANATOP_VDD1P1, &vdd1p1_init);
anatop_register_regulator(&vdd3p0_reg, ANATOP_VDD3P0, &vdd3p0_init);
+ /* clear flag in boot*/
+ pu_is_enabled = 0;
+ get_clk = 0;
return 0;
}
postcore_initcall(regulators_init);
diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S
index 0533ad1b20ef..e8fd2b259aae 100644
--- a/arch/arm/mach-mx6/mx6_suspend.S
+++ b/arch/arm/mach-mx6/mx6_suspend.S
@@ -32,7 +32,7 @@
#define MMDC_MAPSR_OFFSET 0x404
#define MMDC_MAPSR_PSS (1 << 4)
#define MMDC_MAPSR_PSD (1 << 0)
-#define IRAM_SUSPEND_SIZE (1 << 12)
+#define IRAM_SUSPEND_SIZE (1 << 13)
/*************************************************************
mx6_suspend:
@@ -50,6 +50,333 @@ see define in include/linux/suspend.h
r1: iram_paddr
r2: suspend_iram_base
*************************************************************/
+ .macro mx6sl_standy_saving_set
+
+ /* Move periph_clk to OSC_CLK. */
+ ldr r1, =CCM_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Ensure the periph_clk2_sel to OSC clk. */
+ ldr r0, [r1, #0x18]
+ bic r0, r0, #0x3000
+ orr r0, r0, #0x1000
+ str r0, [r1, #0x18]
+
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r1, #0x14]
+
+periph_clk_switch:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch
+
+ /* Set the divider to divider by 8 */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x70000
+ orr r0, r0, #0x1c00
+ str r0, [r1, #0x14]
+
+ahb_podf:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne ahb_podf
+
+ /* Move DDR clk to PLL3 clock.
+ */
+ /* First set the divider to 2. */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x1
+ str r0, [r1, #0x14]
+
+ ldr r0, [r1, #0x18]
+ bic r0, r0, #0x100000
+ str r0, [r1, #0x18]
+
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x4000000
+ str r0, [r1, #0x14]
+
+ddr_switch:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne ddr_switch
+
+ /* Set DDR clock to divide by 8. */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x38
+ str r0, [r1, #0x14]
+
+mmdc_div:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne mmdc_div
+
+ /* Now Switch ARM to run from
+ * step_clk sourced from OSC.
+ */
+ ldr r0, [r1, #0xc]
+ bic r0, r1, #0x100
+ str r0, [r1, #0x0c]
+
+ /* Now switch PLL1_SW_CLK to step_clk. */
+ ldr r0, [r1, #0x0c]
+ orr r0, r0, #0x4
+ str r0, [r1, #0x0c]
+
+ ldr r1, =ANATOP_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Need to clock gate the 528 PFDs before
+ * powering down PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC/AHB
+ */
+ ldr r0, [r1, #0x100]
+ orr r0, r0, #0x800000
+ str r0, [r1, #0x100]
+
+ /* Now bypass PLL1 and PLL2. */
+ ldr r0, =0x10000
+ str r0, [r1, #0x4]
+ str r0, [r1, #0x34]
+
+ /* Now do all the analog savings. */
+
+ /* Disable 1p1 brown out. */
+ ldr r0, [r1, #0x110]
+ bic r0, r0, #0x2
+ str r0, [r1, #0x110]
+
+ /* Enable the weak 2P5 */
+ ldr r0, [r1, #0x130]
+ orr r0, r0, #0x40000
+ str r0, [r1, #0x130]
+
+ /*Disable main 2p5. */
+ ldr r0, [r1, #0x130]
+ bic r0, r0, #0x1
+ str r0, [r1, #0x130]
+
+
+ /* Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r0, [r1, #0x150]
+ orr r0, r0, #0xC000
+ str r0, [r1, #0x150]
+ .endm
+
+ .macro mx6sl_standby_savings_restore
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r1, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r1, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r1, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r1, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5:
+ ldr r6, [r1, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r1, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r1, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r1, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r1, #0x110]
+
+ /* Unbypass PLLs and
+ * wait for relock.
+ */
+ ldr r6, =(1 << 16)
+ str r6, [r1, #0x08]
+ str r6, [r1, #0x38]
+
+wait_for_pll_lock:
+ ldr r6, [r1, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r3, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r3, #0xc]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r1, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r1, #0x100]
+
+ /* Move periph_clk back
+ * to PLL2_PFD2_400.
+ */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x2000000
+ str r6, [r3, #0x14]
+
+ /* Set the dividers to default value. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x70000
+ bic r6, r6, #0x1c00
+ orr r6, r6, #0x10800
+ str r6, [r3, #0x14]
+
+ahb_podf1:
+ ldr r0, [r3, #0x48]
+ cmp r0, #0
+ bne ahb_podf1
+
+periph_clk_switch1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne periph_clk_switch1
+
+ /* Move MMDC back to PLL2_PFD2_400 */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r3, #0x14]
+
+mmdc_loop2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_loop2
+
+ /* Set DDR clock to divide by 1. */
+ ldr r6, [r3, #0x14]
+ bic r6, r0, #0x38
+ str r6, [r3, #0x14]
+
+mmdc_div1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_div1
+
+ .endm
+
+ .macro mx6sl_standby_pg_savings_restore
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r1, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r1, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r1, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r1, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5_1:
+ ldr r6, [r1, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5_1
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r1, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r1, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r1, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r1, #0x110]
+
+ /* Unbypass PLLs and
+ * wait for relock.
+ */
+ ldr r6, =(1 << 16)
+ str r6, [r1, #0x08]
+ str r6, [r1, #0x38]
+
+wait_for_pll_lock1:
+ ldr r6, [r1, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock1
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r3, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r3, #0xc]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r1, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r1, #0x100]
+
+ /* Move DDR clock back to PLL2_PFD2_400 */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r3, #0x14]
+
+mmdc_loop3:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_loop3
+
+ /* Set DDR clock to divide by 1. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x38
+ str r6, [r3, #0x14]
+
+mmdc_div2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_div2
+
+ /* Move periph_clk back
+ * to PLL2_PFD2_400.
+ */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x2000000
+ str r6, [r3, #0x14]
+
+periph_clk_switch2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne periph_clk_switch2
+
+ /* Set the dividers to default value. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x70000
+ bic r6, r6, #0x1c00
+ orr r6, r6, #0x10800
+ str r6, [r3, #0x14]
+
+ahb_podf2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne ahb_podf2
+
+ .endm
+
.macro sl_ddr_io_save
ldr r4, [r1, #0x30c] /* DRAM_DQM0 */
@@ -58,12 +385,6 @@ r2: suspend_iram_base
ldr r7, [r1, #0x318] /* DRAM_DQM3 */
stmfd r0!, {r4-r7}
- ldr r4, [r1, #0x344] /* DRAM_SDQS0 */
- ldr r5, [r1, #0x348] /* DRAM_SDQS1 */
- ldr r6, [r1, #0x34c] /* DRAM_SDQS2 */
- ldr r7, [r1, #0x350] /* DRAM_SDQS3 */
- stmfd r0!, {r4-r7}
-
ldr r4, [r1, #0x5c4] /* GPR_B0DS */
ldr r5, [r1, #0x5cc] /* GPR_B1DS */
ldr r6, [r1, #0x5d4] /* GPR_B2DS */
@@ -73,7 +394,7 @@ r2: suspend_iram_base
ldr r4, [r1, #0x300] /* DRAM_CAS */
ldr r5, [r1, #0x31c] /* DRAM_RAS */
ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */
- ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
+ ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
stmfd r0!, {r4-r7}
ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */
@@ -98,22 +419,16 @@ r2: suspend_iram_base
str r7, [r1, #0x318] /* DRAM_DQM3 */
ldmea r0!, {r4-r7}
- str r4, [r1, #0x344] /* DRAM_SDQS0 */
- str r5, [r1, #0x348] /* DRAM_SDQS1 */
- str r6, [r1, #0x34c] /* DRAM_SDQS2 */
- str r7, [r1, #0x350] /* DRAM_SDQS3 */
-
- ldmea r0!, {r4-r7}
str r4, [r1, #0x5c4] /* GPR_B0DS */
str r5, [r1, #0x5cc] /* GPR_B1DS */
- str r6, [r1, #0x5d4] /* GPR_B2DS */
- str r7, [r1, #0x5d8] /* GPR_B3DS */
+ str r6, [r1, #0x5d4] /* GPR_B2DS */
+ str r7, [r1, #0x5d8] /* GPR_B3DS */
ldmea r0!, {r4-r7}
str r4, [r1, #0x300] /* DRAM_CAS */
str r5, [r1, #0x31c] /* DRAM_RAS */
str r6, [r1, #0x338] /* DRAM_SDCLK_0 */
- str r7, [r1, #0x5ac] /* GPR_ADDS*/
+ str r7, [r1, #0x5ac] /* GPR_ADDS*/
ldmea r0!, {r4-r7}
str r4, [r1, #0x5b0] /* DDRMODE_CTL */
@@ -136,27 +451,15 @@ r2: suspend_iram_base
str r0, [r1, #0x314] /* DRAM_DQM2 */
str r0, [r1, #0x318] /* DRAM_DQM3 */
- /* Make sure the Pull Ups are enabled.
- * So only reduce the drive stength, but
- * leave the pull-ups in the original state.
- * This is required for LPDDR2.
- */
- ldr r0, [r1, #0x344]
- orr r0, r0, #0x3000
- str r0, [r1, #0x344] /* DRAM_SDQS0 */
- str r0, [r1, #0x348] /* DRAM_SDQS1 */
- str r0, [r1, #0x34c] /* DRAM_SDQS2 */
- str r0, [r1, #0x350] /* DRAM_SDQS3 */
-
str r0, [r1, #0x5c4] /* GPR_B0DS */
str r0, [r1, #0x5cc] /* GPR_B1DS */
- str r0, [r1, #0x5d4] /* GPR_B2DS */
- str r0, [r1, #0x5d8] /* GPR_B3DS */
+ str r0, [r1, #0x5d4] /* GPR_B2DS */
+ str r0, [r1, #0x5d8] /* GPR_B3DS */
str r0, [r1, #0x300] /* DRAM_CAS */
str r0, [r1, #0x31c] /* DRAM_RAS */
str r0, [r1, #0x338] /* DRAM_SDCLK_0 */
- str r0, [r1, #0x5ac] /* GPR_ADDS*/
+ str r0, [r1, #0x5ac] /* GPR_ADDS*/
str r0, [r1, #0x5b0] /* DDRMODE_CTL */
str r0, [r1, #0x5c0] /* DDRMODE */
@@ -617,6 +920,10 @@ ENTRY(mx6_suspend)
suspend mode entry
*************************************************************/
mov r12, r3 /* Save CPU type to r12*/
+ mov r11, r0 /* Save the state in r11 */
+
+ cmp r12, #MXC_CPU_MX6SL
+ beq dormant
cmp r0, #0x1
bne dormant /* dormant mode */
@@ -666,14 +973,17 @@ suspend mode entry
never run to here
************************************************************/
b out /* exit standby */
-
+ /* Place the literal pool here so that
+ * literals are within 4KB range
+ */
+ .ltorg
/************************************************************
dormant entry, data save in stack, save sp in the src_gpr2
************************************************************/
dormant:
mov r3, r1
mov r0, r1
- add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
ldr r4, =SRC_BASE_ADDR
add r4, r4, #PERIPBASE_VIRT
str r0, [r4, #SRC_GPR2_OFFSET] /* set src_gpr2 */
@@ -701,10 +1011,12 @@ saved register and context as below:
iram_suspend base */
mov r0, r2 /* get suspend_iram_base */
- add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
mov r4, r12 @ Store cpu type
stmfd r0!, {r4}
+ mov r4, r11 @ Store state entered
+ stmfd r0!, {r4}
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
@@ -784,6 +1096,9 @@ set ddr iomux to low power mode
ldr r1, =SRC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
ldr r0, [r1]
+ 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
@@ -795,14 +1110,23 @@ set ddr iomux to low power mode
ldr r1, =MMDC_P0_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
- ldr r0, [r1, #MMDC_MAPSR_OFFSET]
- bic r0, #MMDC_MAPSR_PSD /* enable lpm */
- str r0, [r1, #MMDC_MAPSR_OFFSET]
-refresh:
- ldr r0, [r1, #MMDC_MAPSR_OFFSET] /* MMDC_MAPSR */
- and r0, r0, #MMDC_MAPSR_PSS /* PSS bit */
- cmp r0, #0
- beq refresh
+
+ /* Put DDR explicitly into self-refresh. */
+ /* Disable Automatic power savings. */
+ ldr r0, [r1, #0x404]
+ orr r0, r0, #0x01
+ str r0, [r1, #0x404]
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r0, [r1, #0x404]
+ orr r0, r0, #0x200000
+ str r0, [r1, #0x404]
+
+ poll_dvfs_set_1:
+ ldr r0, [r1, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ bne poll_dvfs_set_1
/* set mmdc iomux to low power mode */
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
@@ -822,6 +1146,22 @@ sl_io_set_lpm:
ddr_io_set_lpm_done:
+ /* Do Analog Power Optimizations
+ * for MX6SL in standby mode.
+ */
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_savings
+ cmp r11, #1
+ bne no_analog_savings
+
+ /* We are here because on
+ * MX6SL, we want to lower
+ * the power in Standby mode.
+ */
+ mx6sl_standy_saving_set
+
+no_analog_savings:
+
/****************************************************************
save resume pointer into SRC_GPR1
****************************************************************/
@@ -832,13 +1172,14 @@ save resume pointer into SRC_GPR1
ldr r1, =SRC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
str r3, [r1, #SRC_GPR1_OFFSET]
+
#ifdef CONFIG_MX6_INTER_LDO_BYPASS
ldr r1, =ANATOP_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
- ldr r3, [r1, #0x140]
- bic r3, r3, #0x1f
- orr r3, r3, #0x1e
- str r3, [r1, #0x140]
+ ldr r4, [r1, #0x140]
+ bic r4, r4, #0x1f
+ orr r4, r4, #0x1e
+ str r4, [r1, #0x140]
#endif
/****************************************************************
execute a wfi instruction to let SOC go into stop mode.
@@ -863,11 +1204,26 @@ system immediately.
#endif
mov r0, r2 /* get suspend_iram_base */
- add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
ldmea r0!, {r12} @ get cpu type to make ddr io
@ offset right
+ ldmea r0!, {r11} @ standby or mem
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_restore
+
+ cmp r11, #0x1
+ bne no_analog_restore
+
+ ldr r3, =CCM_BASE_ADDR
+ add r3, r3, #PERIPBASE_VIRT
+
+ /* Restore the analog settings. */
+ mx6sl_standby_savings_restore
+
+no_analog_restore:
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
@@ -882,8 +1238,46 @@ dl_io_restore:
b ddr_io_restore_done
sl_io_restore:
sl_ddr_io_restore
+ ldr r1, =MMDC_P0_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+fifo_reset1_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+fifo_reset2_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset2_wait
ddr_io_restore_done:
+ /* Ensure DDR exits self-refresh. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r1, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r1, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r1, #0x404]
+
/* Add enough nops so that the
* prefetcher will not get instructions
* from DDR before its IO pads
@@ -930,6 +1324,7 @@ when SOC exit stop mode, arm core restart from here, currently
are running with MMU off.
****************************************************************/
resume:
+
#ifdef CONFIG_MX6_INTER_LDO_BYPASS
ldr r1, =ANATOP_BASE_ADDR
ldr r3, [r1, #0x140]
@@ -954,6 +1349,22 @@ resume:
ldmea r0!, {r12} @ get cpu type
+ ldmea r0!, {r11} @ standby or mem
+
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_restore1
+
+ cmp r11, #0x1
+ bne no_analog_restore1
+
+ ldr r1, =ANATOP_BASE_ADDR
+ ldr r3, =CCM_BASE_ADDR
+
+ /* Restore the analog settings. */
+ mx6sl_standby_pg_savings_restore
+
+no_analog_restore1:
/* Restore DDR IO */
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
@@ -968,8 +1379,44 @@ dl_io_dsm_restore:
b ddr_io_restore_dsm_done
sl_io_dsm_restore:
sl_ddr_io_restore
+ ldr r1, =MMDC_P0_BASE_ADDR
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+dsm_fifo_reset1_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne dsm_fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+dsm_fifo_reset2_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne dsm_fifo_reset2_wait
ddr_io_restore_dsm_done:
+ /* Ensure DDR exits self-refresh. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r1, #0x404]
+
+poll_dvfs_clear_2:
+ ldr r6, [r1, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_2
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r1, #0x404]
#ifdef CONFIG_CACHE_L2X0
ldr r2, =L2_BASE_ADDR
@@ -1084,11 +1531,11 @@ restore control register to enable cache
#endif
mov r8, lr
- push {r0}
+ push {r0-r12}
/* Set up the per-CPU stacks */
bl cpu_init
- pop {r0}
+ pop {r0-r12}
/*
* Restore the MMU table entry that was modified for
diff --git a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
index 134700a6d200..5cf34073bdc1 100644
--- a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
+++ b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
@@ -40,13 +40,13 @@
#define PFUZE100_I2C_ADDR (0x08)
/*SWBST*/
#define PFUZE100_SW1ASTANDBY 33
-#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) /* 925mV */
#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1BSTANDBY 40
-#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) /* 925mV */
#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1CSTANDBY 47
-#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) /* 925mV */
#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW2STANDBY 54
#define PFUZE100_SW2STANDBY_STBY_VAL 0x0
diff --git a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
index ee66541f8bff..981d149d7aee 100644
--- a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
+++ b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
@@ -40,13 +40,13 @@
#define PFUZE100_I2C_ADDR (0x08)
/*SWBST*/
#define PFUZE100_SW1ASTANDBY 33
-#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) /* 925mv */
#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1BSTANDBY 40
-#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) /* 925mv */
#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1CSTANDBY 47
-#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) /* 925mv */
#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW2STANDBY 54
#define PFUZE100_SW2STANDBY_STBY_VAL 0x0
@@ -143,7 +143,7 @@ static struct regulator_consumer_supply vgen5_consumers[] = {
};
static struct regulator_consumer_supply vgen6_consumers[] = {
{
- .supply = "VGEN6_3V3",
+ .supply = "VGEN6_2V8",
}
};
diff --git a/arch/arm/mach-mx6/mx6sl_wfi.S b/arch/arm/mach-mx6/mx6sl_wfi.S
index 89fe4e292352..dc4107dff7e8 100644
--- a/arch/arm/mach-mx6/mx6sl_wfi.S
+++ b/arch/arm/mach-mx6/mx6sl_wfi.S
@@ -235,15 +235,53 @@ mmdc_podf:
/* Set the DDR IO in LPM state. */
sl_ddr_io_set_lpm
- /* Set AHB to 8MHz., AXI to 3MHz */
- /* We want to ensure IPG_PERCLK to AHB
- * clk ratio is 1:2.5
+ /* Check if none of the PLLs are
+ * locked, except PLL1 which will get
+ * bypassed below.
+ * We should not be here if PLL2 is not
+ * bypassed.
*/
- /* Store the AXI/AHB podfs. */
+ ldr r7, =1
+ /* USB1 PLL3 */
+ ldr r6, [r3, #0x10]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* USB2 PLL7 */
+ ldr r6, [r3, #0x20]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* Audio PLL4 */
+ ldr r6, [r3, #0x70]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* Video PLL5 */
+ ldr r6, [r3, #0xA0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* ENET PLL8 */
+ ldr r6, [r3, #0xE0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ b cont
+
+no_analog_saving:
+ ldr r7, =0
+
+cont:
+ /*Set the AHB to 3MHz. AXI to 3MHz. */
ldr r9, [r2, #0x14]
mov r6, r9
- bic r6, r6, #0x1c00
- orr r6, r6, #0x800
+ orr r6, r6, #0x1c00
orr r6, r6, #0x70000
str r6, [r2, #0x14]
@@ -271,7 +309,7 @@ ahb_podf:
str r6, [r3, #0x04]
/* Set the ARM PODF to divide by 8. */
- /* IPG is at 4MHz here, we need ARM to
+ /* IPG is at 1.5MHz here, we need ARM to
* run at the 12:5 ratio (WAIT mode issue).
*/
ldr r6, =0x7
@@ -283,9 +321,62 @@ podf_loop:
cmp r6, #0x0
bne podf_loop
- /* Now do WFI. */
- dsb
+ /* Check if we can save some
+ * in the Analog section.
+ */
+ cmp r7, #0x1
+ bne do_wfi
+
+ /* Disable 1p1 brown out. */
+ ldr r6, [r3, #0x110]
+ bic r6, r6, #0x2
+ str r6, [r3, #0x110]
+
+ /* Enable the weak 2P5 */
+ ldr r6, [r3, #0x130]
+ orr r6, r6, #0x40000
+ str r6, [r3, #0x130]
+
+ /*Disable main 2p5. */
+ ldr r6, [r3, #0x130]
+ bic r6, r6, #0x1
+ str r6, [r3, #0x130]
+
+ /* Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ /* Enable low power bandgap */
+ ldr r6, [r3, #0x260]
+ orr r6, r6, #0x20
+ str r6, [r3, #0x260]
+
+ /* turn off the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r3, #0x260]
+ orr r6, r6, #0x80
+ str r6, [r3, #0x260]
+
+ /* Clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0x8
+ str r6, [r3, #0x150]
+
+ /*Power down the regular bandgap. */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0x1
+ str r6, [r3, #0x150]
+do_wfi:
+ /* Now do WFI. */
wfi
/* Set original ARM PODF back. */
@@ -297,6 +388,60 @@ podf_loop1:
cmp r6, #0x0
bne podf_loop1
+ /* Check if powered down
+ * analog components.
+ */
+ cmp r7, #0x1
+ bne skip_analog_restore
+
+ /*Power up the regular bandgap. */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0x1
+ str r6, [r3, #0x150]
+
+ /* turn on the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r3, #0x260]
+ bic r6, r6, #0x80
+ str r6, [r3, #0x260]
+
+ /* Disable the low power bandgap */
+ ldr r6, [r3, #0x260]
+ bic r6, r6, #0x20
+ str r6, [r3, #0x260]
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r3, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r3, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5:
+ ldr r6, [r3, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r3, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r3, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r3, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r3, #0x110]
+
+skip_analog_restore:
+
/* Power up PLL1 and un-bypass it. */
ldr r6, =(1 << 12)
str r6, [r3, #0x08]
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
index 45b2e6fffbeb..faf1a59ec2d6 100644
--- a/arch/arm/mach-mx6/pm.c
+++ b/arch/arm/mach-mx6/pm.c
@@ -73,7 +73,6 @@ static struct clk *cpu_clk;
static struct clk *axi_clk;
static struct clk *periph_clk;
static struct clk *axi_org_parent;
-static struct clk *gpu2d_core_clk;
static struct clk *pll3_usb_otg_main_clk;
static struct pm_platform_data *pm_data;
@@ -114,7 +113,6 @@ static u32 ccm_analog_pll3_480;
static u32 ccm_anadig_ana_misc2;
static bool usb_vbus_wakeup_enabled;
-
/*
* The USB VBUS wakeup should be disabled to avoid vbus wake system
* up due to vbus comparator is closed at weak 2p5 mode.
@@ -178,85 +176,6 @@ static void usb_power_up_handler(void)
}
}
-static void gpu_power_down(void)
-{
- int reg;
-
- /* enable power down request */
- reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- /* power down request */
- reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
- /* disable clocks */
- __raw_writel(ccgr1 &
- ~MXC_CCM_CCGRx_CG12_MASK &
- ~MXC_CCM_CCGRx_CG13_MASK, MXC_CCM_CCGR1);
- __raw_writel(ccgr3 & ~MXC_CCM_CCGRx_CG15_MASK, MXC_CCM_CCGR3);
- __raw_writel(ccgr6 & ~MXC_CCM_CCGRx_CG7_MASK, MXC_CCM_CCGR6);
- /* power off pu */
- reg = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
- reg &= ~0x0003fe00;
- __raw_writel(reg, anatop_base + ANATOP_REG_CORE_OFFSET);
-}
-
-static void gpu_power_up(void)
-{
- int reg;
- int i;
- /* power on pu */
- reg = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
- reg &= ~0x0003fe00;
- reg |= 0x10 << 9; /* 1.1v */
- __raw_writel(reg, anatop_base + ANATOP_REG_CORE_OFFSET);
- mdelay(10);
-
- /* enable clocks */
- /* PLL2 PFD0 and PFD1 clock enable */
- __raw_writel(ccm_analog_pfd528 &
- ~ANADIG_PFD0_CLKGATE &
- ~ANADIG_PFD1_CLKGATE, PFD_528_BASE_ADDR);
-
- /* PLL3 480M clock enable which may be used by gpu2d*/
- if (clk_get_parent(gpu2d_core_clk) == pll3_usb_otg_main_clk) {
- __raw_writel(ccm_analog_pll3_480 |
- ANADIG_PLL_POWER_DOWN, PLL3_480_USB1_BASE_ADDR);
- __raw_writel(ccm_anadig_ana_misc2 &
- (~BM_ANADIG_ANA_MISC2_CONTROL0),
- MXC_PLL_BASE + HW_ANADIG_ANA_MISC2);
- for (i = 0; i < 100; i++) {
- if (!(__raw_readl(PLL3_480_USB1_BASE_ADDR) & ANADIG_PLL_LOCK))
- udelay(1);
- else
- break;
- }
- __raw_writel((ccm_analog_pll3_480 & (~ANADIG_PLL_BYPASS)) |
- ANADIG_PLL_ENABLE | ANADIG_PLL_POWER_DOWN,
- PLL3_480_USB1_BASE_ADDR);
- }
- /* gpu3d and gpu2d clock enable */
- __raw_writel(ccgr1 |
- MXC_CCM_CCGRx_CG12_MASK |
- MXC_CCM_CCGRx_CG13_MASK, MXC_CCM_CCGR1);
- /* tzasrc1 clock enable for gpu3d core clock */
- __raw_writel(ccgr2 | MXC_CCM_CCGRx_CG11_MASK, MXC_CCM_CCGR2);
- /* openvgaxi clock enable, mmdc_core_ipg_clk_p0 clock and
- mmdc_core_aclk_fast_core_p0 clock enable for gpu3d core clock */
- __raw_writel(ccgr3 |
- MXC_CCM_CCGRx_CG15_MASK |
- MXC_CCM_CCGRx_CG12_MASK |
- MXC_CCM_CCGRx_CG10_MASK, MXC_CCM_CCGR3);
- /* vpu clock enable */
- __raw_writel(ccgr6 | MXC_CCM_CCGRx_CG7_MASK, MXC_CCM_CCGR6);
-
- /* enable power up request */
- reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- /* power up request */
- reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
- __raw_writel(reg | 0x2, gpc_base + GPC_CNTR_OFFSET);
- udelay(10);
-}
static void disp_power_down(void)
{
@@ -266,12 +185,32 @@ static void disp_power_down(void)
__raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
__raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET);
+
+ /* Disable EPDC/LCDIF pix clock, and EPDC/LCDIF/PXP axi clock */
+ __raw_writel(ccgr3 &
+ ~MXC_CCM_CCGRx_CG5_MASK &
+ ~MXC_CCM_CCGRx_CG4_MASK &
+ ~MXC_CCM_CCGRx_CG3_MASK &
+ ~MXC_CCM_CCGRx_CG2_MASK &
+ ~MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
+
}
}
static void disp_power_up(void)
{
if (cpu_is_mx6sl()) {
+ /*
+ * Need to enable EPDC/LCDIF pix clock, and
+ * EPDC/LCDIF/PXP axi clock before power up.
+ */
+ __raw_writel(ccgr3 |
+ MXC_CCM_CCGRx_CG5_MASK |
+ MXC_CCM_CCGRx_CG4_MASK |
+ MXC_CCM_CCGRx_CG3_MASK |
+ MXC_CCM_CCGRx_CG2_MASK |
+ MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
+
__raw_writel(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
__raw_writel(0x20, gpc_base + GPC_CNTR_OFFSET);
__raw_writel(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
@@ -343,6 +282,7 @@ static int mx6_suspend_enter(suspend_state_t state)
unsigned int cpu_type;
struct gic_dist_state gds;
struct gic_cpu_state gcs;
+ bool arm_pg = false;
if (cpu_is_mx6q())
cpu_type = MXC_CPU_MX6Q;
@@ -377,13 +317,19 @@ static int mx6_suspend_enter(suspend_state_t state)
switch (state) {
case PM_SUSPEND_MEM:
- gpu_power_down();
disp_power_down();
usb_power_down_handler();
mxc_cpu_lp_set(ARM_POWER_OFF);
+ arm_pg = true;
break;
case PM_SUSPEND_STANDBY:
- mxc_cpu_lp_set(STOP_POWER_OFF);
+ if (cpu_is_mx6sl()) {
+ disp_power_down();
+ usb_power_down_handler();
+ mxc_cpu_lp_set(STOP_XTAL_ON);
+ arm_pg = true;
+ } else
+ mxc_cpu_lp_set(STOP_POWER_OFF);
break;
default:
return -EINVAL;
@@ -399,7 +345,7 @@ static int mx6_suspend_enter(suspend_state_t state)
local_flush_tlb_all();
flush_cache_all();
- if (state == PM_SUSPEND_MEM) {
+ if (arm_pg) {
/* preserve gic state */
save_gic_dist_state(0, &gds);
save_gic_cpu_state(0, &gcs);
@@ -408,17 +354,21 @@ static int mx6_suspend_enter(suspend_state_t state)
suspend_in_iram(state, (unsigned long)iram_paddr,
(unsigned long)suspend_iram_base, cpu_type);
- if (state == PM_SUSPEND_MEM) {
+ if (arm_pg) {
/* restore gic registers */
restore_gic_dist_state(0, &gds);
restore_gic_cpu_state(0, &gcs);
+ }
+ if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl())) {
usb_power_up_handler();
disp_power_up();
- gpu_power_up();
}
mx6_suspend_restore();
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base + HW_ANADIG_ANA_MISC0_CLR);
+
if (pm_data && pm_data->suspend_exit)
pm_data->suspend_exit();
} else {
@@ -517,10 +467,10 @@ static int __init pm_init(void)
suspend_set_ops(&mx6_suspend_ops);
/* Move suspend routine into iRAM */
- cpaddr = (unsigned long)iram_alloc(SZ_4K, &iram_paddr);
+ cpaddr = (unsigned long)iram_alloc(SZ_8K, &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_4K,
+ suspend_iram_base = __arm_ioremap(iram_paddr, SZ_8K,
MT_MEMORY_NONCACHED);
pr_info("cpaddr = %x suspend_iram_base=%x\n",
(unsigned int)cpaddr, (unsigned int)suspend_iram_base);
@@ -529,7 +479,7 @@ static int __init pm_init(void)
* Need to run the suspend code from IRAM as the DDR needs
* to be put into low power mode manually.
*/
- memcpy((void *)cpaddr, mx6_suspend, SZ_4K);
+ memcpy((void *)cpaddr, mx6_suspend, SZ_8K);
suspend_in_iram = (void *)suspend_iram_base;
@@ -548,11 +498,6 @@ static int __init pm_init(void)
printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__);
return PTR_ERR(periph_clk);
}
- gpu2d_core_clk = clk_get(NULL, "gpu2d_clk");
- if (IS_ERR(gpu2d_core_clk)) {
- printk(KERN_DEBUG "%s: failed to get gpu2d_clk\n", __func__);
- return PTR_ERR(periph_clk);
- }
pll3_usb_otg_main_clk = clk_get(NULL, "pll3_main_clk");
if (IS_ERR(pll3_usb_otg_main_clk)) {
printk(KERN_DEBUG "%s: failed to get pll3_main_clk\n", __func__);
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
index 800c7cc4e8bd..533d4f5dbfab 100644
--- a/arch/arm/mach-mx6/system.c
+++ b/arch/arm/mach-mx6/system.c
@@ -51,6 +51,7 @@
extern unsigned int gpc_wake_irq[4];
static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+static struct clk *ddr_clk;
volatile unsigned int num_cpu_idle;
volatile unsigned int num_cpu_idle_lock = 0x0;
@@ -132,8 +133,16 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
stop_mode = 2;
}
break;
- case STOP_POWER_ON:
+ case STOP_XTAL_ON:
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ stop_mode = 3;
break;
default:
@@ -146,7 +155,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
/* Power down and power up sequence */
__raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
__raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
- if (stop_mode == 2) {
+ if (stop_mode >= 2) {
/* dormant mode, need to power off the arm core */
__raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
if (cpu_is_mx6q() || cpu_is_mx6dl()) {
@@ -171,38 +180,48 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
HW_ANADIG_REG_CORE);
}
} else {
- /* Disable VDDHIGH_IN to VDDSNVS_IN power path,
- * only used when VDDSNVS_IN is powered by dedicated
- * power rail */
- anatop_val = __raw_readl(anatop_base +
- HW_ANADIG_ANA_MISC0);
- anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN;
- __raw_writel(anatop_val, anatop_base +
- HW_ANADIG_ANA_MISC0);
- /* We need to allow the memories to be clock gated
- * in STOP mode, else the power consumption will
- * be very high. */
- reg = __raw_readl(MXC_CCM_CGPR);
- reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK;
- __raw_writel(reg, MXC_CCM_CGPR);
+ if (stop_mode == 2) {
+ /* Disable VDDHIGH_IN to VDDSNVS_IN
+ * power path, only used when VDDSNVS_IN
+ * is powered by dedicated
+ * power rail */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ /* Need to enable pull down if 2P5 is disabled */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_REG_2P5);
+ anatop_val |= BM_ANADIG_REG_2P5_ENABLE_PULLDOWN;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_REG_2P5);
+ }
}
/* DL's TO1.0 can't support DSM mode due to ipg glitch */
- if (mx6dl_revision() != IMX_CHIP_REVISION_1_0)
+ if ((mx6dl_revision() != IMX_CHIP_REVISION_1_0)
+ && stop_mode != 3)
__raw_writel(__raw_readl(MXC_CCM_CCR) |
MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR);
- /* Make sure we clear WB_COUNT and re-config it */
- __raw_writel(__raw_readl(MXC_CCM_CCR) &
- (~MXC_CCM_CCR_WB_COUNT_MASK) &
- (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR);
- udelay(80);
- /* Reconfigurate WB and RBC counter */
- __raw_writel(__raw_readl(MXC_CCM_CCR) |
- (0x1 << MXC_CCM_CCR_WB_COUNT_OFFSET) |
- (0x20 << MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET), MXC_CCM_CCR);
-
- /* Set WB_PER enable */
- ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM;
+ if (stop_mode != 3) {
+ /* Make sure we clear WB_COUNT
+ * and re-config it.
+ */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) &
+ (~MXC_CCM_CCR_WB_COUNT_MASK) &
+ (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR);
+ udelay(80);
+ /* Reconfigurate WB and RBC counter, need to set WB counter
+ * to 0x7 to make sure it work normally */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) |
+ (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET) |
+ (0x20 << MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET),
+ MXC_CCM_CCR);
+
+ /* Set WB_PER enable */
+ ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM;
+ }
}
if (cpu_is_mx6sl() ||
(mx6q_revision() > IMX_CHIP_REVISION_1_1) ||
@@ -253,7 +272,14 @@ void arch_idle_single_core(void)
ca9_do_idle();
} else {
if (low_bus_freq_mode || audio_bus_freq_mode) {
- if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ u32 ddr_usecount;
+ if (ddr_clk == NULL)
+ ddr_clk = clk_get(NULL ,
+ "mmdc_ch0_axi");
+ ddr_usecount = clk_get_usecount(ddr_clk);
+
+ if (cpu_is_mx6sl() && low_bus_freq_mode
+ && ddr_usecount == 1) {
/* In this mode PLL2 i already in bypass,
* ARM is sourced from PLL1. The code in IRAM
* will set ARM to be sourced from STEP_CLK
@@ -272,17 +298,41 @@ void arch_idle_single_core(void)
* is at 12MHz. This is valid for audio mode on
* MX6SL, and all low power modes on MX6DLS.
*/
- /* PLL1_SW_CLK is sourced from PLL2_PFD2400MHz
- * at this point. Move it to bypassed PLL1.
- */
- reg = __raw_readl(MXC_CCM_CCSR);
- reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- __raw_writel(reg, MXC_CCM_CCSR);
-
+ if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ /* ARM is from PLL1, need to switch to
+ * STEP_CLK sourced from 24MHz.
+ */
+ /* Swtich STEP_CLK to 24MHz. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_STEP_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set PLL1_SW_CLK to be from
+ *STEP_CLK.
+ */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ } else {
+ /* PLL1_SW_CLK is sourced from
+ * PLL2_PFD2_400MHz at this point.
+ * Move it to bypassed PLL1.
+ */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
ca9_do_idle();
- reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- __raw_writel(reg, MXC_CCM_CCSR);
+ if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ /* Set PLL1_SW_CLK to be from PLL1 */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ } else {
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
}
} else {
/*
diff --git a/arch/arm/mach-mx6/usb.h b/arch/arm/mach-mx6/usb.h
index 6914246826f6..f796e7dad87c 100644
--- a/arch/arm/mach-mx6/usb.h
+++ b/arch/arm/mach-mx6/usb.h
@@ -30,9 +30,6 @@ extern void gpio_usbotg_utmi_inactive(void);
extern void __init mx6_usb_dr_init(void);
extern bool usb_icbug_swfix_need(void);
-extern int usb_stop_mode_refcount(bool enable);
-extern void usb_stop_mode_lock(void);
-extern void usb_stop_mode_unlock(void);
extern void __init mx6_usb_h2_init(void);
extern void __init mx6_usb_h3_init(void);
diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c
index 8fe9700a658f..7b79d98c7d5c 100644
--- a/arch/arm/mach-mx6/usb_dr.c
+++ b/arch/arm/mach-mx6/usb_dr.c
@@ -173,9 +173,6 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
static int usbotg_init_ext(struct platform_device *pdev)
{
struct clk *usb_clk;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
-#endif
u32 ret;
/* at mx6q: this clock is AHB clock for usb core */
@@ -201,12 +198,6 @@ static int usbotg_init_ext(struct platform_device *pdev)
mdelay(3);
}
otg_used++;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(true) == 1)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
- usb_stop_mode_unlock();
-#endif
return ret;
}
@@ -214,9 +205,6 @@ 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;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
-#endif
clk_disable(usb_phy1_clk);
clk_put(usb_phy1_clk);
@@ -226,12 +214,6 @@ static void usbotg_uninit_ext(struct platform_device *pdev)
usbotg_uninit(pdata);
otg_used--;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(false) == 0)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR);
- usb_stop_mode_unlock();
-#endif
}
static void usbotg_clock_gate(bool on)
@@ -247,6 +229,13 @@ static void usbotg_clock_gate(bool on)
pr_debug("usb_oh3_clk:%d, usb_phy_clk1_ref_count:%d\n", clk_get_usecount(usb_oh3_clk), clk_get_usecount(usb_phy1_clk));
}
+static void dr_platform_phy_power_on(void)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ 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;
@@ -643,6 +632,7 @@ void __init mx6_usb_dr_init(void)
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;
+ 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;
#endif
@@ -657,6 +647,7 @@ void __init mx6_usb_dr_init(void)
dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
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;
#endif
diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c
index bece29f7d44b..f86a4f42b0bd 100644
--- a/arch/arm/mach-mx6/usb_h1.c
+++ b/arch/arm/mach-mx6/usb_h1.c
@@ -90,6 +90,13 @@ static void usbh1_internal_phy_clock_gate(bool on)
}
}
+static void usbh1_platform_phy_power_on(void)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+}
+
static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
{
u32 tmp;
@@ -134,7 +141,6 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev)
{
int ret;
struct clk *usb_clk;
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
usb_clk = clk_get(NULL, "usboh3_clk");
clk_enable(usb_clk);
usb_oh3_clk = usb_clk;
@@ -146,25 +152,19 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev)
}
usbh1_internal_phy_clock_gate(true);
usb_phy_enable(pdev->dev.platform_data);
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(true) == 1)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
- usb_stop_mode_unlock();
+
return 0;
}
static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+
fsl_usb_host_uninit(pdata);
clk_disable(usb_oh3_clk);
clk_put(usb_oh3_clk);
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(false) == 0)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR);
- usb_stop_mode_unlock();
+
}
static void usbh1_clock_gate(bool on)
@@ -374,6 +374,7 @@ static struct fsl_usb2_platform_data usbh1_config = {
.phy_lowpower_suspend = _phy_lowpower_suspend,
.is_wakeup_event = _is_usbh1_wakeup,
.wakeup_handler = h1_wakeup_handler,
+ .platform_phy_power_on = usbh1_platform_phy_power_on,
.transceiver = "utmi",
.phy_regs = USB_PHY1_BASE_ADDR,
};