From: Danny Nold Date: Thu, 9 Feb 2012 03:28:42 +0000 (-0600) Subject: ENGR00174106-1 - EPDC fb: Support EPDC on MX 6DL/S X-Git-Tag: v3.0.35-fsl~1466 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=26fafc85e2a60727e61203ad2ca307d781838471;p=karo-tx-linux.git ENGR00174106-1 - EPDC fb: Support EPDC on MX 6DL/S - Added EPDC and EPD PMIC (Maxim 17135) to MX6Q ARM2 board file - Added EPDC-related IOMUX and GPIO settings - Added EPDC clock configuration settings to clock file - Updated config files with EPDC and Maxim 17135 config entries Signed-off-by: Danny Nold --- diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig index 8f00d362cc15..5d9d768b34c2 100644 --- a/arch/arm/configs/imx6_defconfig +++ b/arch/arm/configs/imx6_defconfig @@ -275,6 +275,7 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_VIIM=y CONFIG_IMX_HAVE_PLATFORM_PERFMON=y CONFIG_IMX_HAVE_PLATFORM_LDB=y CONFIG_IMX_HAVE_PLATFORM_IMX_PXP=y +CONFIG_IMX_HAVE_PLATFORM_IMX_EPDC=y CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y CONFIG_IMX_HAVE_PLATFORM_VIV_GPU=y CONFIG_IMX_HAVE_PLATFORM_MXC_HDMI=y @@ -1443,7 +1444,7 @@ CONFIG_MFD_PFUZE=y # CONFIG_EZX_PCAP is not set # CONFIG_MFD_WL1273_CORE is not set # CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_MAX17135 is not set +CONFIG_MFD_MAX17135=y CONFIG_MFD_MXC_HDMI=y CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set @@ -1466,6 +1467,7 @@ CONFIG_REGULATOR_PFUZE100=y # CONFIG_REGULATOR_AD5398 is not set CONFIG_REGULATOR_ANATOP=y # CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_MAX17135=y CONFIG_MEDIA_SUPPORT=y # diff --git a/arch/arm/configs/imx6_updater_defconfig b/arch/arm/configs/imx6_updater_defconfig index d0d8e7607563..b03276bf28ba 100644 --- a/arch/arm/configs/imx6_updater_defconfig +++ b/arch/arm/configs/imx6_updater_defconfig @@ -1217,7 +1217,7 @@ CONFIG_MFD_PFUZE=y # CONFIG_EZX_PCAP is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_MAX17135 is not set +CONFIG_MFD_MAX17135=y CONFIG_MFD_MXC_HDMI=y CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set @@ -1238,8 +1238,9 @@ CONFIG_REGULATOR_PFUZE100=y # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_AD5398 is not set -# CONFIG_REGULATOR_TPS6524X is not set CONFIG_REGULATOR_ANATOP=y +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_MAX17135=y CONFIG_MEDIA_SUPPORT=y # diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index aa081b6ce0c1..3c083feb1742 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -57,6 +57,7 @@ config MACH_MX6Q_ARM2 select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2 select IMX_HAVE_PLATFORM_PERFMON select IMX_HAVE_PLATFORM_MXC_MLB + select IMX_HAVE_PLATFORM_IMX_EPDC select IMX_HAVE_PLATFORM_IMX_PXP help Include support for i.MX 6Quad Armadillo2 platform. This includes specific diff --git a/arch/arm/mach-mx6/board-mx6dl_arm2.h b/arch/arm/mach-mx6/board-mx6dl_arm2.h index 9261a28fb6d1..4528da53694a 100644 --- a/arch/arm/mach-mx6/board-mx6dl_arm2.h +++ b/arch/arm/mach-mx6/board-mx6dl_arm2.h @@ -187,6 +187,11 @@ static iomux_v3_cfg_t mx6dl_arm2_pads[] = { MX6DL_PAD_GPIO_3__MLB_MLBCLK, MX6DL_PAD_GPIO_6__MLB_MLBSIG, MX6DL_PAD_GPIO_2__MLB_MLBDAT, + + /* EPDC pins */ + MX6DL_PAD_EIM_A17__GPIO_2_21, + MX6DL_PAD_EIM_D17__GPIO_3_17, + MX6DL_PAD_EIM_A18__GPIO_2_20, }; static iomux_v3_cfg_t mx6dl_arm2_i2c3_pads[] = { diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index 4fa511c8cdf2..71161e82185f 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -97,6 +98,50 @@ #define MX6_ARM2_CAN1_EN IMX_GPIO_NR(7, 13) #define MX6_ARM2_MAX7310_1_BASE_ADDR IMX_GPIO_NR(8, 0) #define MX6_ARM2_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8) +#define MX6DL_ARM2_EPDC_SDDO_0 IMX_GPIO_NR(2, 22) +#define MX6DL_ARM2_EPDC_SDDO_1 IMX_GPIO_NR(3, 10) +#define MX6DL_ARM2_EPDC_SDDO_2 IMX_GPIO_NR(3, 12) +#define MX6DL_ARM2_EPDC_SDDO_3 IMX_GPIO_NR(3, 11) +#define MX6DL_ARM2_EPDC_SDDO_4 IMX_GPIO_NR(2, 27) +#define MX6DL_ARM2_EPDC_SDDO_5 IMX_GPIO_NR(2, 30) +#define MX6DL_ARM2_EPDC_SDDO_6 IMX_GPIO_NR(2, 23) +#define MX6DL_ARM2_EPDC_SDDO_7 IMX_GPIO_NR(2, 26) +#define MX6DL_ARM2_EPDC_SDDO_8 IMX_GPIO_NR(2, 24) +#define MX6DL_ARM2_EPDC_SDDO_9 IMX_GPIO_NR(3, 15) +#define MX6DL_ARM2_EPDC_SDDO_10 IMX_GPIO_NR(3, 16) +#define MX6DL_ARM2_EPDC_SDDO_11 IMX_GPIO_NR(3, 23) +#define MX6DL_ARM2_EPDC_SDDO_12 IMX_GPIO_NR(3, 19) +#define MX6DL_ARM2_EPDC_SDDO_13 IMX_GPIO_NR(3, 13) +#define MX6DL_ARM2_EPDC_SDDO_14 IMX_GPIO_NR(3, 14) +#define MX6DL_ARM2_EPDC_SDDO_15 IMX_GPIO_NR(5, 2) +#define MX6DL_ARM2_EPDC_GDCLK IMX_GPIO_NR(2, 17) +#define MX6DL_ARM2_EPDC_GDSP IMX_GPIO_NR(2, 16) +#define MX6DL_ARM2_EPDC_GDOE IMX_GPIO_NR(6, 6) +#define MX6DL_ARM2_EPDC_GDRL IMX_GPIO_NR(5, 4) +#define MX6DL_ARM2_EPDC_SDCLK IMX_GPIO_NR(3, 31) +#define MX6DL_ARM2_EPDC_SDOEZ IMX_GPIO_NR(3, 30) +#define MX6DL_ARM2_EPDC_SDOED IMX_GPIO_NR(3, 26) +#define MX6DL_ARM2_EPDC_SDOE IMX_GPIO_NR(3, 27) +#define MX6DL_ARM2_EPDC_SDLE IMX_GPIO_NR(3, 1) +#define MX6DL_ARM2_EPDC_SDCLKN IMX_GPIO_NR(3, 0) +#define MX6DL_ARM2_EPDC_SDSHR IMX_GPIO_NR(2, 29) +#define MX6DL_ARM2_EPDC_PWRCOM IMX_GPIO_NR(2, 28) +#define MX6DL_ARM2_EPDC_PWRSTAT IMX_GPIO_NR(2, 21) +#define MX6DL_ARM2_EPDC_PWRCTRL0 IMX_GPIO_NR(2, 20) +#define MX6DL_ARM2_EPDC_PWRCTRL1 IMX_GPIO_NR(2, 19) +#define MX6DL_ARM2_EPDC_PWRCTRL2 IMX_GPIO_NR(2, 18) +#define MX6DL_ARM2_EPDC_PWRCTRL3 IMX_GPIO_NR(3, 28) +#define MX6DL_ARM2_EPDC_BDR0 IMX_GPIO_NR(3, 2) +#define MX6DL_ARM2_EPDC_BDR1 IMX_GPIO_NR(3, 3) +#define MX6DL_ARM2_EPDC_SDCE0 IMX_GPIO_NR(3, 4) +#define MX6DL_ARM2_EPDC_SDCE1 IMX_GPIO_NR(3, 5) +#define MX6DL_ARM2_EPDC_SDCE2 IMX_GPIO_NR(3, 6) +#define MX6DL_ARM2_EPDC_SDCE3 IMX_GPIO_NR(3, 7) +#define MX6DL_ARM2_EPDC_SDCE4 IMX_GPIO_NR(3, 8) +#define MX6DL_ARM2_EPDC_SDCE5 IMX_GPIO_NR(3, 9) +#define MX6DL_ARM2_EPDC_PMIC_WAKE IMX_GPIO_NR(2, 31) +#define MX6DL_ARM2_EPDC_PMIC_INT IMX_GPIO_NR(2, 25) +#define MX6DL_ARM2_EPDC_VCOM IMX_GPIO_NR(3, 17) #define MX6_ARM2_IO_EXP_GPIO1(x) (MX6_ARM2_MAX7310_1_BASE_ADDR + (x)) #define MX6_ARM2_IO_EXP_GPIO2(x) (MX6_ARM2_MAX7310_2_BASE_ADDR + (x)) @@ -117,6 +162,7 @@ extern struct regulator *(*get_cpu_regulator)(void); extern void (*put_cpu_regulator)(void); extern char *gp_reg_id; extern void mx6_cpu_regulator_init(void); +static int max17135_regulator_init(struct max17135 *max17135); enum sd_pad_mode { SD_PAD_MODE_LOW_SPEED, @@ -597,6 +643,175 @@ static struct fsl_mxc_camera_platform_data ov5640_mipi_data = { .io_init = mx6_mipi_sensor_io_init, }; +#define mV_to_uV(mV) (mV * 1000) +#define uV_to_mV(uV) (uV / 1000) +#define V_to_uV(V) (mV_to_uV(V * 1000)) +#define uV_to_V(uV) (uV_to_mV(uV) / 1000) + +static struct regulator_consumer_supply display_consumers[] = { + { + /* MAX17135 */ + .supply = "DISPLAY", + }, +}; + +static struct regulator_consumer_supply vcom_consumers[] = { + { + /* MAX17135 */ + .supply = "VCOM", + }, +}; + +static struct regulator_consumer_supply v3p3_consumers[] = { + { + /* MAX17135 */ + .supply = "V3P3", + }, +}; + +static struct regulator_init_data max17135_init_data[] = { + { + .constraints = { + .name = "DISPLAY", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(display_consumers), + .consumer_supplies = display_consumers, + }, { + .constraints = { + .name = "GVDD", + .min_uV = V_to_uV(20), + .max_uV = V_to_uV(20), + }, + }, { + .constraints = { + .name = "GVEE", + .min_uV = V_to_uV(-22), + .max_uV = V_to_uV(-22), + }, + }, { + .constraints = { + .name = "HVINN", + .min_uV = V_to_uV(-22), + .max_uV = V_to_uV(-22), + }, + }, { + .constraints = { + .name = "HVINP", + .min_uV = V_to_uV(20), + .max_uV = V_to_uV(20), + }, + }, { + .constraints = { + .name = "VCOM", + .min_uV = mV_to_uV(-4325), + .max_uV = mV_to_uV(-500), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(vcom_consumers), + .consumer_supplies = vcom_consumers, + }, { + .constraints = { + .name = "VNEG", + .min_uV = V_to_uV(-15), + .max_uV = V_to_uV(-15), + }, + }, { + .constraints = { + .name = "VPOS", + .min_uV = V_to_uV(15), + .max_uV = V_to_uV(15), + }, + }, { + .constraints = { + .name = "V3P3", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers), + .consumer_supplies = v3p3_consumers, + }, +}; + +static struct platform_device max17135_sensor_device = { + .name = "max17135_sensor", + .id = 0, +}; + +static struct max17135_platform_data max17135_pdata __initdata = { + .vneg_pwrup = 1, + .gvee_pwrup = 1, + .vpos_pwrup = 2, + .gvdd_pwrup = 1, + .gvdd_pwrdn = 1, + .vpos_pwrdn = 2, + .gvee_pwrdn = 1, + .vneg_pwrdn = 1, + .gpio_pmic_pwrgood = MX6DL_ARM2_EPDC_PWRSTAT, + .gpio_pmic_vcom_ctrl = MX6DL_ARM2_EPDC_VCOM, + .gpio_pmic_wakeup = MX6DL_ARM2_EPDC_PMIC_WAKE, + .gpio_pmic_v3p3 = MX6DL_ARM2_EPDC_PWRCTRL0, + .gpio_pmic_intr = MX6DL_ARM2_EPDC_PMIC_INT, + .regulator_init = max17135_init_data, + .init = max17135_regulator_init, +}; + +static int max17135_regulator_init(struct max17135 *max17135) +{ + struct max17135_platform_data *pdata = &max17135_pdata; + int i, ret; + + max17135->gvee_pwrup = pdata->gvee_pwrup; + max17135->vneg_pwrup = pdata->vneg_pwrup; + max17135->vpos_pwrup = pdata->vpos_pwrup; + max17135->gvdd_pwrup = pdata->gvdd_pwrup; + max17135->gvdd_pwrdn = pdata->gvdd_pwrdn; + max17135->vpos_pwrdn = pdata->vpos_pwrdn; + max17135->vneg_pwrdn = pdata->vneg_pwrdn; + max17135->gvee_pwrdn = pdata->gvee_pwrdn; + + max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup + + pdata->gvdd_pwrup + pdata->gvee_pwrup; + + max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood; + max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl; + max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup; + max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3; + max17135->gpio_pmic_intr = pdata->gpio_pmic_intr; + + gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake"); + gpio_direction_output(max17135->gpio_pmic_wakeup, 0); + + gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom"); + gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0); + + gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3"); + gpio_direction_output(max17135->gpio_pmic_v3p3, 0); + + gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int"); + gpio_direction_input(max17135->gpio_pmic_intr); + + gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat"); + gpio_direction_input(max17135->gpio_pmic_pwrgood); + + max17135->vcom_setup = false; + max17135->init_done = false; + + for (i = 0; i < MAX17135_NUM_REGULATORS; i++) { + ret = max17135_register_regulator(max17135, i, + &pdata->regulator_init[i]); + if (ret != 0) { + printk(KERN_ERR"max17135 regulator init failed: %d\n", + ret); + return ret; + } + } + + regulator_has_full_constraints(); + + return 0; +} + static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { { I2C_BOARD_INFO("cs42888", 0x48), @@ -623,6 +838,9 @@ static struct imxi2c_platform_data mx6_arm2_i2c2_data = { static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { { + I2C_BOARD_INFO("max17135", 0x48), + .platform_data = &max17135_pdata, + }, { I2C_BOARD_INFO("max7310", 0x1F), .platform_data = &max7310_platdata, }, { @@ -653,6 +871,309 @@ static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { }, }; +static int epdc_get_pins(void) +{ + int ret = 0; + + /* Claim GPIOs for EPDC pins - used during power up/down */ + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_0, "epdc_d0"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_1, "epdc_d1"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_2, "epdc_d2"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_3, "epdc_d3"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_4, "epdc_d4"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_5, "epdc_d5"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_6, "epdc_d6"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDDO_7, "epdc_d7"); + ret |= gpio_request(MX6DL_ARM2_EPDC_GDCLK, "epdc_gdclk"); + ret |= gpio_request(MX6DL_ARM2_EPDC_GDSP, "epdc_gdsp"); + ret |= gpio_request(MX6DL_ARM2_EPDC_GDOE, "epdc_gdoe"); + ret |= gpio_request(MX6DL_ARM2_EPDC_GDRL, "epdc_gdrl"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDCLK, "epdc_sdclk"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDOE, "epdc_sdoe"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDLE, "epdc_sdle"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDSHR, "epdc_sdshr"); + ret |= gpio_request(MX6DL_ARM2_EPDC_BDR0, "epdc_bdr0"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDCE0, "epdc_sdce0"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDCE1, "epdc_sdce1"); + ret |= gpio_request(MX6DL_ARM2_EPDC_SDCE2, "epdc_sdce2"); + + return ret; +} + +static void epdc_put_pins(void) +{ + gpio_free(MX6DL_ARM2_EPDC_SDDO_0); + gpio_free(MX6DL_ARM2_EPDC_SDDO_1); + gpio_free(MX6DL_ARM2_EPDC_SDDO_2); + gpio_free(MX6DL_ARM2_EPDC_SDDO_3); + gpio_free(MX6DL_ARM2_EPDC_SDDO_4); + gpio_free(MX6DL_ARM2_EPDC_SDDO_5); + gpio_free(MX6DL_ARM2_EPDC_SDDO_6); + gpio_free(MX6DL_ARM2_EPDC_SDDO_7); + gpio_free(MX6DL_ARM2_EPDC_GDCLK); + gpio_free(MX6DL_ARM2_EPDC_GDSP); + gpio_free(MX6DL_ARM2_EPDC_GDOE); + gpio_free(MX6DL_ARM2_EPDC_GDRL); + gpio_free(MX6DL_ARM2_EPDC_SDCLK); + gpio_free(MX6DL_ARM2_EPDC_SDOE); + gpio_free(MX6DL_ARM2_EPDC_SDLE); + gpio_free(MX6DL_ARM2_EPDC_SDSHR); + gpio_free(MX6DL_ARM2_EPDC_BDR0); + gpio_free(MX6DL_ARM2_EPDC_SDCE0); + gpio_free(MX6DL_ARM2_EPDC_SDCE1); + gpio_free(MX6DL_ARM2_EPDC_SDCE2); +} + +static iomux_v3_cfg_t mx6dl_epdc_pads_enabled[] = { + MX6DL_PAD_EIM_A16__EPDC_SDDO_0, + MX6DL_PAD_EIM_DA10__EPDC_SDDO_1, + MX6DL_PAD_EIM_DA12__EPDC_SDDO_2, + MX6DL_PAD_EIM_DA11__EPDC_SDDO_3, + MX6DL_PAD_EIM_LBA__EPDC_SDDO_4, + MX6DL_PAD_EIM_EB2__EPDC_SDDO_5, + MX6DL_PAD_EIM_CS0__EPDC_SDDO_6, + MX6DL_PAD_EIM_RW__EPDC_SDDO_7, + MX6DL_PAD_EIM_CS1__EPDC_SDDO_8, + MX6DL_PAD_EIM_DA15__EPDC_SDDO_9, + MX6DL_PAD_EIM_D16__EPDC_SDDO_10, + MX6DL_PAD_EIM_D23__EPDC_SDDO_11, + MX6DL_PAD_EIM_D19__EPDC_SDDO_12, + MX6DL_PAD_EIM_DA13__EPDC_SDDO_13, + MX6DL_PAD_EIM_DA14__EPDC_SDDO_14, + MX6DL_PAD_EIM_A25__EPDC_SDDO_15, + MX6DL_PAD_EIM_A21__EPDC_GDCLK, + MX6DL_PAD_EIM_A22__EPDC_GDSP, + MX6DL_PAD_EIM_A23__EPDC_GDOE, + MX6DL_PAD_EIM_A24__EPDC_GDRL, + MX6DL_PAD_EIM_D31__EPDC_SDCLK, + MX6DL_PAD_EIM_D27__EPDC_SDOE, + MX6DL_PAD_EIM_DA1__EPDC_SDLE, + MX6DL_PAD_EIM_EB1__EPDC_SDSHR, + MX6DL_PAD_EIM_DA2__EPDC_BDR_0, + MX6DL_PAD_EIM_DA4__EPDC_SDCE_0, + MX6DL_PAD_EIM_DA5__EPDC_SDCE_1, + MX6DL_PAD_EIM_DA6__EPDC_SDCE_2, +}; + +static iomux_v3_cfg_t mx6dl_epdc_pads_disabled[] = { + MX6DL_PAD_EIM_A16__GPIO_2_22, + MX6DL_PAD_EIM_DA10__GPIO_3_10, + MX6DL_PAD_EIM_DA12__GPIO_3_12, + MX6DL_PAD_EIM_DA11__GPIO_3_11, + MX6DL_PAD_EIM_LBA__GPIO_2_27, + MX6DL_PAD_EIM_EB2__GPIO_2_30, + MX6DL_PAD_EIM_CS0__GPIO_2_23, + MX6DL_PAD_EIM_RW__GPIO_2_26, + MX6DL_PAD_EIM_CS1__GPIO_2_24, + MX6DL_PAD_EIM_DA15__GPIO_3_15, + MX6DL_PAD_EIM_D16__GPIO_3_16, + MX6DL_PAD_EIM_D23__GPIO_3_23, + MX6DL_PAD_EIM_D19__GPIO_3_19, + MX6DL_PAD_EIM_DA13__GPIO_3_13, + MX6DL_PAD_EIM_DA14__GPIO_3_14, + MX6DL_PAD_EIM_A25__GPIO_5_2, + MX6DL_PAD_EIM_A21__GPIO_2_17, + MX6DL_PAD_EIM_A22__GPIO_2_16, + MX6DL_PAD_EIM_A23__GPIO_6_6, + MX6DL_PAD_EIM_A24__GPIO_5_4, + MX6DL_PAD_EIM_D31__GPIO_3_31, + MX6DL_PAD_EIM_D27__GPIO_3_27, + MX6DL_PAD_EIM_DA1__GPIO_3_1, + MX6DL_PAD_EIM_EB1__GPIO_2_29, + MX6DL_PAD_EIM_DA2__GPIO_3_2, + MX6DL_PAD_EIM_DA4__GPIO_3_4, + MX6DL_PAD_EIM_DA5__GPIO_3_5, + MX6DL_PAD_EIM_DA6__GPIO_3_6, +}; +static void epdc_enable_pins(void) +{ + /* Configure MUX settings to enable EPDC use */ + mxc_iomux_v3_setup_multiple_pads(mx6dl_epdc_pads_enabled, \ + ARRAY_SIZE(mx6dl_epdc_pads_enabled)); + + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_0); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_1); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_2); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_3); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_4); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_5); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_6); + gpio_direction_input(MX6DL_ARM2_EPDC_SDDO_7); + gpio_direction_input(MX6DL_ARM2_EPDC_GDCLK); + gpio_direction_input(MX6DL_ARM2_EPDC_GDSP); + gpio_direction_input(MX6DL_ARM2_EPDC_GDOE); + gpio_direction_input(MX6DL_ARM2_EPDC_GDRL); + gpio_direction_input(MX6DL_ARM2_EPDC_SDCLK); + gpio_direction_input(MX6DL_ARM2_EPDC_SDOE); + gpio_direction_input(MX6DL_ARM2_EPDC_SDLE); + gpio_direction_input(MX6DL_ARM2_EPDC_SDSHR); + gpio_direction_input(MX6DL_ARM2_EPDC_BDR0); + gpio_direction_input(MX6DL_ARM2_EPDC_SDCE0); + gpio_direction_input(MX6DL_ARM2_EPDC_SDCE1); + gpio_direction_input(MX6DL_ARM2_EPDC_SDCE2); +} + +static void epdc_disable_pins(void) +{ + /* Configure MUX settings for EPDC pins to + * GPIO and drive to 0. */ + mxc_iomux_v3_setup_multiple_pads(mx6dl_epdc_pads_disabled, \ + ARRAY_SIZE(mx6dl_epdc_pads_disabled)); + + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_0, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_1, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_2, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_3, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_4, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_5, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_6, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDDO_7, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_GDCLK, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_GDSP, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_GDOE, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_GDRL, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDCLK, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDOE, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDLE, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDSHR, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_BDR0, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDCE0, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDCE1, 0); + gpio_direction_output(MX6DL_ARM2_EPDC_SDCE2, 0); +} + +static struct fb_videomode e60_v110_mode = { + .name = "E60_V110", + .refresh = 50, + .xres = 800, + .yres = 600, + .pixclock = 18604700, + .left_margin = 8, + .right_margin = 178, + .upper_margin = 4, + .lower_margin = 10, + .hsync_len = 20, + .vsync_len = 4, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, +}; +static struct fb_videomode e60_v220_mode = { + .name = "E60_V220", + .refresh = 85, + .xres = 800, + .yres = 600, + .pixclock = 30000000, + .left_margin = 8, + .right_margin = 164, + .upper_margin = 4, + .lower_margin = 8, + .hsync_len = 4, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, + .refresh = 85, + .xres = 800, + .yres = 600, +}; +static struct fb_videomode e060scm_mode = { + .name = "E060SCM", + .refresh = 85, + .xres = 800, + .yres = 600, + .pixclock = 26666667, + .left_margin = 8, + .right_margin = 100, + .upper_margin = 4, + .lower_margin = 8, + .hsync_len = 4, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, +}; +static struct fb_videomode e97_v110_mode = { + .name = "E97_V110", + .refresh = 50, + .xres = 1200, + .yres = 825, + .pixclock = 32000000, + .left_margin = 12, + .right_margin = 128, + .upper_margin = 4, + .lower_margin = 10, + .hsync_len = 20, + .vsync_len = 4, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, +}; + +static struct imx_epdc_fb_mode panel_modes[] = { + { + &e60_v110_mode, + 4, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 428, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 1, /* gdclk_offs */ + 1, /* num_ce */ + }, + { + &e60_v220_mode, + 4, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 465, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 9, /* gdclk_offs */ + 1, /* num_ce */ + }, + { + &e060scm_mode, + 4, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 419, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 5, /* gdclk_offs */ + 1, /* num_ce */ + }, + { + &e97_v110_mode, + 8, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 632, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 1, /* gdclk_offs */ + 3, /* num_ce */ + } +}; + +static struct imx_epdc_fb_platform_data epdc_data = { + .epdc_mode = panel_modes, + .num_modes = ARRAY_SIZE(panel_modes), + .get_pins = epdc_get_pins, + .put_pins = epdc_put_pins, + .enable_pins = epdc_enable_pins, + .disable_pins = epdc_disable_pins, +}; + static void imx6_arm2_usbotg_vbus(bool on) { if (on) @@ -1564,6 +2085,8 @@ static void __init mx6_arm2_init(void) if (cpu_is_mx6dl()) { imx6dl_add_imx_pxp(); imx6dl_add_imx_pxp_client(); + mxc_register_device(&max17135_sensor_device, NULL); + imx6dl_add_imx_epdc(&epdc_data); } } diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index e52dcab916ce..58dcbe103ae0 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -99,6 +99,21 @@ static int cpu_op_nr; static unsigned long external_high_reference, external_low_reference; static unsigned long oscillator_reference, ckih2_reference; +/* For MX 6DL/S, Video PLL may be used by synchronous display devices, + * such as HDMI or LVDS, and also by the EPDC. If EPDC is in use, + * it must use the Video PLL to achieve the clock frequencies it needs. + * So if EPDC is in use, the "epdc" string should be added to kernel + * parameters, in order to set the EPDC parent clock to the Video PLL. + * This will have an impact on the behavior of HDMI and LVDS. + */ +static int epdc_use_video_pll; +static int __init epdc_clk_setup(char *__unused) +{ + epdc_use_video_pll = 1; + return 1; +} +__setup("epdc", epdc_clk_setup); + static void __calc_pre_post_dividers(u32 max_podf, u32 div, u32 *pre, u32 *post) { u32 min_pre, temp_pre, old_err, err; @@ -781,7 +796,7 @@ static unsigned long _clk_audio_video_get_rate(struct clk *clk) else pllbase = PLL5_VIDEO_BASE_ADDR; - if (rev >= IMX_CHIP_REVISION_1_1) { + if ((rev >= IMX_CHIP_REVISION_1_1) || cpu_is_mx6dl()) { test_div_sel = (__raw_readl(pllbase) & ANADIG_PLL_AV_TEST_DIV_SEL_MASK) >> ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET; @@ -823,7 +838,7 @@ static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate) u32 test_div_sel = 2; u32 control3 = 0; - if (rev < IMX_CHIP_REVISION_1_1) + if ((rev < IMX_CHIP_REVISION_1_1) && !cpu_is_mx6dl()) min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ; else if (clk == &pll4_audio_main_clk) min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4; @@ -839,7 +854,7 @@ static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate) pllbase = PLL5_VIDEO_BASE_ADDR; pre_div_rate = rate; - if (rev >= IMX_CHIP_REVISION_1_1) { + if ((rev >= IMX_CHIP_REVISION_1_1) || cpu_is_mx6dl()) { while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) { pre_div_rate *= 2; /* @@ -902,7 +917,7 @@ static unsigned long _clk_audio_video_round_rate(struct clk *clk, unsigned long final_rate; int rev = mx6q_revision(); - if (rev < IMX_CHIP_REVISION_1_1) + if ((rev < IMX_CHIP_REVISION_1_1) && !cpu_is_mx6dl()) min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ; else if (clk == &pll4_audio_main_clk) min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4; @@ -916,7 +931,7 @@ static unsigned long _clk_audio_video_round_rate(struct clk *clk, return AUDIO_VIDEO_MAX_CLK_FREQ; pre_div_rate = rate; - if (rev >= IMX_CHIP_REVISION_1_1) { + if ((rev >= IMX_CHIP_REVISION_1_1) || cpu_is_mx6dl()) { while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) { pre_div_rate *= 2; post_div *= 2; @@ -5111,6 +5126,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "clko_clk", clko_clk), _REGISTER_CLOCK(NULL, "clko2_clk", clko2_clk), _REGISTER_CLOCK(NULL, "pxp_axi", ipu2_clk), + _REGISTER_CLOCK(NULL, "epdc_axi", ipu2_clk), + _REGISTER_CLOCK(NULL, "epdc_pix", ipu2_di_clk[1]), _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk), _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk), _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk), @@ -5271,6 +5288,13 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, gpt_clk[0].get_rate = NULL; } + if (cpu_is_mx6dl()) { + if (epdc_use_video_pll) + clk_set_parent(&ipu2_di_clk[1], &pll5_video_main_clk); + else + clk_set_parent(&ipu2_di_clk[1], &pll3_pfd_540M); + } + base = ioremap(GPT_BASE_ADDR, SZ_4K); mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT); diff --git a/arch/arm/plat-mxc/devices/platform-imx-epdc-fb.c b/arch/arm/plat-mxc/devices/platform-imx-epdc-fb.c index d7dbe3edcaef..404a264e7ddc 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-epdc-fb.c +++ b/arch/arm/plat-mxc/devices/platform-imx-epdc-fb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -22,7 +22,7 @@ #include #include -#define imx5_epdc_data_entry_single(soc, size) \ +#define imx_epdc_data_entry_single(soc, size) \ { \ .iobase = soc ## _EPDC_BASE_ADDR, \ .irq = soc ## _INT_EPDC, \ @@ -31,7 +31,12 @@ #ifdef CONFIG_SOC_IMX50 const struct imx_epdc_data imx50_epdc_data __initconst = - imx5_epdc_data_entry_single(MX50, SZ_4K); + imx_epdc_data_entry_single(MX50, SZ_4K); +#endif + +#ifdef CONFIG_SOC_IMX6Q +const struct imx_epdc_data imx6dl_epdc_data __initconst = + imx_epdc_data_entry_single(MX6DL, SZ_16K); #endif struct platform_device *__init imx_add_imx_epdc(