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 * 131a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 14f4f680aaSMarek Vasut */ 15f4f680aaSMarek Vasut 16f4f680aaSMarek Vasut #include <common.h> 17f4f680aaSMarek Vasut #include <malloc.h> 18fa5e2845SMarek Vasut #include <i2c.h> 19f4f680aaSMarek Vasut #include <asm/errno.h> 20f4f680aaSMarek Vasut #include <asm/io.h> 21f4f680aaSMarek Vasut #include <asm/arch/clock.h> 22f4f680aaSMarek Vasut #include <asm/arch/imx-regs.h> 23f4f680aaSMarek Vasut #include <asm/arch/sys_proto.h> 24f4f680aaSMarek Vasut 25f4f680aaSMarek Vasut #define MXS_I2C_MAX_TIMEOUT 1000000 26f4f680aaSMarek Vasut 27*9536099dSMarek Vasut static struct mxs_i2c_regs *mxs_i2c_get_base(struct i2c_adapter *adap) 28*9536099dSMarek Vasut { 29*9536099dSMarek Vasut return (struct mxs_i2c_regs *)MXS_I2C0_BASE; 30*9536099dSMarek Vasut } 31*9536099dSMarek Vasut 3249c28b56SMarek Vasut static void mxs_i2c_reset(void) 33f4f680aaSMarek Vasut { 34*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 35f4f680aaSMarek Vasut int ret; 361e2fc0d1SMarek Vasut int speed = i2c_get_bus_speed(); 37f4f680aaSMarek Vasut 38fa7a51cbSOtavio Salvador ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg); 39f4f680aaSMarek Vasut if (ret) { 40f4f680aaSMarek Vasut debug("MXS I2C: Block reset timeout\n"); 41f4f680aaSMarek Vasut return; 42f4f680aaSMarek Vasut } 43f4f680aaSMarek Vasut 44f4f680aaSMarek Vasut writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ | 45f4f680aaSMarek Vasut I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | 46f4f680aaSMarek Vasut I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ, 47f4f680aaSMarek Vasut &i2c_regs->hw_i2c_ctrl1_clr); 48f4f680aaSMarek Vasut 49f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set); 501e2fc0d1SMarek Vasut 511e2fc0d1SMarek Vasut i2c_set_bus_speed(speed); 52f4f680aaSMarek Vasut } 53f4f680aaSMarek Vasut 5449c28b56SMarek Vasut static void mxs_i2c_setup_read(uint8_t chip, int len) 55f4f680aaSMarek Vasut { 56*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 57f4f680aaSMarek Vasut 58f4f680aaSMarek Vasut writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START | 59f4f680aaSMarek Vasut I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | 60f4f680aaSMarek Vasut (1 << I2C_QUEUECMD_XFER_COUNT_OFFSET), 61f4f680aaSMarek Vasut &i2c_regs->hw_i2c_queuecmd); 62f4f680aaSMarek Vasut 63f4f680aaSMarek Vasut writel((chip << 1) | 1, &i2c_regs->hw_i2c_data); 64f4f680aaSMarek Vasut 65f4f680aaSMarek Vasut writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE | 66f4f680aaSMarek Vasut (len << I2C_QUEUECMD_XFER_COUNT_OFFSET) | 67f4f680aaSMarek Vasut I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd); 68f4f680aaSMarek Vasut 69f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); 70f4f680aaSMarek Vasut } 71f4f680aaSMarek Vasut 72d22643e7SMarek Vasut static int mxs_i2c_write(uchar chip, uint addr, int alen, 73f4f680aaSMarek Vasut uchar *buf, int blen, int stop) 74f4f680aaSMarek Vasut { 75*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 76d22643e7SMarek Vasut uint32_t data, tmp; 77f4f680aaSMarek Vasut int i, remain, off; 78d22643e7SMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 79f4f680aaSMarek Vasut 80f4f680aaSMarek Vasut if ((alen > 4) || (alen == 0)) { 81f4f680aaSMarek Vasut debug("MXS I2C: Invalid address length\n"); 82d22643e7SMarek Vasut return -EINVAL; 83f4f680aaSMarek Vasut } 84f4f680aaSMarek Vasut 85f4f680aaSMarek Vasut if (stop) 86f4f680aaSMarek Vasut stop = I2C_QUEUECMD_POST_SEND_STOP; 87f4f680aaSMarek Vasut 88f4f680aaSMarek Vasut writel(I2C_QUEUECMD_PRE_SEND_START | 89f4f680aaSMarek Vasut I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | 90f4f680aaSMarek Vasut ((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop, 91f4f680aaSMarek Vasut &i2c_regs->hw_i2c_queuecmd); 92f4f680aaSMarek Vasut 93f4f680aaSMarek Vasut data = (chip << 1) << 24; 94f4f680aaSMarek Vasut 95f4f680aaSMarek Vasut for (i = 0; i < alen; i++) { 96f4f680aaSMarek Vasut data >>= 8; 97fa86d1c0STorsten Fleischer data |= ((char *)&addr)[alen - i - 1] << 24; 98f4f680aaSMarek Vasut if ((i & 3) == 2) 99f4f680aaSMarek Vasut writel(data, &i2c_regs->hw_i2c_data); 100f4f680aaSMarek Vasut } 101f4f680aaSMarek Vasut 102f4f680aaSMarek Vasut off = i; 103f4f680aaSMarek Vasut for (; i < off + blen; i++) { 104f4f680aaSMarek Vasut data >>= 8; 105f4f680aaSMarek Vasut data |= buf[i - off] << 24; 106f4f680aaSMarek Vasut if ((i & 3) == 2) 107f4f680aaSMarek Vasut writel(data, &i2c_regs->hw_i2c_data); 108f4f680aaSMarek Vasut } 109f4f680aaSMarek Vasut 110f4f680aaSMarek Vasut remain = 24 - ((i & 3) * 8); 111f4f680aaSMarek Vasut if (remain) 112f4f680aaSMarek Vasut writel(data >> remain, &i2c_regs->hw_i2c_data); 113f4f680aaSMarek Vasut 114f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); 115d22643e7SMarek Vasut 116d22643e7SMarek Vasut while (--timeout) { 117d22643e7SMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuestat); 118d22643e7SMarek Vasut if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY) 119d22643e7SMarek Vasut break; 120d22643e7SMarek Vasut } 121d22643e7SMarek Vasut 122d22643e7SMarek Vasut if (!timeout) { 123d22643e7SMarek Vasut debug("MXS I2C: Failed transmitting data!\n"); 124d22643e7SMarek Vasut return -EINVAL; 125d22643e7SMarek Vasut } 126d22643e7SMarek Vasut 127d22643e7SMarek Vasut return 0; 128f4f680aaSMarek Vasut } 129f4f680aaSMarek Vasut 13049c28b56SMarek Vasut static int mxs_i2c_wait_for_ack(void) 131f4f680aaSMarek Vasut { 132*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 133f4f680aaSMarek Vasut uint32_t tmp; 134f4f680aaSMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 135f4f680aaSMarek Vasut 136f4f680aaSMarek Vasut for (;;) { 137f4f680aaSMarek Vasut tmp = readl(&i2c_regs->hw_i2c_ctrl1); 138f4f680aaSMarek Vasut if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) { 139f4f680aaSMarek Vasut debug("MXS I2C: No slave ACK\n"); 140f4f680aaSMarek Vasut goto err; 141f4f680aaSMarek Vasut } 142f4f680aaSMarek Vasut 143f4f680aaSMarek Vasut if (tmp & ( 144f4f680aaSMarek Vasut I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | 145f4f680aaSMarek Vasut I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) { 146f4f680aaSMarek Vasut debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp); 147f4f680aaSMarek Vasut goto err; 148f4f680aaSMarek Vasut } 149f4f680aaSMarek Vasut 150f4f680aaSMarek Vasut if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ) 151f4f680aaSMarek Vasut break; 152f4f680aaSMarek Vasut 153f4f680aaSMarek Vasut if (!timeout--) { 154f4f680aaSMarek Vasut debug("MXS I2C: Operation timed out\n"); 155f4f680aaSMarek Vasut goto err; 156f4f680aaSMarek Vasut } 157f4f680aaSMarek Vasut 158f4f680aaSMarek Vasut udelay(1); 159f4f680aaSMarek Vasut } 160f4f680aaSMarek Vasut 161f4f680aaSMarek Vasut return 0; 162f4f680aaSMarek Vasut 163f4f680aaSMarek Vasut err: 164f4f680aaSMarek Vasut mxs_i2c_reset(); 165f4f680aaSMarek Vasut return 1; 166f4f680aaSMarek Vasut } 167f4f680aaSMarek Vasut 168f4f680aaSMarek Vasut int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) 169f4f680aaSMarek Vasut { 170*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 171f4f680aaSMarek Vasut uint32_t tmp = 0; 17212491355SMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 173f4f680aaSMarek Vasut int ret; 174f4f680aaSMarek Vasut int i; 175f4f680aaSMarek Vasut 176d22643e7SMarek Vasut ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0); 177d22643e7SMarek Vasut if (ret) { 178d22643e7SMarek Vasut debug("MXS I2C: Failed writing address\n"); 179d22643e7SMarek Vasut return ret; 180d22643e7SMarek Vasut } 181d22643e7SMarek Vasut 182f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 183f4f680aaSMarek Vasut if (ret) { 184f4f680aaSMarek Vasut debug("MXS I2C: Failed writing address\n"); 185f4f680aaSMarek Vasut return ret; 186f4f680aaSMarek Vasut } 187f4f680aaSMarek Vasut 188f4f680aaSMarek Vasut mxs_i2c_setup_read(chip, len); 189f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 190f4f680aaSMarek Vasut if (ret) { 191f4f680aaSMarek Vasut debug("MXS I2C: Failed reading address\n"); 192f4f680aaSMarek Vasut return ret; 193f4f680aaSMarek Vasut } 194f4f680aaSMarek Vasut 195f4f680aaSMarek Vasut for (i = 0; i < len; i++) { 196f4f680aaSMarek Vasut if (!(i & 3)) { 19712491355SMarek Vasut while (--timeout) { 19812491355SMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuestat); 19912491355SMarek Vasut if (!(tmp & I2C_QUEUESTAT_RD_QUEUE_EMPTY)) 20012491355SMarek Vasut break; 20112491355SMarek Vasut } 20212491355SMarek Vasut 20312491355SMarek Vasut if (!timeout) { 20412491355SMarek Vasut debug("MXS I2C: Failed receiving data!\n"); 20512491355SMarek Vasut return -ETIMEDOUT; 20612491355SMarek Vasut } 20712491355SMarek Vasut 208f4f680aaSMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuedata); 209f4f680aaSMarek Vasut } 210f4f680aaSMarek Vasut buffer[i] = tmp & 0xff; 211f4f680aaSMarek Vasut tmp >>= 8; 212f4f680aaSMarek Vasut } 213f4f680aaSMarek Vasut 214f4f680aaSMarek Vasut return 0; 215f4f680aaSMarek Vasut } 216f4f680aaSMarek Vasut 217f4f680aaSMarek Vasut int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) 218f4f680aaSMarek Vasut { 219f4f680aaSMarek Vasut int ret; 220d22643e7SMarek Vasut ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1); 221d22643e7SMarek Vasut if (ret) { 222d22643e7SMarek Vasut debug("MXS I2C: Failed writing address\n"); 223d22643e7SMarek Vasut return ret; 224d22643e7SMarek Vasut } 225d22643e7SMarek Vasut 226f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 227f4f680aaSMarek Vasut if (ret) 228f4f680aaSMarek Vasut debug("MXS I2C: Failed writing address\n"); 229f4f680aaSMarek Vasut 230f4f680aaSMarek Vasut return ret; 231f4f680aaSMarek Vasut } 232f4f680aaSMarek Vasut 233f4f680aaSMarek Vasut int i2c_probe(uchar chip) 234f4f680aaSMarek Vasut { 235f4f680aaSMarek Vasut int ret; 236d22643e7SMarek Vasut ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1); 237d22643e7SMarek Vasut if (!ret) 238f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 239f4f680aaSMarek Vasut mxs_i2c_reset(); 240f4f680aaSMarek Vasut return ret; 241f4f680aaSMarek Vasut } 242f4f680aaSMarek Vasut 243a06f590fSMarek Vasut int i2c_set_bus_speed(unsigned int speed) 244a06f590fSMarek Vasut { 245*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 246fa5e2845SMarek Vasut /* 247fa5e2845SMarek Vasut * The timing derivation algorithm. There is no documentation for this 248fa5e2845SMarek Vasut * algorithm available, it was derived by using the scope and fiddling 249fa5e2845SMarek Vasut * with constants until the result observed on the scope was good enough 250fa5e2845SMarek Vasut * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be 251fa5e2845SMarek Vasut * possible to assume the algorithm works for other frequencies as well. 252fa5e2845SMarek Vasut * 253fa5e2845SMarek Vasut * Note it was necessary to cap the frequency on both ends as it's not 254fa5e2845SMarek Vasut * possible to configure completely arbitrary frequency for the I2C bus 255fa5e2845SMarek Vasut * clock. 256fa5e2845SMarek Vasut */ 257fa5e2845SMarek Vasut uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); 258fa5e2845SMarek Vasut uint32_t base = ((clk / speed) - 38) / 2; 259fa5e2845SMarek Vasut uint16_t high_count = base + 3; 260fa5e2845SMarek Vasut uint16_t low_count = base - 3; 261fa5e2845SMarek Vasut uint16_t rcv_count = (high_count * 3) / 4; 262fa5e2845SMarek Vasut uint16_t xmit_count = low_count / 4; 263a06f590fSMarek Vasut 264fa5e2845SMarek Vasut if (speed > 540000) { 265fa5e2845SMarek Vasut printf("MXS I2C: Speed too high (%d Hz)\n", speed); 266a06f590fSMarek Vasut return -EINVAL; 267a06f590fSMarek Vasut } 268a06f590fSMarek Vasut 269fa5e2845SMarek Vasut if (speed < 12000) { 270fa5e2845SMarek Vasut printf("MXS I2C: Speed too low (%d Hz)\n", speed); 271fa5e2845SMarek Vasut return -EINVAL; 272fa5e2845SMarek Vasut } 273fa5e2845SMarek Vasut 274fa5e2845SMarek Vasut writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0); 275fa5e2845SMarek Vasut writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1); 276a06f590fSMarek Vasut 277aff36ea9SMarek Vasut writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) | 278aff36ea9SMarek Vasut (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET), 279a06f590fSMarek Vasut &i2c_regs->hw_i2c_timing2); 280a06f590fSMarek Vasut 281a06f590fSMarek Vasut return 0; 282a06f590fSMarek Vasut } 283a06f590fSMarek Vasut 284a06f590fSMarek Vasut unsigned int i2c_get_bus_speed(void) 285a06f590fSMarek Vasut { 286*9536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 287fa5e2845SMarek Vasut uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); 288fa5e2845SMarek Vasut uint32_t timing0; 289a06f590fSMarek Vasut 290a06f590fSMarek Vasut timing0 = readl(&i2c_regs->hw_i2c_timing0); 291fa5e2845SMarek Vasut /* 292fa5e2845SMarek Vasut * This is a reverse version of the algorithm presented in 293fa5e2845SMarek Vasut * i2c_set_bus_speed(). Please refer there for details. 294fa5e2845SMarek Vasut */ 295fa5e2845SMarek Vasut return clk / ((((timing0 >> 16) - 3) * 2) + 38); 296a06f590fSMarek Vasut } 297a06f590fSMarek Vasut 298f4f680aaSMarek Vasut void i2c_init(int speed, int slaveadd) 299f4f680aaSMarek Vasut { 300f32a470eSMarek Vasut mxs_i2c_reset(); 301a157e0d5SMarek Vasut i2c_set_bus_speed(speed); 302f4f680aaSMarek Vasut 303f4f680aaSMarek Vasut return; 304f4f680aaSMarek Vasut } 305