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 279536099dSMarek Vasut static struct mxs_i2c_regs *mxs_i2c_get_base(struct i2c_adapter *adap) 289536099dSMarek Vasut { 299536099dSMarek Vasut return (struct mxs_i2c_regs *)MXS_I2C0_BASE; 309536099dSMarek Vasut } 319536099dSMarek Vasut 32*1fa96e80SMarek Vasut static unsigned int mxs_i2c_get_bus_speed(void) 33*1fa96e80SMarek Vasut { 34*1fa96e80SMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 35*1fa96e80SMarek Vasut uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); 36*1fa96e80SMarek Vasut uint32_t timing0; 37*1fa96e80SMarek Vasut 38*1fa96e80SMarek Vasut timing0 = readl(&i2c_regs->hw_i2c_timing0); 39*1fa96e80SMarek Vasut /* 40*1fa96e80SMarek Vasut * This is a reverse version of the algorithm presented in 41*1fa96e80SMarek Vasut * i2c_set_bus_speed(). Please refer there for details. 42*1fa96e80SMarek Vasut */ 43*1fa96e80SMarek Vasut return clk / ((((timing0 >> 16) - 3) * 2) + 38); 44*1fa96e80SMarek Vasut } 45*1fa96e80SMarek Vasut 4649c28b56SMarek Vasut static void mxs_i2c_reset(void) 47f4f680aaSMarek Vasut { 489536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 49f4f680aaSMarek Vasut int ret; 50*1fa96e80SMarek Vasut int speed = mxs_i2c_get_bus_speed(); 51f4f680aaSMarek Vasut 52fa7a51cbSOtavio Salvador ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg); 53f4f680aaSMarek Vasut if (ret) { 54f4f680aaSMarek Vasut debug("MXS I2C: Block reset timeout\n"); 55f4f680aaSMarek Vasut return; 56f4f680aaSMarek Vasut } 57f4f680aaSMarek Vasut 58f4f680aaSMarek Vasut writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ | 59f4f680aaSMarek Vasut I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | 60f4f680aaSMarek Vasut I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ, 61f4f680aaSMarek Vasut &i2c_regs->hw_i2c_ctrl1_clr); 62f4f680aaSMarek Vasut 63f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set); 641e2fc0d1SMarek Vasut 651e2fc0d1SMarek Vasut i2c_set_bus_speed(speed); 66f4f680aaSMarek Vasut } 67f4f680aaSMarek Vasut 6849c28b56SMarek Vasut static void mxs_i2c_setup_read(uint8_t chip, int len) 69f4f680aaSMarek Vasut { 709536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 71f4f680aaSMarek Vasut 72f4f680aaSMarek Vasut writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START | 73f4f680aaSMarek Vasut I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | 74f4f680aaSMarek Vasut (1 << I2C_QUEUECMD_XFER_COUNT_OFFSET), 75f4f680aaSMarek Vasut &i2c_regs->hw_i2c_queuecmd); 76f4f680aaSMarek Vasut 77f4f680aaSMarek Vasut writel((chip << 1) | 1, &i2c_regs->hw_i2c_data); 78f4f680aaSMarek Vasut 79f4f680aaSMarek Vasut writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE | 80f4f680aaSMarek Vasut (len << I2C_QUEUECMD_XFER_COUNT_OFFSET) | 81f4f680aaSMarek Vasut I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd); 82f4f680aaSMarek Vasut 83f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); 84f4f680aaSMarek Vasut } 85f4f680aaSMarek Vasut 86d22643e7SMarek Vasut static int mxs_i2c_write(uchar chip, uint addr, int alen, 87f4f680aaSMarek Vasut uchar *buf, int blen, int stop) 88f4f680aaSMarek Vasut { 899536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 90d22643e7SMarek Vasut uint32_t data, tmp; 91f4f680aaSMarek Vasut int i, remain, off; 92d22643e7SMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 93f4f680aaSMarek Vasut 94f4f680aaSMarek Vasut if ((alen > 4) || (alen == 0)) { 95f4f680aaSMarek Vasut debug("MXS I2C: Invalid address length\n"); 96d22643e7SMarek Vasut return -EINVAL; 97f4f680aaSMarek Vasut } 98f4f680aaSMarek Vasut 99f4f680aaSMarek Vasut if (stop) 100f4f680aaSMarek Vasut stop = I2C_QUEUECMD_POST_SEND_STOP; 101f4f680aaSMarek Vasut 102f4f680aaSMarek Vasut writel(I2C_QUEUECMD_PRE_SEND_START | 103f4f680aaSMarek Vasut I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | 104f4f680aaSMarek Vasut ((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop, 105f4f680aaSMarek Vasut &i2c_regs->hw_i2c_queuecmd); 106f4f680aaSMarek Vasut 107f4f680aaSMarek Vasut data = (chip << 1) << 24; 108f4f680aaSMarek Vasut 109f4f680aaSMarek Vasut for (i = 0; i < alen; i++) { 110f4f680aaSMarek Vasut data >>= 8; 111fa86d1c0STorsten Fleischer data |= ((char *)&addr)[alen - i - 1] << 24; 112f4f680aaSMarek Vasut if ((i & 3) == 2) 113f4f680aaSMarek Vasut writel(data, &i2c_regs->hw_i2c_data); 114f4f680aaSMarek Vasut } 115f4f680aaSMarek Vasut 116f4f680aaSMarek Vasut off = i; 117f4f680aaSMarek Vasut for (; i < off + blen; i++) { 118f4f680aaSMarek Vasut data >>= 8; 119f4f680aaSMarek Vasut data |= buf[i - off] << 24; 120f4f680aaSMarek Vasut if ((i & 3) == 2) 121f4f680aaSMarek Vasut writel(data, &i2c_regs->hw_i2c_data); 122f4f680aaSMarek Vasut } 123f4f680aaSMarek Vasut 124f4f680aaSMarek Vasut remain = 24 - ((i & 3) * 8); 125f4f680aaSMarek Vasut if (remain) 126f4f680aaSMarek Vasut writel(data >> remain, &i2c_regs->hw_i2c_data); 127f4f680aaSMarek Vasut 128f4f680aaSMarek Vasut writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); 129d22643e7SMarek Vasut 130d22643e7SMarek Vasut while (--timeout) { 131d22643e7SMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuestat); 132d22643e7SMarek Vasut if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY) 133d22643e7SMarek Vasut break; 134d22643e7SMarek Vasut } 135d22643e7SMarek Vasut 136d22643e7SMarek Vasut if (!timeout) { 137d22643e7SMarek Vasut debug("MXS I2C: Failed transmitting data!\n"); 138d22643e7SMarek Vasut return -EINVAL; 139d22643e7SMarek Vasut } 140d22643e7SMarek Vasut 141d22643e7SMarek Vasut return 0; 142f4f680aaSMarek Vasut } 143f4f680aaSMarek Vasut 14449c28b56SMarek Vasut static int mxs_i2c_wait_for_ack(void) 145f4f680aaSMarek Vasut { 1469536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 147f4f680aaSMarek Vasut uint32_t tmp; 148f4f680aaSMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 149f4f680aaSMarek Vasut 150f4f680aaSMarek Vasut for (;;) { 151f4f680aaSMarek Vasut tmp = readl(&i2c_regs->hw_i2c_ctrl1); 152f4f680aaSMarek Vasut if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) { 153f4f680aaSMarek Vasut debug("MXS I2C: No slave ACK\n"); 154f4f680aaSMarek Vasut goto err; 155f4f680aaSMarek Vasut } 156f4f680aaSMarek Vasut 157f4f680aaSMarek Vasut if (tmp & ( 158f4f680aaSMarek Vasut I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | 159f4f680aaSMarek Vasut I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) { 160f4f680aaSMarek Vasut debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp); 161f4f680aaSMarek Vasut goto err; 162f4f680aaSMarek Vasut } 163f4f680aaSMarek Vasut 164f4f680aaSMarek Vasut if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ) 165f4f680aaSMarek Vasut break; 166f4f680aaSMarek Vasut 167f4f680aaSMarek Vasut if (!timeout--) { 168f4f680aaSMarek Vasut debug("MXS I2C: Operation timed out\n"); 169f4f680aaSMarek Vasut goto err; 170f4f680aaSMarek Vasut } 171f4f680aaSMarek Vasut 172f4f680aaSMarek Vasut udelay(1); 173f4f680aaSMarek Vasut } 174f4f680aaSMarek Vasut 175f4f680aaSMarek Vasut return 0; 176f4f680aaSMarek Vasut 177f4f680aaSMarek Vasut err: 178f4f680aaSMarek Vasut mxs_i2c_reset(); 179f4f680aaSMarek Vasut return 1; 180f4f680aaSMarek Vasut } 181f4f680aaSMarek Vasut 182*1fa96e80SMarek Vasut static int mxs_i2c_if_read(struct i2c_adapter *adap, uint8_t chip, 183*1fa96e80SMarek Vasut uint addr, int alen, uint8_t *buffer, 184*1fa96e80SMarek Vasut int len) 185f4f680aaSMarek Vasut { 1869536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 187f4f680aaSMarek Vasut uint32_t tmp = 0; 18812491355SMarek Vasut int timeout = MXS_I2C_MAX_TIMEOUT; 189f4f680aaSMarek Vasut int ret; 190f4f680aaSMarek Vasut int i; 191f4f680aaSMarek Vasut 192d22643e7SMarek Vasut ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0); 193d22643e7SMarek Vasut if (ret) { 194d22643e7SMarek Vasut debug("MXS I2C: Failed writing address\n"); 195d22643e7SMarek Vasut return ret; 196d22643e7SMarek Vasut } 197d22643e7SMarek Vasut 198f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 199f4f680aaSMarek Vasut if (ret) { 200f4f680aaSMarek Vasut debug("MXS I2C: Failed writing address\n"); 201f4f680aaSMarek Vasut return ret; 202f4f680aaSMarek Vasut } 203f4f680aaSMarek Vasut 204f4f680aaSMarek Vasut mxs_i2c_setup_read(chip, len); 205f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 206f4f680aaSMarek Vasut if (ret) { 207f4f680aaSMarek Vasut debug("MXS I2C: Failed reading address\n"); 208f4f680aaSMarek Vasut return ret; 209f4f680aaSMarek Vasut } 210f4f680aaSMarek Vasut 211f4f680aaSMarek Vasut for (i = 0; i < len; i++) { 212f4f680aaSMarek Vasut if (!(i & 3)) { 21312491355SMarek Vasut while (--timeout) { 21412491355SMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuestat); 21512491355SMarek Vasut if (!(tmp & I2C_QUEUESTAT_RD_QUEUE_EMPTY)) 21612491355SMarek Vasut break; 21712491355SMarek Vasut } 21812491355SMarek Vasut 21912491355SMarek Vasut if (!timeout) { 22012491355SMarek Vasut debug("MXS I2C: Failed receiving data!\n"); 22112491355SMarek Vasut return -ETIMEDOUT; 22212491355SMarek Vasut } 22312491355SMarek Vasut 224f4f680aaSMarek Vasut tmp = readl(&i2c_regs->hw_i2c_queuedata); 225f4f680aaSMarek Vasut } 226f4f680aaSMarek Vasut buffer[i] = tmp & 0xff; 227f4f680aaSMarek Vasut tmp >>= 8; 228f4f680aaSMarek Vasut } 229f4f680aaSMarek Vasut 230f4f680aaSMarek Vasut return 0; 231f4f680aaSMarek Vasut } 232f4f680aaSMarek Vasut 233*1fa96e80SMarek Vasut static int mxs_i2c_if_write(struct i2c_adapter *adap, uint8_t chip, 234*1fa96e80SMarek Vasut uint addr, int alen, uint8_t *buffer, 235*1fa96e80SMarek Vasut int len) 236f4f680aaSMarek Vasut { 237f4f680aaSMarek Vasut int ret; 238d22643e7SMarek Vasut ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1); 239d22643e7SMarek Vasut if (ret) { 240d22643e7SMarek Vasut debug("MXS I2C: Failed writing address\n"); 241d22643e7SMarek Vasut return ret; 242d22643e7SMarek Vasut } 243d22643e7SMarek Vasut 244f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 245f4f680aaSMarek Vasut if (ret) 246f4f680aaSMarek Vasut debug("MXS I2C: Failed writing address\n"); 247f4f680aaSMarek Vasut 248f4f680aaSMarek Vasut return ret; 249f4f680aaSMarek Vasut } 250f4f680aaSMarek Vasut 251*1fa96e80SMarek Vasut static int mxs_i2c_probe(struct i2c_adapter *adap, uint8_t chip) 252f4f680aaSMarek Vasut { 253f4f680aaSMarek Vasut int ret; 254d22643e7SMarek Vasut ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1); 255d22643e7SMarek Vasut if (!ret) 256f4f680aaSMarek Vasut ret = mxs_i2c_wait_for_ack(); 257f4f680aaSMarek Vasut mxs_i2c_reset(); 258f4f680aaSMarek Vasut return ret; 259f4f680aaSMarek Vasut } 260f4f680aaSMarek Vasut 261*1fa96e80SMarek Vasut static uint mxs_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed) 262a06f590fSMarek Vasut { 2639536099dSMarek Vasut struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL); 264fa5e2845SMarek Vasut /* 265fa5e2845SMarek Vasut * The timing derivation algorithm. There is no documentation for this 266fa5e2845SMarek Vasut * algorithm available, it was derived by using the scope and fiddling 267fa5e2845SMarek Vasut * with constants until the result observed on the scope was good enough 268fa5e2845SMarek Vasut * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be 269fa5e2845SMarek Vasut * possible to assume the algorithm works for other frequencies as well. 270fa5e2845SMarek Vasut * 271fa5e2845SMarek Vasut * Note it was necessary to cap the frequency on both ends as it's not 272fa5e2845SMarek Vasut * possible to configure completely arbitrary frequency for the I2C bus 273fa5e2845SMarek Vasut * clock. 274fa5e2845SMarek Vasut */ 275fa5e2845SMarek Vasut uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); 276fa5e2845SMarek Vasut uint32_t base = ((clk / speed) - 38) / 2; 277fa5e2845SMarek Vasut uint16_t high_count = base + 3; 278fa5e2845SMarek Vasut uint16_t low_count = base - 3; 279fa5e2845SMarek Vasut uint16_t rcv_count = (high_count * 3) / 4; 280fa5e2845SMarek Vasut uint16_t xmit_count = low_count / 4; 281a06f590fSMarek Vasut 282fa5e2845SMarek Vasut if (speed > 540000) { 283fa5e2845SMarek Vasut printf("MXS I2C: Speed too high (%d Hz)\n", speed); 284a06f590fSMarek Vasut return -EINVAL; 285a06f590fSMarek Vasut } 286a06f590fSMarek Vasut 287fa5e2845SMarek Vasut if (speed < 12000) { 288fa5e2845SMarek Vasut printf("MXS I2C: Speed too low (%d Hz)\n", speed); 289fa5e2845SMarek Vasut return -EINVAL; 290fa5e2845SMarek Vasut } 291fa5e2845SMarek Vasut 292fa5e2845SMarek Vasut writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0); 293fa5e2845SMarek Vasut writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1); 294a06f590fSMarek Vasut 295aff36ea9SMarek Vasut writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) | 296aff36ea9SMarek Vasut (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET), 297a06f590fSMarek Vasut &i2c_regs->hw_i2c_timing2); 298a06f590fSMarek Vasut 299a06f590fSMarek Vasut return 0; 300a06f590fSMarek Vasut } 301a06f590fSMarek Vasut 302*1fa96e80SMarek Vasut static void mxs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) 303f4f680aaSMarek Vasut { 304f32a470eSMarek Vasut mxs_i2c_reset(); 305a157e0d5SMarek Vasut i2c_set_bus_speed(speed); 306f4f680aaSMarek Vasut 307f4f680aaSMarek Vasut return; 308f4f680aaSMarek Vasut } 309*1fa96e80SMarek Vasut 310*1fa96e80SMarek Vasut U_BOOT_I2C_ADAP_COMPLETE(mxs0, mxs_i2c_init, mxs_i2c_probe, 311*1fa96e80SMarek Vasut mxs_i2c_if_read, mxs_i2c_if_write, 312*1fa96e80SMarek Vasut mxs_i2c_set_bus_speed, 313*1fa96e80SMarek Vasut CONFIG_SYS_I2C_SPEED, 0, 0) 314