blob: cc313a6937a80f0da8886fe3ebc1b3d05519ac88 [file] [log] [blame]
Marek Vasutf4f680a2011-11-08 23:18:12 +00001/*
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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020013 * SPDX-License-Identifier: GPL-2.0+
Marek Vasutf4f680a2011-11-08 23:18:12 +000014 */
15
16#include <common.h>
17#include <malloc.h>
Marek Vasutfa5e2842012-11-30 18:17:07 +000018#include <i2c.h>
Marek Vasutf4f680a2011-11-08 23:18:12 +000019#include <asm/errno.h>
20#include <asm/io.h>
21#include <asm/arch/clock.h>
22#include <asm/arch/imx-regs.h>
23#include <asm/arch/sys_proto.h>
24
25#define MXS_I2C_MAX_TIMEOUT 1000000
26
Marek Vasut95360992014-10-20 00:23:40 +020027static struct mxs_i2c_regs *mxs_i2c_get_base(struct i2c_adapter *adap)
28{
29 return (struct mxs_i2c_regs *)MXS_I2C0_BASE;
30}
31
Marek Vasut49c28b52012-12-16 02:48:16 +000032static void mxs_i2c_reset(void)
Marek Vasutf4f680a2011-11-08 23:18:12 +000033{
Marek Vasut95360992014-10-20 00:23:40 +020034 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutf4f680a2011-11-08 23:18:12 +000035 int ret;
Marek Vasut1e2fc0d2012-11-30 18:17:06 +000036 int speed = i2c_get_bus_speed();
Marek Vasutf4f680a2011-11-08 23:18:12 +000037
Otavio Salvadorfa7a51c2012-08-13 09:53:12 +000038 ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
Marek Vasutf4f680a2011-11-08 23:18:12 +000039 if (ret) {
40 debug("MXS I2C: Block reset timeout\n");
41 return;
42 }
43
44 writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ |
45 I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
46 I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ,
47 &i2c_regs->hw_i2c_ctrl1_clr);
48
49 writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
Marek Vasut1e2fc0d2012-11-30 18:17:06 +000050
51 i2c_set_bus_speed(speed);
Marek Vasutf4f680a2011-11-08 23:18:12 +000052}
53
Marek Vasut49c28b52012-12-16 02:48:16 +000054static void mxs_i2c_setup_read(uint8_t chip, int len)
Marek Vasutf4f680a2011-11-08 23:18:12 +000055{
Marek Vasut95360992014-10-20 00:23:40 +020056 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutf4f680a2011-11-08 23:18:12 +000057
58 writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START |
59 I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
60 (1 << I2C_QUEUECMD_XFER_COUNT_OFFSET),
61 &i2c_regs->hw_i2c_queuecmd);
62
63 writel((chip << 1) | 1, &i2c_regs->hw_i2c_data);
64
65 writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE |
66 (len << I2C_QUEUECMD_XFER_COUNT_OFFSET) |
67 I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd);
68
69 writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
70}
71
Marek Vasutd22643e2014-02-06 02:59:34 +010072static int mxs_i2c_write(uchar chip, uint addr, int alen,
Marek Vasutf4f680a2011-11-08 23:18:12 +000073 uchar *buf, int blen, int stop)
74{
Marek Vasut95360992014-10-20 00:23:40 +020075 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutd22643e2014-02-06 02:59:34 +010076 uint32_t data, tmp;
Marek Vasutf4f680a2011-11-08 23:18:12 +000077 int i, remain, off;
Marek Vasutd22643e2014-02-06 02:59:34 +010078 int timeout = MXS_I2C_MAX_TIMEOUT;
Marek Vasutf4f680a2011-11-08 23:18:12 +000079
80 if ((alen > 4) || (alen == 0)) {
81 debug("MXS I2C: Invalid address length\n");
Marek Vasutd22643e2014-02-06 02:59:34 +010082 return -EINVAL;
Marek Vasutf4f680a2011-11-08 23:18:12 +000083 }
84
85 if (stop)
86 stop = I2C_QUEUECMD_POST_SEND_STOP;
87
88 writel(I2C_QUEUECMD_PRE_SEND_START |
89 I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
90 ((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop,
91 &i2c_regs->hw_i2c_queuecmd);
92
93 data = (chip << 1) << 24;
94
95 for (i = 0; i < alen; i++) {
96 data >>= 8;
Torsten Fleischerfa86d1c2012-04-17 05:37:45 +000097 data |= ((char *)&addr)[alen - i - 1] << 24;
Marek Vasutf4f680a2011-11-08 23:18:12 +000098 if ((i & 3) == 2)
99 writel(data, &i2c_regs->hw_i2c_data);
100 }
101
102 off = i;
103 for (; i < off + blen; i++) {
104 data >>= 8;
105 data |= buf[i - off] << 24;
106 if ((i & 3) == 2)
107 writel(data, &i2c_regs->hw_i2c_data);
108 }
109
110 remain = 24 - ((i & 3) * 8);
111 if (remain)
112 writel(data >> remain, &i2c_regs->hw_i2c_data);
113
114 writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
Marek Vasutd22643e2014-02-06 02:59:34 +0100115
116 while (--timeout) {
117 tmp = readl(&i2c_regs->hw_i2c_queuestat);
118 if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY)
119 break;
120 }
121
122 if (!timeout) {
123 debug("MXS I2C: Failed transmitting data!\n");
124 return -EINVAL;
125 }
126
127 return 0;
Marek Vasutf4f680a2011-11-08 23:18:12 +0000128}
129
Marek Vasut49c28b52012-12-16 02:48:16 +0000130static int mxs_i2c_wait_for_ack(void)
Marek Vasutf4f680a2011-11-08 23:18:12 +0000131{
Marek Vasut95360992014-10-20 00:23:40 +0200132 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutf4f680a2011-11-08 23:18:12 +0000133 uint32_t tmp;
134 int timeout = MXS_I2C_MAX_TIMEOUT;
135
136 for (;;) {
137 tmp = readl(&i2c_regs->hw_i2c_ctrl1);
138 if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) {
139 debug("MXS I2C: No slave ACK\n");
140 goto err;
141 }
142
143 if (tmp & (
144 I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
145 I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) {
146 debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp);
147 goto err;
148 }
149
150 if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ)
151 break;
152
153 if (!timeout--) {
154 debug("MXS I2C: Operation timed out\n");
155 goto err;
156 }
157
158 udelay(1);
159 }
160
161 return 0;
162
163err:
164 mxs_i2c_reset();
165 return 1;
166}
167
168int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
169{
Marek Vasut95360992014-10-20 00:23:40 +0200170 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutf4f680a2011-11-08 23:18:12 +0000171 uint32_t tmp = 0;
Marek Vasut12491352013-11-04 14:29:12 +0100172 int timeout = MXS_I2C_MAX_TIMEOUT;
Marek Vasutf4f680a2011-11-08 23:18:12 +0000173 int ret;
174 int i;
175
Marek Vasutd22643e2014-02-06 02:59:34 +0100176 ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
177 if (ret) {
178 debug("MXS I2C: Failed writing address\n");
179 return ret;
180 }
181
Marek Vasutf4f680a2011-11-08 23:18:12 +0000182 ret = mxs_i2c_wait_for_ack();
183 if (ret) {
184 debug("MXS I2C: Failed writing address\n");
185 return ret;
186 }
187
188 mxs_i2c_setup_read(chip, len);
189 ret = mxs_i2c_wait_for_ack();
190 if (ret) {
191 debug("MXS I2C: Failed reading address\n");
192 return ret;
193 }
194
195 for (i = 0; i < len; i++) {
196 if (!(i & 3)) {
Marek Vasut12491352013-11-04 14:29:12 +0100197 while (--timeout) {
198 tmp = readl(&i2c_regs->hw_i2c_queuestat);
199 if (!(tmp & I2C_QUEUESTAT_RD_QUEUE_EMPTY))
200 break;
201 }
202
203 if (!timeout) {
204 debug("MXS I2C: Failed receiving data!\n");
205 return -ETIMEDOUT;
206 }
207
Marek Vasutf4f680a2011-11-08 23:18:12 +0000208 tmp = readl(&i2c_regs->hw_i2c_queuedata);
209 }
210 buffer[i] = tmp & 0xff;
211 tmp >>= 8;
212 }
213
214 return 0;
215}
216
217int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
218{
219 int ret;
Marek Vasutd22643e2014-02-06 02:59:34 +0100220 ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1);
221 if (ret) {
222 debug("MXS I2C: Failed writing address\n");
223 return ret;
224 }
225
Marek Vasutf4f680a2011-11-08 23:18:12 +0000226 ret = mxs_i2c_wait_for_ack();
227 if (ret)
228 debug("MXS I2C: Failed writing address\n");
229
230 return ret;
231}
232
233int i2c_probe(uchar chip)
234{
235 int ret;
Marek Vasutd22643e2014-02-06 02:59:34 +0100236 ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
237 if (!ret)
238 ret = mxs_i2c_wait_for_ack();
Marek Vasutf4f680a2011-11-08 23:18:12 +0000239 mxs_i2c_reset();
240 return ret;
241}
242
Marek Vasuta06f5902012-11-12 14:34:29 +0000243int i2c_set_bus_speed(unsigned int speed)
244{
Marek Vasut95360992014-10-20 00:23:40 +0200245 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutfa5e2842012-11-30 18:17:07 +0000246 /*
247 * The timing derivation algorithm. There is no documentation for this
248 * algorithm available, it was derived by using the scope and fiddling
249 * with constants until the result observed on the scope was good enough
250 * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be
251 * possible to assume the algorithm works for other frequencies as well.
252 *
253 * Note it was necessary to cap the frequency on both ends as it's not
254 * possible to configure completely arbitrary frequency for the I2C bus
255 * clock.
256 */
257 uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
258 uint32_t base = ((clk / speed) - 38) / 2;
259 uint16_t high_count = base + 3;
260 uint16_t low_count = base - 3;
261 uint16_t rcv_count = (high_count * 3) / 4;
262 uint16_t xmit_count = low_count / 4;
Marek Vasuta06f5902012-11-12 14:34:29 +0000263
Marek Vasutfa5e2842012-11-30 18:17:07 +0000264 if (speed > 540000) {
265 printf("MXS I2C: Speed too high (%d Hz)\n", speed);
Marek Vasuta06f5902012-11-12 14:34:29 +0000266 return -EINVAL;
267 }
268
Marek Vasutfa5e2842012-11-30 18:17:07 +0000269 if (speed < 12000) {
270 printf("MXS I2C: Speed too low (%d Hz)\n", speed);
271 return -EINVAL;
272 }
273
274 writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0);
275 writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1);
Marek Vasuta06f5902012-11-12 14:34:29 +0000276
Marek Vasutaff36ea2012-11-12 14:34:31 +0000277 writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) |
278 (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET),
Marek Vasuta06f5902012-11-12 14:34:29 +0000279 &i2c_regs->hw_i2c_timing2);
280
281 return 0;
282}
283
284unsigned int i2c_get_bus_speed(void)
285{
Marek Vasut95360992014-10-20 00:23:40 +0200286 struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(NULL);
Marek Vasutfa5e2842012-11-30 18:17:07 +0000287 uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
288 uint32_t timing0;
Marek Vasuta06f5902012-11-12 14:34:29 +0000289
290 timing0 = readl(&i2c_regs->hw_i2c_timing0);
Marek Vasutfa5e2842012-11-30 18:17:07 +0000291 /*
292 * This is a reverse version of the algorithm presented in
293 * i2c_set_bus_speed(). Please refer there for details.
294 */
295 return clk / ((((timing0 >> 16) - 3) * 2) + 38);
Marek Vasuta06f5902012-11-12 14:34:29 +0000296}
297
Marek Vasutf4f680a2011-11-08 23:18:12 +0000298void i2c_init(int speed, int slaveadd)
299{
Marek Vasutf32a4702012-11-12 14:34:28 +0000300 mxs_i2c_reset();
Marek Vasuta157e0d2012-11-12 14:34:30 +0000301 i2c_set_bus_speed(speed);
Marek Vasutf4f680a2011-11-08 23:18:12 +0000302
303 return;
304}