1f4f680aaSMarek Vasut /* 2f4f680aaSMarek Vasut * Freescale i.MX28 I2C Driver 3f4f680aaSMarek Vasut * 4f4f680aaSMarek Vasut * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 5f4f680aaSMarek Vasut * on behalf of DENX Software Engineering GmbH 6f4f680aaSMarek Vasut * 7f4f680aaSMarek Vasut * Partly based on Linux kernel i2c-mxs.c driver: 8f4f680aaSMarek Vasut * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. 9f4f680aaSMarek Vasut * 10f4f680aaSMarek Vasut * Which was based on a (non-working) driver which was: 11f4f680aaSMarek Vasut * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. 12f4f680aaSMarek Vasut * 13f4f680aaSMarek Vasut * This program is free software; you can redistribute it and/or modify 14f4f680aaSMarek Vasut * it under the terms of the GNU General Public License as published by 15f4f680aaSMarek Vasut * the Free Software Foundation; either version 2 of the License, or 16f4f680aaSMarek Vasut * (at your option) any later version. 17f4f680aaSMarek Vasut * 18f4f680aaSMarek Vasut * This program is distributed in the hope that it will be useful, 19f4f680aaSMarek Vasut * but WITHOUT ANY WARRANTY; without even the implied warranty of 20f4f680aaSMarek Vasut * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21f4f680aaSMarek Vasut * GNU General Public License for more details. 22f4f680aaSMarek Vasut * 23f4f680aaSMarek Vasut * You should have received a copy of the GNU General Public License 24f4f680aaSMarek Vasut * along with this program; if not, write to the Free Software 25f4f680aaSMarek Vasut * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26f4f680aaSMarek Vasut * 27f4f680aaSMarek Vasut */ 28f4f680aaSMarek Vasut 29f4f680aaSMarek Vasut #include <common.h> 30f4f680aaSMarek Vasut #include <malloc.h> 31f4f680aaSMarek Vasut #include <asm/errno.h> 32f4f680aaSMarek Vasut #include <asm/io.h> 33f4f680aaSMarek Vasut #include <asm/arch/clock.h> 34f4f680aaSMarek Vasut #include <asm/arch/imx-regs.h> 35f4f680aaSMarek Vasut #include <asm/arch/sys_proto.h> 36f4f680aaSMarek Vasut 37f4f680aaSMarek Vasut #define MXS_I2C_MAX_TIMEOUT 1000000 38f4f680aaSMarek Vasut 39f4f680aaSMarek Vasut void mxs_i2c_reset(void) 40f4f680aaSMarek Vasut { 419c471142SOtavio Salvador struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 42f4f680aaSMarek Vasut int ret; 43*1e2fc0d1SMarek Vasut int speed = i2c_get_bus_speed(); 44f4f680aaSMarek Vasut 45fa7a51cbSOtavio Salvador ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg); 46f4f680aaSMarek Vasut if (ret) { 47f4f680aaSMarek Vasut debug("MXS I2C: Block reset timeout\n"); 48f4f680aaSMarek Vasut return; 49f4f680aaSMarek Vasut } 50f4f680aaSMarek Vasut 51f4f680aaSMarek Vasut writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ | 52f4f680aaSMarek Vasut I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | 53f4f680aaSMarek Vasut I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ, 54f4f680aaSMarek Vasut &i2c_regs->hw_i2c_ctrl1_clr); 55f4f680aaSMarek Vasut 56f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set); 57*1e2fc0d1SMarek Vasut 58*1e2fc0d1SMarek Vasut i2c_set_bus_speed(speed); 59f4f680aaSMarek Vasut } 60f4f680aaSMarek Vasut 61f4f680aaSMarek Vasut void mxs_i2c_setup_read(uint8_t chip, int len) 62f4f680aaSMarek Vasut { 639c471142SOtavio Salvador struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 64f4f680aaSMarek Vasut 65f4f680aaSMarek Vasut writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START | 66f4f680aaSMarek Vasut I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | 67f4f680aaSMarek Vasut (1 << I2C_QUEUECMD_XFER_COUNT_OFFSET), 68f4f680aaSMarek Vasut &i2c_regs->hw_i2c_queuecmd); 69f4f680aaSMarek Vasut 70f4f680aaSMarek Vasut writel((chip << 1) | 1, &i2c_regs->hw_i2c_data); 71f4f680aaSMarek Vasut 72f4f680aaSMarek Vasut writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE | 73f4f680aaSMarek Vasut (len << I2C_QUEUECMD_XFER_COUNT_OFFSET) | 74f4f680aaSMarek Vasut I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd); 75f4f680aaSMarek Vasut 76f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); 77f4f680aaSMarek Vasut } 78f4f680aaSMarek Vasut 79f4f680aaSMarek Vasut void mxs_i2c_write(uchar chip, uint addr, int alen, 80f4f680aaSMarek Vasut uchar *buf, int blen, int stop) 81f4f680aaSMarek Vasut { 829c471142SOtavio Salvador struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 83f4f680aaSMarek Vasut uint32_t data; 84f4f680aaSMarek Vasut int i, remain, off; 85f4f680aaSMarek Vasut 86f4f680aaSMarek Vasut if ((alen > 4) || (alen == 0)) { 87f4f680aaSMarek Vasut debug("MXS I2C: Invalid address length\n"); 88f4f680aaSMarek Vasut return; 89f4f680aaSMarek Vasut } 90f4f680aaSMarek Vasut 91f4f680aaSMarek Vasut if (stop) 92f4f680aaSMarek Vasut stop = I2C_QUEUECMD_POST_SEND_STOP; 93f4f680aaSMarek Vasut 94f4f680aaSMarek Vasut writel(I2C_QUEUECMD_PRE_SEND_START | 95f4f680aaSMarek Vasut I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | 96f4f680aaSMarek Vasut ((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop, 97f4f680aaSMarek Vasut &i2c_regs->hw_i2c_queuecmd); 98f4f680aaSMarek Vasut 99f4f680aaSMarek Vasut data = (chip << 1) << 24; 100f4f680aaSMarek Vasut 101f4f680aaSMarek Vasut for (i = 0; i < alen; i++) { 102f4f680aaSMarek Vasut data >>= 8; 103fa86d1c0STorsten Fleischer data |= ((char *)&addr)[alen - i - 1] << 24; 104f4f680aaSMarek Vasut if ((i & 3) == 2) 105f4f680aaSMarek Vasut writel(data, &i2c_regs->hw_i2c_data); 106f4f680aaSMarek Vasut } 107f4f680aaSMarek Vasut 108f4f680aaSMarek Vasut off = i; 109f4f680aaSMarek Vasut for (; i < off + blen; i++) { 110f4f680aaSMarek Vasut data >>= 8; 111f4f680aaSMarek Vasut data |= buf[i - off] << 24; 112f4f680aaSMarek Vasut if ((i & 3) == 2) 113f4f680aaSMarek Vasut writel(data, &i2c_regs->hw_i2c_data); 114f4f680aaSMarek Vasut } 115f4f680aaSMarek Vasut 116f4f680aaSMarek Vasut remain = 24 - ((i & 3) * 8); 117f4f680aaSMarek Vasut if (remain) 118f4f680aaSMarek Vasut writel(data >> remain, &i2c_regs->hw_i2c_data); 119f4f680aaSMarek Vasut 120f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); 121f4f680aaSMarek Vasut } 122f4f680aaSMarek Vasut 123f4f680aaSMarek Vasut int mxs_i2c_wait_for_ack(void) 124f4f680aaSMarek Vasut { 1259c471142SOtavio Salvador struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 126f4f680aaSMarek Vasut uint32_t tmp; 127f4f680aaSMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 128f4f680aaSMarek Vasut 129f4f680aaSMarek Vasut for (;;) { 130f4f680aaSMarek Vasut tmp = readl(&i2c_regs->hw_i2c_ctrl1); 131f4f680aaSMarek Vasut if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) { 132f4f680aaSMarek Vasut debug("MXS I2C: No slave ACK\n"); 133f4f680aaSMarek Vasut goto err; 134f4f680aaSMarek Vasut } 135f4f680aaSMarek Vasut 136f4f680aaSMarek Vasut if (tmp & ( 137f4f680aaSMarek Vasut I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | 138f4f680aaSMarek Vasut I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) { 139f4f680aaSMarek Vasut debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp); 140f4f680aaSMarek Vasut goto err; 141f4f680aaSMarek Vasut } 142f4f680aaSMarek Vasut 143f4f680aaSMarek Vasut if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ) 144f4f680aaSMarek Vasut break; 145f4f680aaSMarek Vasut 146f4f680aaSMarek Vasut if (!timeout--) { 147f4f680aaSMarek Vasut debug("MXS I2C: Operation timed out\n"); 148f4f680aaSMarek Vasut goto err; 149f4f680aaSMarek Vasut } 150f4f680aaSMarek Vasut 151f4f680aaSMarek Vasut udelay(1); 152f4f680aaSMarek Vasut } 153f4f680aaSMarek Vasut 154f4f680aaSMarek Vasut return 0; 155f4f680aaSMarek Vasut 156f4f680aaSMarek Vasut err: 157f4f680aaSMarek Vasut mxs_i2c_reset(); 158f4f680aaSMarek Vasut return 1; 159f4f680aaSMarek Vasut } 160f4f680aaSMarek Vasut 161f4f680aaSMarek Vasut int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) 162f4f680aaSMarek Vasut { 1639c471142SOtavio Salvador struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 164f4f680aaSMarek Vasut uint32_t tmp = 0; 165f4f680aaSMarek Vasut int ret; 166f4f680aaSMarek Vasut int i; 167f4f680aaSMarek Vasut 168f4f680aaSMarek Vasut mxs_i2c_write(chip, addr, alen, NULL, 0, 0); 169f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 170f4f680aaSMarek Vasut if (ret) { 171f4f680aaSMarek Vasut debug("MXS I2C: Failed writing address\n"); 172f4f680aaSMarek Vasut return ret; 173f4f680aaSMarek Vasut } 174f4f680aaSMarek Vasut 175f4f680aaSMarek Vasut mxs_i2c_setup_read(chip, len); 176f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 177f4f680aaSMarek Vasut if (ret) { 178f4f680aaSMarek Vasut debug("MXS I2C: Failed reading address\n"); 179f4f680aaSMarek Vasut return ret; 180f4f680aaSMarek Vasut } 181f4f680aaSMarek Vasut 182f4f680aaSMarek Vasut for (i = 0; i < len; i++) { 183f4f680aaSMarek Vasut if (!(i & 3)) { 184f4f680aaSMarek Vasut while (readl(&i2c_regs->hw_i2c_queuestat) & 185f4f680aaSMarek Vasut I2C_QUEUESTAT_RD_QUEUE_EMPTY) 186f4f680aaSMarek Vasut ; 187f4f680aaSMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuedata); 188f4f680aaSMarek Vasut } 189f4f680aaSMarek Vasut buffer[i] = tmp & 0xff; 190f4f680aaSMarek Vasut tmp >>= 8; 191f4f680aaSMarek Vasut } 192f4f680aaSMarek Vasut 193f4f680aaSMarek Vasut return 0; 194f4f680aaSMarek Vasut } 195f4f680aaSMarek Vasut 196f4f680aaSMarek Vasut int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) 197f4f680aaSMarek Vasut { 198f4f680aaSMarek Vasut int ret; 199f4f680aaSMarek Vasut mxs_i2c_write(chip, addr, alen, buffer, len, 1); 200f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 201f4f680aaSMarek Vasut if (ret) 202f4f680aaSMarek Vasut debug("MXS I2C: Failed writing address\n"); 203f4f680aaSMarek Vasut 204f4f680aaSMarek Vasut return ret; 205f4f680aaSMarek Vasut } 206f4f680aaSMarek Vasut 207f4f680aaSMarek Vasut int i2c_probe(uchar chip) 208f4f680aaSMarek Vasut { 209f4f680aaSMarek Vasut int ret; 210f4f680aaSMarek Vasut mxs_i2c_write(chip, 0, 1, NULL, 0, 1); 211f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 212f4f680aaSMarek Vasut mxs_i2c_reset(); 213f4f680aaSMarek Vasut return ret; 214f4f680aaSMarek Vasut } 215f4f680aaSMarek Vasut 216f32a470eSMarek Vasut static struct mxs_i2c_speed_table { 217f32a470eSMarek Vasut uint32_t speed; 218f32a470eSMarek Vasut uint32_t timing0; 219f32a470eSMarek Vasut uint32_t timing1; 220f32a470eSMarek Vasut } mxs_i2c_tbl[] = { 221f32a470eSMarek Vasut { 222f32a470eSMarek Vasut 100000, 223f32a470eSMarek Vasut (0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) | 224f32a470eSMarek Vasut (0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET), 225f32a470eSMarek Vasut (0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) | 226f32a470eSMarek Vasut (0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET) 227f32a470eSMarek Vasut }, 228f32a470eSMarek Vasut { 229f32a470eSMarek Vasut 400000, 230f32a470eSMarek Vasut (0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) | 231f32a470eSMarek Vasut (0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET), 232f32a470eSMarek Vasut (0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) | 233f32a470eSMarek Vasut (0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET), 234f32a470eSMarek Vasut } 235f32a470eSMarek Vasut }; 236f32a470eSMarek Vasut 237f32a470eSMarek Vasut static struct mxs_i2c_speed_table *mxs_i2c_speed_to_cfg(uint32_t speed) 238f32a470eSMarek Vasut { 239f32a470eSMarek Vasut int i; 240f32a470eSMarek Vasut for (i = 0; i < ARRAY_SIZE(mxs_i2c_tbl); i++) 241f32a470eSMarek Vasut if (mxs_i2c_tbl[i].speed == speed) 242f32a470eSMarek Vasut return &mxs_i2c_tbl[i]; 243f32a470eSMarek Vasut return NULL; 244f32a470eSMarek Vasut } 245f32a470eSMarek Vasut 246a06f590fSMarek Vasut static uint32_t mxs_i2c_cfg_to_speed(uint32_t timing0, uint32_t timing1) 247a06f590fSMarek Vasut { 248a06f590fSMarek Vasut int i; 249a06f590fSMarek Vasut for (i = 0; i < ARRAY_SIZE(mxs_i2c_tbl); i++) { 250a06f590fSMarek Vasut if (mxs_i2c_tbl[i].timing0 != timing0) 251a06f590fSMarek Vasut continue; 252a06f590fSMarek Vasut if (mxs_i2c_tbl[i].timing1 != timing1) 253a06f590fSMarek Vasut continue; 254a06f590fSMarek Vasut return mxs_i2c_tbl[i].speed; 255a06f590fSMarek Vasut } 256a06f590fSMarek Vasut 257a06f590fSMarek Vasut return 0; 258a06f590fSMarek Vasut } 259a06f590fSMarek Vasut 260a06f590fSMarek Vasut int i2c_set_bus_speed(unsigned int speed) 261a06f590fSMarek Vasut { 262a06f590fSMarek Vasut struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 263a06f590fSMarek Vasut struct mxs_i2c_speed_table *spd = mxs_i2c_speed_to_cfg(speed); 264a06f590fSMarek Vasut 265a06f590fSMarek Vasut if (!spd) { 266a06f590fSMarek Vasut printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed); 267a06f590fSMarek Vasut return -EINVAL; 268a06f590fSMarek Vasut } 269a06f590fSMarek Vasut 270a06f590fSMarek Vasut writel(spd->timing0, &i2c_regs->hw_i2c_timing0); 271a06f590fSMarek Vasut writel(spd->timing1, &i2c_regs->hw_i2c_timing1); 272a06f590fSMarek Vasut 273aff36ea9SMarek Vasut writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) | 274aff36ea9SMarek Vasut (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET), 275a06f590fSMarek Vasut &i2c_regs->hw_i2c_timing2); 276a06f590fSMarek Vasut 277a06f590fSMarek Vasut return 0; 278a06f590fSMarek Vasut } 279a06f590fSMarek Vasut 280a06f590fSMarek Vasut unsigned int i2c_get_bus_speed(void) 281a06f590fSMarek Vasut { 282a06f590fSMarek Vasut struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; 283a06f590fSMarek Vasut uint32_t timing0, timing1; 284a06f590fSMarek Vasut 285a06f590fSMarek Vasut timing0 = readl(&i2c_regs->hw_i2c_timing0); 286a06f590fSMarek Vasut timing1 = readl(&i2c_regs->hw_i2c_timing1); 287a06f590fSMarek Vasut 288a06f590fSMarek Vasut return mxs_i2c_cfg_to_speed(timing0, timing1); 289a06f590fSMarek Vasut } 290a06f590fSMarek Vasut 291f4f680aaSMarek Vasut void i2c_init(int speed, int slaveadd) 292f4f680aaSMarek Vasut { 293f32a470eSMarek Vasut mxs_i2c_reset(); 294a157e0d5SMarek Vasut i2c_set_bus_speed(speed); 295f4f680aaSMarek Vasut 296f4f680aaSMarek Vasut return; 297f4f680aaSMarek Vasut } 298