Commit 6baaad39acc031cdb93a5e5a68a26c3fbc25c88f

Authored by Haibo Chen
1 parent b68f4a1fc4

MLK-10215 Add elan init in i.MX6SL-EVK board

EPDC board contain a elan touch screen, this screen is a i2c
slave. If this EPDC board connect to i.MX6SL-EVK board, after
uboot boot up, if we do i2c operation, like i2c probe, then
the i2c bus block. This is due to the elan touch screen i2c slave.
This device needs to do some initialization opearation before its
i2c operation, otherwise this i2c device pull down the i2c clk line,
and make the i2c bus hang. This means elan needs a special flow on
i2c before its address is acked, otherwise the i2c bus will be hang.

This patch is a workaround, it add a void function which is defined
as a weak symbol in i2c driver, and it is called before every i2c
operation. In mx6slevk, this function was overwrite to execute elan
initialization. So that, for mx6slevk board, it will  initialize
elan before every i2c operation, but for other boards, it just work
as before.

Signed-off-by: Haibo Chen <haibo.chen@freescale.com>

Showing 3 changed files with 56 additions and 1 deletions Side-by-side Diff

arch/arm/include/asm/arch-mx6/mx6sl_pins.h
... ... @@ -57,7 +57,8 @@
57 57 MX6_PAD_I2C1_SDA__GPIO_3_13 = IOMUX_PAD(0x0450, 0x0160, 5, 0x0000, 0, 0),
58 58 MX6_PAD_I2C1_SCL__I2C1_SCL = IOMUX_PAD(0x044C, 0x015C, 0x10, 0x071C, 2, 0),
59 59 MX6_PAD_I2C1_SCL__GPIO_3_12 = IOMUX_PAD(0x044C, 0x015C, 5, 0x0000, 0, 0),
60   -
  60 + MX6_PAD_EPDC_PWRCTRL2__GPIO_2_9 = IOMUX_PAD(0x03DC, 0x00EC, 5, 0x0000, 0, 0),
  61 + MX6_PAD_EPDC_PWRCTRL3__GPIO_2_10 = IOMUX_PAD(0x03E0, 0x00F0, 5, 0x0000, 0, 0),
61 62 MX6_PAD_EPDC_PWRSTAT__GPIO_2_13 = IOMUX_PAD(0x03E8, 0x00F8, 5, 0x0000, 0, 0),
62 63 MX6_PAD_EPDC_VCOM0__GPIO_2_3 = IOMUX_PAD(0x0410, 0x0120, 5, 0x0000, 0, 0),
63 64 MX6_PAD_EPDC_PWRWAKEUP__GPIO_2_14 = IOMUX_PAD(0x03EC, 0x00FC, 5, 0x0000, 0, 0),
... ... @@ -116,6 +117,7 @@
116 117 MX6_PAD_KEY_COL4__USB_USBOTG1_PWR = IOMUX_PAD(0x0484, 0x017C, 6, 0x0000, 0, 0),
117 118 MX6_PAD_KEY_COL5__USB_USBOTG2_PWR = IOMUX_PAD(0x0488, 0x0180, 6, 0x0000, 0, 0),
118 119  
  120 + MX6_PAD_KEY_COL6__GPIO_4_4 = IOMUX_PAD(0x048C, 0x0184, 5, 0x0000, 0, 0),
119 121 MX6_PAD_ECSPI1_MISO__ECSPI1_MISO = IOMUX_PAD(0x0358, 0x0068, 0, 0x0684, 0, 0),
120 122 MX6_PAD_ECSPI1_MOSI__ECSPI1_MOSI = IOMUX_PAD(0x035C, 0x006C, 0, 0x0688, 0, 0),
121 123 MX6_PAD_ECSPI1_SCLK__ECSPI1_SCLK = IOMUX_PAD(0x0360, 0x0070, 0, 0x067C, 0, 0),
board/freescale/mx6slevk/mx6slevk.c
... ... @@ -60,6 +60,8 @@
60 60 PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
61 61 PAD_CTL_ODE | PAD_CTL_SRE_FAST)
62 62  
  63 +#define ELAN_INTR_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_HYS)
  64 +
63 65 #define EPDC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_SPEED_MED | \
64 66 PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
65 67  
... ... @@ -149,6 +151,12 @@
149 151 MX6_PAD_FEC_TX_CLK__GPIO_4_21 | MUX_PAD_CTRL(NO_PAD_CTRL),
150 152 };
151 153  
  154 +static iomux_v3_cfg_t const elan_pads[] = {
  155 + MX6_PAD_EPDC_PWRCTRL2__GPIO_2_9 | MUX_PAD_CTRL(NO_PAD_CTRL),
  156 + MX6_PAD_EPDC_PWRCTRL3__GPIO_2_10 | MUX_PAD_CTRL(ELAN_INTR_PAD_CTRL),
  157 + MX6_PAD_KEY_COL6__GPIO_4_4 | MUX_PAD_CTRL(EPDC_PAD_CTRL),
  158 +};
  159 +
152 160 static iomux_v3_cfg_t const epdc_enable_pads[] = {
153 161 MX6_PAD_EPDC_D0__EPDC_SDDO_0 | MUX_PAD_CTRL(EPDC_PAD_CTRL),
154 162 MX6_PAD_EPDC_D1__EPDC_SDDO_1 | MUX_PAD_CTRL(EPDC_PAD_CTRL),
... ... @@ -853,6 +861,36 @@
853 861 return 0;
854 862 }
855 863  
  864 +void setup_elan_pads(void)
  865 +{
  866 +#define TOUCH_CS IMX_GPIO_NR(2, 9)
  867 +#define TOUCH_INT IMX_GPIO_NR(2, 10)
  868 +#define TOUCH_RST IMX_GPIO_NR(4, 4)
  869 + imx_iomux_v3_setup_multiple_pads(elan_pads, ARRAY_SIZE(elan_pads));
  870 +}
  871 +
  872 +void elan_init(void)
  873 +{
  874 + gpio_direction_input(TOUCH_INT);
  875 + gpio_direction_output(TOUCH_CS , 1);
  876 + gpio_set_value(TOUCH_CS, 0);
  877 + gpio_direction_output(TOUCH_RST , 1);
  878 + gpio_set_value(TOUCH_RST, 0);
  879 + mdelay(10);
  880 + gpio_set_value(TOUCH_RST, 1);
  881 + gpio_set_value(TOUCH_CS, 1);
  882 + mdelay(100);
  883 +}
  884 +
  885 +/*
  886 + * This function overwrite the function defined in
  887 + * drivers/i2c/mxc_i2c.c, which is a weak symbol
  888 + */
  889 +void i2c_force_reset_slave(void)
  890 +{
  891 + elan_init();
  892 +}
  893 +
856 894 int board_late_init(void)
857 895 {
858 896 int ret = 0;
... ... @@ -860,6 +898,7 @@
860 898 #ifdef CONFIG_SYS_I2C_MXC
861 899 setup_i2c(0, CONFIG_SYS_I2C_SPEED,
862 900 0x7f, &i2c_pad_info0);
  901 + setup_elan_pads();
863 902 ret = setup_pmic_voltages();
864 903 if (ret)
865 904 return -1;
drivers/i2c/mxc_i2c.c
... ... @@ -238,6 +238,17 @@
238 238 }
239 239  
240 240 /*
  241 + * Stub implementations for outer i2c slave operations
  242 + * Any board has special requirement (i.mx6slevk) can
  243 + * overwrite the function
  244 + */
  245 +void __i2c_force_reset_slave(void)
  246 +{
  247 +}
  248 +void i2c_force_reset_slave(void)
  249 + __attribute__((weak, alias("__i2c_force_reset_slave")));
  250 +
  251 +/*
241 252 * Send start signal, chip address and
242 253 * write register address
243 254 */
... ... @@ -246,6 +257,9 @@
246 257 {
247 258 unsigned int temp;
248 259 int ret;
  260 +
  261 + /* Reset i2c slave */
  262 + i2c_force_reset_slave();
249 263  
250 264 /* Enable I2C controller */
251 265 #ifdef I2C_QUIRK_REG