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