1cdace066SSascha Hauer /* 2db84140bSMarek Vasut * i2c driver for Freescale i.MX series 3cdace066SSascha Hauer * 4cdace066SSascha Hauer * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> 5db84140bSMarek Vasut * (c) 2011 Marek Vasut <marek.vasut@gmail.com> 6db84140bSMarek Vasut * 7db84140bSMarek Vasut * Based on i2c-imx.c from linux kernel: 8db84140bSMarek Vasut * Copyright (C) 2005 Torsten Koschorrek <koschorrek at synertronixx.de> 9db84140bSMarek Vasut * Copyright (C) 2005 Matthias Blaschke <blaschke at synertronixx.de> 10db84140bSMarek Vasut * Copyright (C) 2007 RightHand Technologies, Inc. 11db84140bSMarek Vasut * Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt> 12db84140bSMarek Vasut * 13cdace066SSascha Hauer * 14cdace066SSascha Hauer * See file CREDITS for list of people who contributed to this 15cdace066SSascha Hauer * project. 16cdace066SSascha Hauer * 17cdace066SSascha Hauer * This program is free software; you can redistribute it and/or 18cdace066SSascha Hauer * modify it under the terms of the GNU General Public License as 19cdace066SSascha Hauer * published by the Free Software Foundation; either version 2 of 20cdace066SSascha Hauer * the License, or (at your option) any later version. 21cdace066SSascha Hauer * 22cdace066SSascha Hauer * This program is distributed in the hope that it will be useful, 23cdace066SSascha Hauer * but WITHOUT ANY WARRANTY; without even the implied warranty of 24cdace066SSascha Hauer * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25cdace066SSascha Hauer * GNU General Public License for more details. 26cdace066SSascha Hauer * 27cdace066SSascha Hauer * You should have received a copy of the GNU General Public License 28cdace066SSascha Hauer * along with this program; if not, write to the Free Software 29cdace066SSascha Hauer * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 30cdace066SSascha Hauer * MA 02111-1307 USA 31cdace066SSascha Hauer */ 32cdace066SSascha Hauer 33cdace066SSascha Hauer #include <common.h> 34127cec18SLiu Hui-R64343 #include <asm/arch/clock.h> 3586271115SStefano Babic #include <asm/arch/imx-regs.h> 36cea60b0cSTroy Kisky #include <asm/errno.h> 3724cd738bSTroy Kisky #include <asm/io.h> 38bf0783dfSMarek Vasut #include <i2c.h> 397aa57a01STroy Kisky #include <watchdog.h> 40cdace066SSascha Hauer 41*30ea41a4SAlison Wang #ifdef I2C_QUIRK_REG 42*30ea41a4SAlison Wang struct mxc_i2c_regs { 43*30ea41a4SAlison Wang uint8_t iadr; 44*30ea41a4SAlison Wang uint8_t ifdr; 45*30ea41a4SAlison Wang uint8_t i2cr; 46*30ea41a4SAlison Wang uint8_t i2sr; 47*30ea41a4SAlison Wang uint8_t i2dr; 48*30ea41a4SAlison Wang }; 49*30ea41a4SAlison Wang #else 50db84140bSMarek Vasut struct mxc_i2c_regs { 51db84140bSMarek Vasut uint32_t iadr; 52db84140bSMarek Vasut uint32_t ifdr; 53db84140bSMarek Vasut uint32_t i2cr; 54db84140bSMarek Vasut uint32_t i2sr; 55db84140bSMarek Vasut uint32_t i2dr; 56db84140bSMarek Vasut }; 57*30ea41a4SAlison Wang #endif 58cdace066SSascha Hauer 59cdace066SSascha Hauer #define I2CR_IIEN (1 << 6) 60cdace066SSascha Hauer #define I2CR_MSTA (1 << 5) 61cdace066SSascha Hauer #define I2CR_MTX (1 << 4) 62cdace066SSascha Hauer #define I2CR_TX_NO_AK (1 << 3) 63cdace066SSascha Hauer #define I2CR_RSTA (1 << 2) 64cdace066SSascha Hauer 65cdace066SSascha Hauer #define I2SR_ICF (1 << 7) 66cdace066SSascha Hauer #define I2SR_IBB (1 << 5) 67d5383a63STroy Kisky #define I2SR_IAL (1 << 4) 68cdace066SSascha Hauer #define I2SR_IIF (1 << 1) 69cdace066SSascha Hauer #define I2SR_RX_NO_AK (1 << 0) 70cdace066SSascha Hauer 71*30ea41a4SAlison Wang #ifdef I2C_QUIRK_REG 72*30ea41a4SAlison Wang #define I2CR_IEN (0 << 7) 73*30ea41a4SAlison Wang #define I2CR_IDIS (1 << 7) 74*30ea41a4SAlison Wang #define I2SR_IIF_CLEAR (1 << 1) 75*30ea41a4SAlison Wang #else 76*30ea41a4SAlison Wang #define I2CR_IEN (1 << 7) 77*30ea41a4SAlison Wang #define I2CR_IDIS (0 << 7) 78*30ea41a4SAlison Wang #define I2SR_IIF_CLEAR (0 << 1) 79*30ea41a4SAlison Wang #endif 80*30ea41a4SAlison Wang 81e4ff525fSTroy Kisky #if defined(CONFIG_HARD_I2C) && !defined(CONFIG_SYS_I2C_BASE) 82de6f604dSTroy Kisky #error "define CONFIG_SYS_I2C_BASE to use the mxc_i2c driver" 83cdace066SSascha Hauer #endif 84cdace066SSascha Hauer 85*30ea41a4SAlison Wang #ifdef I2C_QUIRK_REG 86*30ea41a4SAlison Wang static u16 i2c_clk_div[60][2] = { 87*30ea41a4SAlison Wang { 20, 0x00 }, { 22, 0x01 }, { 24, 0x02 }, { 26, 0x03 }, 88*30ea41a4SAlison Wang { 28, 0x04 }, { 30, 0x05 }, { 32, 0x09 }, { 34, 0x06 }, 89*30ea41a4SAlison Wang { 36, 0x0A }, { 40, 0x07 }, { 44, 0x0C }, { 48, 0x0D }, 90*30ea41a4SAlison Wang { 52, 0x43 }, { 56, 0x0E }, { 60, 0x45 }, { 64, 0x12 }, 91*30ea41a4SAlison Wang { 68, 0x0F }, { 72, 0x13 }, { 80, 0x14 }, { 88, 0x15 }, 92*30ea41a4SAlison Wang { 96, 0x19 }, { 104, 0x16 }, { 112, 0x1A }, { 128, 0x17 }, 93*30ea41a4SAlison Wang { 136, 0x4F }, { 144, 0x1C }, { 160, 0x1D }, { 176, 0x55 }, 94*30ea41a4SAlison Wang { 192, 0x1E }, { 208, 0x56 }, { 224, 0x22 }, { 228, 0x24 }, 95*30ea41a4SAlison Wang { 240, 0x1F }, { 256, 0x23 }, { 288, 0x5C }, { 320, 0x25 }, 96*30ea41a4SAlison Wang { 384, 0x26 }, { 448, 0x2A }, { 480, 0x27 }, { 512, 0x2B }, 97*30ea41a4SAlison Wang { 576, 0x2C }, { 640, 0x2D }, { 768, 0x31 }, { 896, 0x32 }, 98*30ea41a4SAlison Wang { 960, 0x2F }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 }, 99*30ea41a4SAlison Wang { 1536, 0x36 }, { 1792, 0x3A }, { 1920, 0x37 }, { 2048, 0x3B }, 100*30ea41a4SAlison Wang { 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A }, 101*30ea41a4SAlison Wang { 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E }, 102*30ea41a4SAlison Wang }; 103*30ea41a4SAlison Wang #else 104db84140bSMarek Vasut static u16 i2c_clk_div[50][2] = { 105db84140bSMarek Vasut { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, 106db84140bSMarek Vasut { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, 107db84140bSMarek Vasut { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, 108db84140bSMarek Vasut { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2A }, { 72, 0x2B }, 109db84140bSMarek Vasut { 80, 0x2C }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, 110db84140bSMarek Vasut { 112, 0x2E }, { 128, 0x2F }, { 144, 0x0C }, { 160, 0x30 }, 111db84140bSMarek Vasut { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, 112db84140bSMarek Vasut { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 }, { 448, 0x36 }, 113db84140bSMarek Vasut { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x38 }, 114db84140bSMarek Vasut { 768, 0x39 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, 115db84140bSMarek Vasut { 1152, 0x18 }, { 1280, 0x3C }, { 1536, 0x3D }, { 1792, 0x3E }, 116db84140bSMarek Vasut { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, 117db84140bSMarek Vasut { 3072, 0x1E }, { 3840, 0x1F } 118db84140bSMarek Vasut }; 119*30ea41a4SAlison Wang #endif 120cdace066SSascha Hauer 121db84140bSMarek Vasut /* 122db84140bSMarek Vasut * Calculate and set proper clock divider 123db84140bSMarek Vasut */ 124bf0783dfSMarek Vasut static uint8_t i2c_imx_get_clk(unsigned int rate) 1251d549adeSStefano Babic { 126db84140bSMarek Vasut unsigned int i2c_clk_rate; 127db84140bSMarek Vasut unsigned int div; 128bf0783dfSMarek Vasut u8 clk_div; 129cdace066SSascha Hauer 130127cec18SLiu Hui-R64343 #if defined(CONFIG_MX31) 1311d549adeSStefano Babic struct clock_control_regs *sc_regs = 1321d549adeSStefano Babic (struct clock_control_regs *)CCM_BASE; 133db84140bSMarek Vasut 134e7de18afSGuennadi Liakhovetski /* start the required I2C clock */ 135de6f604dSTroy Kisky writel(readl(&sc_regs->cgr0) | (3 << CONFIG_SYS_I2C_CLK_OFFSET), 1361d549adeSStefano Babic &sc_regs->cgr0); 137127cec18SLiu Hui-R64343 #endif 138e7de18afSGuennadi Liakhovetski 139db84140bSMarek Vasut /* Divider value calculation */ 140e7bed5c2SMatthias Weisser i2c_clk_rate = mxc_get_clock(MXC_I2C_CLK); 141db84140bSMarek Vasut div = (i2c_clk_rate + rate - 1) / rate; 142db84140bSMarek Vasut if (div < i2c_clk_div[0][0]) 143b567b8ffSMarek Vasut clk_div = 0; 144db84140bSMarek Vasut else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0]) 145b567b8ffSMarek Vasut clk_div = ARRAY_SIZE(i2c_clk_div) - 1; 146db84140bSMarek Vasut else 147b567b8ffSMarek Vasut for (clk_div = 0; i2c_clk_div[clk_div][0] < div; clk_div++) 148db84140bSMarek Vasut ; 149cdace066SSascha Hauer 150db84140bSMarek Vasut /* Store divider value */ 151bf0783dfSMarek Vasut return clk_div; 152db84140bSMarek Vasut } 153cdace066SSascha Hauer 154db84140bSMarek Vasut /* 155e4ff525fSTroy Kisky * Set I2C Bus speed 156db84140bSMarek Vasut */ 1577f86bd57SMarek Vasut static int bus_i2c_set_bus_speed(void *base, int speed) 158db84140bSMarek Vasut { 159e4ff525fSTroy Kisky struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base; 160bf0783dfSMarek Vasut u8 clk_idx = i2c_imx_get_clk(speed); 161bf0783dfSMarek Vasut u8 idx = i2c_clk_div[clk_idx][1]; 162bf0783dfSMarek Vasut 163bf0783dfSMarek Vasut /* Store divider value */ 164bf0783dfSMarek Vasut writeb(idx, &i2c_regs->ifdr); 165bf0783dfSMarek Vasut 16683a1a190STroy Kisky /* Reset module */ 167*30ea41a4SAlison Wang writeb(I2CR_IDIS, &i2c_regs->i2cr); 16883a1a190STroy Kisky writeb(0, &i2c_regs->i2sr); 169b567b8ffSMarek Vasut return 0; 170b567b8ffSMarek Vasut } 171b567b8ffSMarek Vasut 172b567b8ffSMarek Vasut /* 173b567b8ffSMarek Vasut * Get I2C Speed 174b567b8ffSMarek Vasut */ 1757f86bd57SMarek Vasut static unsigned int bus_i2c_get_bus_speed(void *base) 176b567b8ffSMarek Vasut { 177e4ff525fSTroy Kisky struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base; 178bf0783dfSMarek Vasut u8 clk_idx = readb(&i2c_regs->ifdr); 179bf0783dfSMarek Vasut u8 clk_div; 180bf0783dfSMarek Vasut 181bf0783dfSMarek Vasut for (clk_div = 0; i2c_clk_div[clk_div][1] != clk_idx; clk_div++) 182bf0783dfSMarek Vasut ; 183bf0783dfSMarek Vasut 184e7bed5c2SMatthias Weisser return mxc_get_clock(MXC_I2C_CLK) / i2c_clk_div[clk_div][0]; 185b567b8ffSMarek Vasut } 186b567b8ffSMarek Vasut 1877aa57a01STroy Kisky #define ST_BUS_IDLE (0 | (I2SR_IBB << 8)) 1887aa57a01STroy Kisky #define ST_BUS_BUSY (I2SR_IBB | (I2SR_IBB << 8)) 1897aa57a01STroy Kisky #define ST_IIF (I2SR_IIF | (I2SR_IIF << 8)) 1907aa57a01STroy Kisky 1917aa57a01STroy Kisky static int wait_for_sr_state(struct mxc_i2c_regs *i2c_regs, unsigned state) 19281687212SStefano Babic { 1937aa57a01STroy Kisky unsigned sr; 1947aa57a01STroy Kisky ulong elapsed; 1957aa57a01STroy Kisky ulong start_time = get_timer(0); 1967aa57a01STroy Kisky for (;;) { 1977aa57a01STroy Kisky sr = readb(&i2c_regs->i2sr); 198d5383a63STroy Kisky if (sr & I2SR_IAL) { 199*30ea41a4SAlison Wang #ifdef I2C_QUIRK_REG 200*30ea41a4SAlison Wang writeb(sr | I2SR_IAL, &i2c_regs->i2sr); 201*30ea41a4SAlison Wang #else 202d5383a63STroy Kisky writeb(sr & ~I2SR_IAL, &i2c_regs->i2sr); 203*30ea41a4SAlison Wang #endif 204d5383a63STroy Kisky printf("%s: Arbitration lost sr=%x cr=%x state=%x\n", 205d5383a63STroy Kisky __func__, sr, readb(&i2c_regs->i2cr), state); 206d5383a63STroy Kisky return -ERESTART; 207d5383a63STroy Kisky } 2087aa57a01STroy Kisky if ((sr & (state >> 8)) == (unsigned char)state) 2097aa57a01STroy Kisky return sr; 2107aa57a01STroy Kisky WATCHDOG_RESET(); 2117aa57a01STroy Kisky elapsed = get_timer(start_time); 2127aa57a01STroy Kisky if (elapsed > (CONFIG_SYS_HZ / 10)) /* .1 seconds */ 2137aa57a01STroy Kisky break; 21481687212SStefano Babic } 2157aa57a01STroy Kisky printf("%s: failed sr=%x cr=%x state=%x\n", __func__, 2167aa57a01STroy Kisky sr, readb(&i2c_regs->i2cr), state); 217cea60b0cSTroy Kisky return -ETIMEDOUT; 218db84140bSMarek Vasut } 219db84140bSMarek Vasut 220cea60b0cSTroy Kisky static int tx_byte(struct mxc_i2c_regs *i2c_regs, u8 byte) 221cdace066SSascha Hauer { 222cea60b0cSTroy Kisky int ret; 223db84140bSMarek Vasut 224*30ea41a4SAlison Wang writeb(I2SR_IIF_CLEAR, &i2c_regs->i2sr); 225cea60b0cSTroy Kisky writeb(byte, &i2c_regs->i2dr); 2267aa57a01STroy Kisky ret = wait_for_sr_state(i2c_regs, ST_IIF); 227cea60b0cSTroy Kisky if (ret < 0) 228cea60b0cSTroy Kisky return ret; 229cea60b0cSTroy Kisky if (ret & I2SR_RX_NO_AK) 230cea60b0cSTroy Kisky return -ENODEV; 231cea60b0cSTroy Kisky return 0; 232db84140bSMarek Vasut } 233db84140bSMarek Vasut 234db84140bSMarek Vasut /* 23590a5b70fSTroy Kisky * Stop I2C transaction 236db84140bSMarek Vasut */ 23727a5da02STroy Kisky static void i2c_imx_stop(struct mxc_i2c_regs *i2c_regs) 238db84140bSMarek Vasut { 2397aa57a01STroy Kisky int ret; 24090a5b70fSTroy Kisky unsigned int temp = readb(&i2c_regs->i2cr); 241db84140bSMarek Vasut 2421c076dbaSTroy Kisky temp &= ~(I2CR_MSTA | I2CR_MTX); 243db84140bSMarek Vasut writeb(temp, &i2c_regs->i2cr); 2447aa57a01STroy Kisky ret = wait_for_sr_state(i2c_regs, ST_BUS_IDLE); 2457aa57a01STroy Kisky if (ret < 0) 2467aa57a01STroy Kisky printf("%s:trigger stop failed\n", __func__); 247db84140bSMarek Vasut } 248db84140bSMarek Vasut 249db84140bSMarek Vasut /* 250b230ddc2STroy Kisky * Send start signal, chip address and 251b230ddc2STroy Kisky * write register address 252db84140bSMarek Vasut */ 253a7f1a005STroy Kisky static int i2c_init_transfer_(struct mxc_i2c_regs *i2c_regs, 254b230ddc2STroy Kisky uchar chip, uint addr, int alen) 255cdace066SSascha Hauer { 25671e9f3cbSTroy Kisky unsigned int temp; 25771e9f3cbSTroy Kisky int ret; 25871e9f3cbSTroy Kisky 25971e9f3cbSTroy Kisky /* Enable I2C controller */ 260*30ea41a4SAlison Wang #ifdef I2C_QUIRK_REG 261*30ea41a4SAlison Wang if (readb(&i2c_regs->i2cr) & I2CR_IDIS) { 262*30ea41a4SAlison Wang #else 26390a5b70fSTroy Kisky if (!(readb(&i2c_regs->i2cr) & I2CR_IEN)) { 264*30ea41a4SAlison Wang #endif 26571e9f3cbSTroy Kisky writeb(I2CR_IEN, &i2c_regs->i2cr); 26671e9f3cbSTroy Kisky /* Wait for controller to be stable */ 26771e9f3cbSTroy Kisky udelay(50); 26890a5b70fSTroy Kisky } 269ca741da1STroy Kisky if (readb(&i2c_regs->iadr) == (chip << 1)) 270ca741da1STroy Kisky writeb((chip << 1) ^ 2, &i2c_regs->iadr); 271*30ea41a4SAlison Wang writeb(I2SR_IIF_CLEAR, &i2c_regs->i2sr); 27290a5b70fSTroy Kisky ret = wait_for_sr_state(i2c_regs, ST_BUS_IDLE); 27390a5b70fSTroy Kisky if (ret < 0) 274a7f1a005STroy Kisky return ret; 27571e9f3cbSTroy Kisky 27671e9f3cbSTroy Kisky /* Start I2C transaction */ 27771e9f3cbSTroy Kisky temp = readb(&i2c_regs->i2cr); 27871e9f3cbSTroy Kisky temp |= I2CR_MSTA; 27971e9f3cbSTroy Kisky writeb(temp, &i2c_regs->i2cr); 28071e9f3cbSTroy Kisky 28171e9f3cbSTroy Kisky ret = wait_for_sr_state(i2c_regs, ST_BUS_BUSY); 28271e9f3cbSTroy Kisky if (ret < 0) 283a7f1a005STroy Kisky return ret; 284b230ddc2STroy Kisky 28571e9f3cbSTroy Kisky temp |= I2CR_MTX | I2CR_TX_NO_AK; 28671e9f3cbSTroy Kisky writeb(temp, &i2c_regs->i2cr); 28771e9f3cbSTroy Kisky 288b230ddc2STroy Kisky /* write slave address */ 289b230ddc2STroy Kisky ret = tx_byte(i2c_regs, chip << 1); 290b230ddc2STroy Kisky if (ret < 0) 291a7f1a005STroy Kisky return ret; 292db84140bSMarek Vasut 293bf0783dfSMarek Vasut while (alen--) { 294cea60b0cSTroy Kisky ret = tx_byte(i2c_regs, (addr >> (alen * 8)) & 0xff); 295cea60b0cSTroy Kisky if (ret < 0) 296a7f1a005STroy Kisky return ret; 29781687212SStefano Babic } 298b230ddc2STroy Kisky return 0; 299a7f1a005STroy Kisky } 300a7f1a005STroy Kisky 30196c19bd3STroy Kisky static int i2c_idle_bus(void *base); 30296c19bd3STroy Kisky 303a7f1a005STroy Kisky static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, 304a7f1a005STroy Kisky uchar chip, uint addr, int alen) 305a7f1a005STroy Kisky { 306a7f1a005STroy Kisky int retry; 307a7f1a005STroy Kisky int ret; 308a7f1a005STroy Kisky for (retry = 0; retry < 3; retry++) { 309a7f1a005STroy Kisky ret = i2c_init_transfer_(i2c_regs, chip, addr, alen); 310a7f1a005STroy Kisky if (ret >= 0) 311a7f1a005STroy Kisky return 0; 31227a5da02STroy Kisky i2c_imx_stop(i2c_regs); 313a7f1a005STroy Kisky if (ret == -ENODEV) 314a7f1a005STroy Kisky return ret; 315a7f1a005STroy Kisky 316a7f1a005STroy Kisky printf("%s: failed for chip 0x%x retry=%d\n", __func__, chip, 317a7f1a005STroy Kisky retry); 318a7f1a005STroy Kisky if (ret != -ERESTART) 319*30ea41a4SAlison Wang /* Disable controller */ 320*30ea41a4SAlison Wang writeb(I2CR_IDIS, &i2c_regs->i2cr); 321a7f1a005STroy Kisky udelay(100); 32296c19bd3STroy Kisky if (i2c_idle_bus(i2c_regs) < 0) 32396c19bd3STroy Kisky break; 324a7f1a005STroy Kisky } 325a7f1a005STroy Kisky printf("%s: give up i2c_regs=%p\n", __func__, i2c_regs); 326db84140bSMarek Vasut return ret; 327cdace066SSascha Hauer } 328cdace066SSascha Hauer 329db84140bSMarek Vasut /* 330db84140bSMarek Vasut * Read data from I2C device 331db84140bSMarek Vasut */ 332e4ff525fSTroy Kisky int bus_i2c_read(void *base, uchar chip, uint addr, int alen, uchar *buf, 333e4ff525fSTroy Kisky int len) 334db84140bSMarek Vasut { 335db84140bSMarek Vasut int ret; 336db84140bSMarek Vasut unsigned int temp; 337db84140bSMarek Vasut int i; 338e4ff525fSTroy Kisky struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base; 339cdace066SSascha Hauer 340b230ddc2STroy Kisky ret = i2c_init_transfer(i2c_regs, chip, addr, alen); 341cea60b0cSTroy Kisky if (ret < 0) 342db84140bSMarek Vasut return ret; 343cdace066SSascha Hauer 344db84140bSMarek Vasut temp = readb(&i2c_regs->i2cr); 345db84140bSMarek Vasut temp |= I2CR_RSTA; 346db84140bSMarek Vasut writeb(temp, &i2c_regs->i2cr); 347db84140bSMarek Vasut 348cea60b0cSTroy Kisky ret = tx_byte(i2c_regs, (chip << 1) | 1); 349c4330d28STroy Kisky if (ret < 0) { 35027a5da02STroy Kisky i2c_imx_stop(i2c_regs); 351db84140bSMarek Vasut return ret; 352c4330d28STroy Kisky } 353db84140bSMarek Vasut 354db84140bSMarek Vasut /* setup bus to read data */ 355db84140bSMarek Vasut temp = readb(&i2c_regs->i2cr); 356db84140bSMarek Vasut temp &= ~(I2CR_MTX | I2CR_TX_NO_AK); 357db84140bSMarek Vasut if (len == 1) 358db84140bSMarek Vasut temp |= I2CR_TX_NO_AK; 359db84140bSMarek Vasut writeb(temp, &i2c_regs->i2cr); 360*30ea41a4SAlison Wang writeb(I2SR_IIF_CLEAR, &i2c_regs->i2sr); 361ea572d85STroy Kisky readb(&i2c_regs->i2dr); /* dummy read to clear ICF */ 362db84140bSMarek Vasut 363db84140bSMarek Vasut /* read data */ 364db84140bSMarek Vasut for (i = 0; i < len; i++) { 3657aa57a01STroy Kisky ret = wait_for_sr_state(i2c_regs, ST_IIF); 3667aa57a01STroy Kisky if (ret < 0) { 36727a5da02STroy Kisky i2c_imx_stop(i2c_regs); 368db84140bSMarek Vasut return ret; 369c4330d28STroy Kisky } 370db84140bSMarek Vasut 371db84140bSMarek Vasut /* 372db84140bSMarek Vasut * It must generate STOP before read I2DR to prevent 373db84140bSMarek Vasut * controller from generating another clock cycle 374db84140bSMarek Vasut */ 375db84140bSMarek Vasut if (i == (len - 1)) { 37627a5da02STroy Kisky i2c_imx_stop(i2c_regs); 377db84140bSMarek Vasut } else if (i == (len - 2)) { 378db84140bSMarek Vasut temp = readb(&i2c_regs->i2cr); 379db84140bSMarek Vasut temp |= I2CR_TX_NO_AK; 380db84140bSMarek Vasut writeb(temp, &i2c_regs->i2cr); 381cdace066SSascha Hauer } 382*30ea41a4SAlison Wang writeb(I2SR_IIF_CLEAR, &i2c_regs->i2sr); 383db84140bSMarek Vasut buf[i] = readb(&i2c_regs->i2dr); 384cdace066SSascha Hauer } 38527a5da02STroy Kisky i2c_imx_stop(i2c_regs); 3867aa57a01STroy Kisky return 0; 387db84140bSMarek Vasut } 388db84140bSMarek Vasut 389db84140bSMarek Vasut /* 390db84140bSMarek Vasut * Write data to I2C device 391db84140bSMarek Vasut */ 392e4ff525fSTroy Kisky int bus_i2c_write(void *base, uchar chip, uint addr, int alen, 393e4ff525fSTroy Kisky const uchar *buf, int len) 394cdace066SSascha Hauer { 395db84140bSMarek Vasut int ret; 396db84140bSMarek Vasut int i; 397e4ff525fSTroy Kisky struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base; 398cdace066SSascha Hauer 399b230ddc2STroy Kisky ret = i2c_init_transfer(i2c_regs, chip, addr, alen); 400cea60b0cSTroy Kisky if (ret < 0) 401db84140bSMarek Vasut return ret; 402cdace066SSascha Hauer 403db84140bSMarek Vasut for (i = 0; i < len; i++) { 404cea60b0cSTroy Kisky ret = tx_byte(i2c_regs, buf[i]); 405cea60b0cSTroy Kisky if (ret < 0) 406c4330d28STroy Kisky break; 407cdace066SSascha Hauer } 40827a5da02STroy Kisky i2c_imx_stop(i2c_regs); 409db84140bSMarek Vasut return ret; 410db84140bSMarek Vasut } 411cfbb88d3STroy Kisky 412e4ff525fSTroy Kisky struct i2c_parms { 413e4ff525fSTroy Kisky void *base; 414e4ff525fSTroy Kisky void *idle_bus_data; 415e4ff525fSTroy Kisky int (*idle_bus_fn)(void *p); 416e4ff525fSTroy Kisky }; 417e4ff525fSTroy Kisky 418e4ff525fSTroy Kisky struct sram_data { 419e4ff525fSTroy Kisky unsigned curr_i2c_bus; 420e4ff525fSTroy Kisky struct i2c_parms i2c_data[3]; 421e4ff525fSTroy Kisky }; 422e4ff525fSTroy Kisky 423e4ff525fSTroy Kisky /* 424e4ff525fSTroy Kisky * For SPL boot some boards need i2c before SDRAM is initialized so force 425e4ff525fSTroy Kisky * variables to live in SRAM 426e4ff525fSTroy Kisky */ 427e4ff525fSTroy Kisky static struct sram_data __attribute__((section(".data"))) srdata; 428e4ff525fSTroy Kisky 429e4ff525fSTroy Kisky void *get_base(void) 430e4ff525fSTroy Kisky { 431e4ff525fSTroy Kisky #ifdef CONFIG_SYS_I2C_BASE 432e4ff525fSTroy Kisky #ifdef CONFIG_I2C_MULTI_BUS 433e4ff525fSTroy Kisky void *ret = srdata.i2c_data[srdata.curr_i2c_bus].base; 434e4ff525fSTroy Kisky if (ret) 435e4ff525fSTroy Kisky return ret; 436e4ff525fSTroy Kisky #endif 437e4ff525fSTroy Kisky return (void *)CONFIG_SYS_I2C_BASE; 438e4ff525fSTroy Kisky #elif defined(CONFIG_I2C_MULTI_BUS) 439e4ff525fSTroy Kisky return srdata.i2c_data[srdata.curr_i2c_bus].base; 440e4ff525fSTroy Kisky #else 441e4ff525fSTroy Kisky return srdata.i2c_data[0].base; 442e4ff525fSTroy Kisky #endif 443e4ff525fSTroy Kisky } 444e4ff525fSTroy Kisky 44596c19bd3STroy Kisky static struct i2c_parms *i2c_get_parms(void *base) 44696c19bd3STroy Kisky { 44796c19bd3STroy Kisky int i = 0; 44896c19bd3STroy Kisky struct i2c_parms *p = srdata.i2c_data; 44996c19bd3STroy Kisky while (i < ARRAY_SIZE(srdata.i2c_data)) { 45096c19bd3STroy Kisky if (p->base == base) 45196c19bd3STroy Kisky return p; 45296c19bd3STroy Kisky p++; 45396c19bd3STroy Kisky i++; 45496c19bd3STroy Kisky } 45596c19bd3STroy Kisky printf("Invalid I2C base: %p\n", base); 45696c19bd3STroy Kisky return NULL; 45796c19bd3STroy Kisky } 45896c19bd3STroy Kisky 45996c19bd3STroy Kisky static int i2c_idle_bus(void *base) 46096c19bd3STroy Kisky { 46196c19bd3STroy Kisky struct i2c_parms *p = i2c_get_parms(base); 46296c19bd3STroy Kisky if (p && p->idle_bus_fn) 46396c19bd3STroy Kisky return p->idle_bus_fn(p->idle_bus_data); 46496c19bd3STroy Kisky return 0; 46596c19bd3STroy Kisky } 46696c19bd3STroy Kisky 4679815326dSTroy Kisky #ifdef CONFIG_I2C_MULTI_BUS 4689815326dSTroy Kisky unsigned int i2c_get_bus_num(void) 4699815326dSTroy Kisky { 4709815326dSTroy Kisky return srdata.curr_i2c_bus; 4719815326dSTroy Kisky } 4729815326dSTroy Kisky 4739815326dSTroy Kisky int i2c_set_bus_num(unsigned bus_idx) 4749815326dSTroy Kisky { 4759815326dSTroy Kisky if (bus_idx >= ARRAY_SIZE(srdata.i2c_data)) 4769815326dSTroy Kisky return -1; 4779815326dSTroy Kisky if (!srdata.i2c_data[bus_idx].base) 4789815326dSTroy Kisky return -1; 4799815326dSTroy Kisky srdata.curr_i2c_bus = bus_idx; 4809815326dSTroy Kisky return 0; 4819815326dSTroy Kisky } 4829815326dSTroy Kisky #endif 4839815326dSTroy Kisky 484e4ff525fSTroy Kisky int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) 485e4ff525fSTroy Kisky { 486e4ff525fSTroy Kisky return bus_i2c_read(get_base(), chip, addr, alen, buf, len); 487e4ff525fSTroy Kisky } 488e4ff525fSTroy Kisky 489e4ff525fSTroy Kisky int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) 490e4ff525fSTroy Kisky { 491e4ff525fSTroy Kisky return bus_i2c_write(get_base(), chip, addr, alen, buf, len); 492e4ff525fSTroy Kisky } 493e4ff525fSTroy Kisky 494cfbb88d3STroy Kisky /* 495cfbb88d3STroy Kisky * Test if a chip at a given address responds (probe the chip) 496cfbb88d3STroy Kisky */ 497cfbb88d3STroy Kisky int i2c_probe(uchar chip) 498cfbb88d3STroy Kisky { 499e4ff525fSTroy Kisky return bus_i2c_write(get_base(), chip, 0, 0, NULL, 0); 500e4ff525fSTroy Kisky } 501e4ff525fSTroy Kisky 502e4ff525fSTroy Kisky void bus_i2c_init(void *base, int speed, int unused, 503e4ff525fSTroy Kisky int (*idle_bus_fn)(void *p), void *idle_bus_data) 504e4ff525fSTroy Kisky { 505e4ff525fSTroy Kisky int i = 0; 506e4ff525fSTroy Kisky struct i2c_parms *p = srdata.i2c_data; 507e4ff525fSTroy Kisky if (!base) 508e4ff525fSTroy Kisky return; 509e4ff525fSTroy Kisky for (;;) { 510e4ff525fSTroy Kisky if (!p->base || (p->base == base)) { 511e4ff525fSTroy Kisky p->base = base; 512e4ff525fSTroy Kisky if (idle_bus_fn) { 513e4ff525fSTroy Kisky p->idle_bus_fn = idle_bus_fn; 514e4ff525fSTroy Kisky p->idle_bus_data = idle_bus_data; 515e4ff525fSTroy Kisky } 516e4ff525fSTroy Kisky break; 517e4ff525fSTroy Kisky } 518e4ff525fSTroy Kisky p++; 519e4ff525fSTroy Kisky i++; 520e4ff525fSTroy Kisky if (i >= ARRAY_SIZE(srdata.i2c_data)) 521e4ff525fSTroy Kisky return; 522e4ff525fSTroy Kisky } 523e4ff525fSTroy Kisky bus_i2c_set_bus_speed(base, speed); 524e4ff525fSTroy Kisky } 525e4ff525fSTroy Kisky 526e4ff525fSTroy Kisky /* 527e4ff525fSTroy Kisky * Init I2C Bus 528e4ff525fSTroy Kisky */ 529e4ff525fSTroy Kisky void i2c_init(int speed, int unused) 530e4ff525fSTroy Kisky { 531e4ff525fSTroy Kisky bus_i2c_init(get_base(), speed, unused, NULL, NULL); 532e4ff525fSTroy Kisky } 533e4ff525fSTroy Kisky 534e4ff525fSTroy Kisky /* 535e4ff525fSTroy Kisky * Set I2C Speed 536e4ff525fSTroy Kisky */ 537e4ff525fSTroy Kisky int i2c_set_bus_speed(unsigned int speed) 538e4ff525fSTroy Kisky { 539e4ff525fSTroy Kisky return bus_i2c_set_bus_speed(get_base(), speed); 540e4ff525fSTroy Kisky } 541e4ff525fSTroy Kisky 542e4ff525fSTroy Kisky /* 543e4ff525fSTroy Kisky * Get I2C Speed 544e4ff525fSTroy Kisky */ 545e4ff525fSTroy Kisky unsigned int i2c_get_bus_speed(void) 546e4ff525fSTroy Kisky { 547e4ff525fSTroy Kisky return bus_i2c_get_bus_speed(get_base()); 548cfbb88d3STroy Kisky } 549