blob: a4abd25c398798df159c65b6f0e5e066a2a8f483 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Sergey Kubushyne8f39122007-08-10 20:26:18 +02002/*
3 * TI DaVinci (TMS320DM644x) I2C driver.
4 *
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -04005 * (C) Copyright 2012-2014
6 * Texas Instruments Incorporated, <www.ti.com>
7 * (C) Copyright 2007 Sergey Kubushyn <ksi@koi8.net>
Sergey Kubushyne8f39122007-08-10 20:26:18 +02008 * --------------------------------------------------------
9 *
Simon Glasscb052ff2016-11-23 06:34:44 -070010 * NOTE: This driver should be converted to driver model before June 2017.
Heinrich Schuchardtc79f03c2020-02-25 21:35:39 +010011 * Please see doc/driver-model/i2c-howto.rst for instructions.
Sergey Kubushyne8f39122007-08-10 20:26:18 +020012 */
13
14#include <common.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020015#include <i2c.h>
Cooper Jr., Frankline9d85272017-04-20 10:25:43 -050016#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060017#include <log.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020018#include <asm/arch/hardware.h>
19#include <asm/arch/i2c_defs.h>
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040020#include <asm/io.h>
Simon Glassdbd79542020-05-10 11:40:11 -060021#include <linux/delay.h>
Karicheri, Muralidharanf89c87f2014-04-04 13:16:51 -040022#include "davinci_i2c.h"
Sergey Kubushyne8f39122007-08-10 20:26:18 +020023
Igor Opaniukf7c91762021-02-09 13:52:45 +020024#if CONFIG_IS_ENABLED(DM_I2C)
Cooper Jr., Frankline9d85272017-04-20 10:25:43 -050025/* Information about i2c controller */
26struct i2c_bus {
27 int id;
28 uint speed;
29 struct i2c_regs *regs;
30};
31#endif
32
Sergey Kubushyne8f39122007-08-10 20:26:18 +020033#define CHECK_NACK() \
34 do {\
35 if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040036 REG(&(i2c_base->i2c_con)) = 0;\
37 return 1;\
38 } \
Sergey Kubushyne8f39122007-08-10 20:26:18 +020039 } while (0)
40
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -050041static int _wait_for_bus(struct i2c_regs *i2c_base)
Sergey Kubushyne8f39122007-08-10 20:26:18 +020042{
43 int stat, timeout;
44
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040045 REG(&(i2c_base->i2c_stat)) = 0xffff;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020046
47 for (timeout = 0; timeout < 10; timeout++) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040048 stat = REG(&(i2c_base->i2c_stat));
49 if (!((stat) & I2C_STAT_BB)) {
50 REG(&(i2c_base->i2c_stat)) = 0xffff;
51 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020052 }
53
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040054 REG(&(i2c_base->i2c_stat)) = stat;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020055 udelay(50000);
56 }
57
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040058 REG(&(i2c_base->i2c_stat)) = 0xffff;
59 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020060}
61
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -050062static int _poll_i2c_irq(struct i2c_regs *i2c_base, int mask)
Sergey Kubushyne8f39122007-08-10 20:26:18 +020063{
64 int stat, timeout;
65
66 for (timeout = 0; timeout < 10; timeout++) {
67 udelay(1000);
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040068 stat = REG(&(i2c_base->i2c_stat));
69 if (stat & mask)
70 return stat;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020071 }
72
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040073 REG(&(i2c_base->i2c_stat)) = 0xffff;
74 return stat | I2C_TIMEOUT;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020075}
76
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -050077static void _flush_rx(struct i2c_regs *i2c_base)
Sergey Kubushyne8f39122007-08-10 20:26:18 +020078{
Sergey Kubushyne8f39122007-08-10 20:26:18 +020079 while (1) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040080 if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_RRDY))
Sergey Kubushyne8f39122007-08-10 20:26:18 +020081 break;
82
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040083 REG(&(i2c_base->i2c_drr));
84 REG(&(i2c_base->i2c_stat)) = I2C_STAT_RRDY;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020085 udelay(1000);
86 }
87}
88
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -050089static uint _davinci_i2c_setspeed(struct i2c_regs *i2c_base,
90 uint speed)
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040091{
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040092 uint32_t div, psc;
Sergey Kubushyne8f39122007-08-10 20:26:18 +020093
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -040094 psc = 2;
95 /* SCLL + SCLH */
96 div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10;
97 REG(&(i2c_base->i2c_psc)) = psc; /* 27MHz / (2 + 1) = 9MHz */
98 REG(&(i2c_base->i2c_scll)) = (div * 50) / 100; /* 50% Duty */
99 REG(&(i2c_base->i2c_sclh)) = div - REG(&(i2c_base->i2c_scll));
100
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400101 return 0;
102}
103
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500104static void _davinci_i2c_init(struct i2c_regs *i2c_base,
105 uint speed, int slaveadd)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200106{
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400107 if (REG(&(i2c_base->i2c_con)) & I2C_CON_EN) {
108 REG(&(i2c_base->i2c_con)) = 0;
109 udelay(50000);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200110 }
111
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500112 _davinci_i2c_setspeed(i2c_base, speed);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200113
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400114 REG(&(i2c_base->i2c_oa)) = slaveadd;
115 REG(&(i2c_base->i2c_cnt)) = 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200116
117 /* Interrupts must be enabled or I2C module won't work */
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400118 REG(&(i2c_base->i2c_ie)) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE |
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200119 I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
120
121 /* Now enable I2C controller (get it out of reset) */
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400122 REG(&(i2c_base->i2c_con)) = I2C_CON_EN;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200123
124 udelay(1000);
125}
126
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500127static int _davinci_i2c_read(struct i2c_regs *i2c_base, uint8_t chip,
128 uint32_t addr, int alen, uint8_t *buf, int len)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200129{
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400130 uint32_t tmp;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200131 int i;
132
133 if ((alen < 0) || (alen > 2)) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400134 printf("%s(): bogus address length %x\n", __func__, alen);
135 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200136 }
137
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500138 if (_wait_for_bus(i2c_base))
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400139 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200140
141 if (alen != 0) {
142 /* Start address phase */
143 tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX;
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400144 REG(&(i2c_base->i2c_cnt)) = alen;
145 REG(&(i2c_base->i2c_sa)) = chip;
146 REG(&(i2c_base->i2c_con)) = tmp;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200147
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500148 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_XRDY | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200149
150 CHECK_NACK();
151
152 switch (alen) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400153 case 2:
154 /* Send address MSByte */
155 if (tmp & I2C_STAT_XRDY) {
156 REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff;
157 } else {
158 REG(&(i2c_base->i2c_con)) = 0;
159 return 1;
160 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200161
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500162 tmp = _poll_i2c_irq(i2c_base,
163 I2C_STAT_XRDY | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200164
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400165 CHECK_NACK();
166 /* No break, fall through */
167 case 1:
168 /* Send address LSByte */
169 if (tmp & I2C_STAT_XRDY) {
170 REG(&(i2c_base->i2c_dxr)) = addr & 0xff;
171 } else {
172 REG(&(i2c_base->i2c_con)) = 0;
173 return 1;
174 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200175
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500176 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_XRDY |
177 I2C_STAT_NACK | I2C_STAT_ARDY);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200178
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400179 CHECK_NACK();
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200180
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400181 if (!(tmp & I2C_STAT_ARDY)) {
182 REG(&(i2c_base->i2c_con)) = 0;
183 return 1;
184 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200185 }
186 }
187
188 /* Address phase is over, now read 'len' bytes and stop */
189 tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP;
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400190 REG(&(i2c_base->i2c_cnt)) = len & 0xffff;
191 REG(&(i2c_base->i2c_sa)) = chip;
192 REG(&(i2c_base->i2c_con)) = tmp;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200193
194 for (i = 0; i < len; i++) {
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500195 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_RRDY | I2C_STAT_NACK |
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400196 I2C_STAT_ROVR);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200197
198 CHECK_NACK();
199
200 if (tmp & I2C_STAT_RRDY) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400201 buf[i] = REG(&(i2c_base->i2c_drr));
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200202 } else {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400203 REG(&(i2c_base->i2c_con)) = 0;
204 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200205 }
206 }
207
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500208 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_SCD | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200209
210 CHECK_NACK();
211
212 if (!(tmp & I2C_STAT_SCD)) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400213 REG(&(i2c_base->i2c_con)) = 0;
214 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200215 }
216
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500217 _flush_rx(i2c_base);
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400218 REG(&(i2c_base->i2c_stat)) = 0xffff;
219 REG(&(i2c_base->i2c_cnt)) = 0;
220 REG(&(i2c_base->i2c_con)) = 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200221
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400222 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200223}
224
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500225static int _davinci_i2c_write(struct i2c_regs *i2c_base, uint8_t chip,
226 uint32_t addr, int alen, uint8_t *buf, int len)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200227{
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400228 uint32_t tmp;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200229 int i;
230
231 if ((alen < 0) || (alen > 2)) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400232 printf("%s(): bogus address length %x\n", __func__, alen);
233 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200234 }
235 if (len < 0) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400236 printf("%s(): bogus length %x\n", __func__, len);
237 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200238 }
239
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500240 if (_wait_for_bus(i2c_base))
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400241 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200242
243 /* Start address phase */
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400244 tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
245 I2C_CON_TRX | I2C_CON_STP;
246 REG(&(i2c_base->i2c_cnt)) = (alen == 0) ?
247 len & 0xffff : (len & 0xffff) + alen;
248 REG(&(i2c_base->i2c_sa)) = chip;
249 REG(&(i2c_base->i2c_con)) = tmp;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200250
251 switch (alen) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400252 case 2:
253 /* Send address MSByte */
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500254 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_XRDY | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200255
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400256 CHECK_NACK();
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200257
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400258 if (tmp & I2C_STAT_XRDY) {
259 REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff;
260 } else {
261 REG(&(i2c_base->i2c_con)) = 0;
262 return 1;
263 }
264 /* No break, fall through */
265 case 1:
266 /* Send address LSByte */
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500267 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_XRDY | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200268
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400269 CHECK_NACK();
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200270
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400271 if (tmp & I2C_STAT_XRDY) {
272 REG(&(i2c_base->i2c_dxr)) = addr & 0xff;
273 } else {
274 REG(&(i2c_base->i2c_con)) = 0;
275 return 1;
276 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200277 }
278
279 for (i = 0; i < len; i++) {
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500280 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_XRDY | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200281
282 CHECK_NACK();
283
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400284 if (tmp & I2C_STAT_XRDY)
285 REG(&(i2c_base->i2c_dxr)) = buf[i];
286 else
287 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200288 }
289
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500290 tmp = _poll_i2c_irq(i2c_base, I2C_STAT_SCD | I2C_STAT_NACK);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200291
292 CHECK_NACK();
293
294 if (!(tmp & I2C_STAT_SCD)) {
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400295 REG(&(i2c_base->i2c_con)) = 0;
296 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200297 }
298
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500299 _flush_rx(i2c_base);
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400300 REG(&(i2c_base->i2c_stat)) = 0xffff;
301 REG(&(i2c_base->i2c_cnt)) = 0;
302 REG(&(i2c_base->i2c_con)) = 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200303
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400304 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200305}
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400306
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500307static int _davinci_i2c_probe_chip(struct i2c_regs *i2c_base, uint8_t chip)
308{
309 int rc = 1;
310
311 if (chip == REG(&(i2c_base->i2c_oa)))
312 return rc;
313
314 REG(&(i2c_base->i2c_con)) = 0;
315 if (_wait_for_bus(i2c_base))
316 return 1;
317
318 /* try to read one byte from current (or only) address */
319 REG(&(i2c_base->i2c_cnt)) = 1;
320 REG(&(i2c_base->i2c_sa)) = chip;
321 REG(&(i2c_base->i2c_con)) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
322 I2C_CON_STP);
323 udelay(50000);
324
325 if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_NACK)) {
326 rc = 0;
327 _flush_rx(i2c_base);
328 REG(&(i2c_base->i2c_stat)) = 0xffff;
329 } else {
330 REG(&(i2c_base->i2c_stat)) = 0xffff;
331 REG(&(i2c_base->i2c_con)) |= I2C_CON_STP;
332 udelay(20000);
333 if (_wait_for_bus(i2c_base))
334 return 1;
335 }
336
337 _flush_rx(i2c_base);
338 REG(&(i2c_base->i2c_stat)) = 0xffff;
339 REG(&(i2c_base->i2c_cnt)) = 0;
340 return rc;
341}
342
Igor Opaniukf7c91762021-02-09 13:52:45 +0200343#if !CONFIG_IS_ENABLED(DM_I2C)
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400344static struct i2c_regs *davinci_get_base(struct i2c_adapter *adap)
345{
346 switch (adap->hwadapnr) {
Adam Ford73010ab2017-08-11 06:39:13 -0500347#if CONFIG_SYS_I2C_BUS_MAX >= 3
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400348 case 2:
349 return (struct i2c_regs *)I2C2_BASE;
350#endif
Adam Ford73010ab2017-08-11 06:39:13 -0500351#if CONFIG_SYS_I2C_BUS_MAX >= 2
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400352 case 1:
353 return (struct i2c_regs *)I2C1_BASE;
354#endif
355 case 0:
356 return (struct i2c_regs *)I2C_BASE;
357
358 default:
359 printf("wrong hwadapnr: %d\n", adap->hwadapnr);
360 }
361
362 return NULL;
363}
364
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500365static uint davinci_i2c_setspeed(struct i2c_adapter *adap, uint speed)
366{
367 struct i2c_regs *i2c_base = davinci_get_base(adap);
368 uint ret;
369
370 adap->speed = speed;
371 ret = _davinci_i2c_setspeed(i2c_base, speed);
372
373 return ret;
374}
375
376static void davinci_i2c_init(struct i2c_adapter *adap, int speed,
377 int slaveadd)
378{
379 struct i2c_regs *i2c_base = davinci_get_base(adap);
380
381 adap->speed = speed;
382 _davinci_i2c_init(i2c_base, speed, slaveadd);
383
384 return;
385}
386
387static int davinci_i2c_read(struct i2c_adapter *adap, uint8_t chip,
388 uint32_t addr, int alen, uint8_t *buf, int len)
389{
390 struct i2c_regs *i2c_base = davinci_get_base(adap);
391 return _davinci_i2c_read(i2c_base, chip, addr, alen, buf, len);
392}
393
394static int davinci_i2c_write(struct i2c_adapter *adap, uint8_t chip,
395 uint32_t addr, int alen, uint8_t *buf, int len)
396{
397 struct i2c_regs *i2c_base = davinci_get_base(adap);
398
399 return _davinci_i2c_write(i2c_base, chip, addr, alen, buf, len);
400}
401
402static int davinci_i2c_probe_chip(struct i2c_adapter *adap, uint8_t chip)
403{
404 struct i2c_regs *i2c_base = davinci_get_base(adap);
405
406 return _davinci_i2c_probe_chip(i2c_base, chip);
407}
408
409U_BOOT_I2C_ADAP_COMPLETE(davinci_0, davinci_i2c_init, davinci_i2c_probe_chip,
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400410 davinci_i2c_read, davinci_i2c_write,
411 davinci_i2c_setspeed,
412 CONFIG_SYS_DAVINCI_I2C_SPEED,
413 CONFIG_SYS_DAVINCI_I2C_SLAVE,
414 0)
415
Adam Ford73010ab2017-08-11 06:39:13 -0500416#if CONFIG_SYS_I2C_BUS_MAX >= 2
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500417U_BOOT_I2C_ADAP_COMPLETE(davinci_1, davinci_i2c_init, davinci_i2c_probe_chip,
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400418 davinci_i2c_read, davinci_i2c_write,
419 davinci_i2c_setspeed,
420 CONFIG_SYS_DAVINCI_I2C_SPEED1,
421 CONFIG_SYS_DAVINCI_I2C_SLAVE1,
422 1)
423#endif
424
Adam Ford73010ab2017-08-11 06:39:13 -0500425#if CONFIG_SYS_I2C_BUS_MAX >= 3
Cooper Jr., Frankline1f7f6d2017-04-20 10:25:42 -0500426U_BOOT_I2C_ADAP_COMPLETE(davinci_2, davinci_i2c_init, davinci_i2c_probe_chip,
Vitaly Andrianovbc9cd952014-04-04 13:16:52 -0400427 davinci_i2c_read, davinci_i2c_write,
428 davinci_i2c_setspeed,
429 CONFIG_SYS_DAVINCI_I2C_SPEED2,
430 CONFIG_SYS_DAVINCI_I2C_SLAVE2,
431 2)
432#endif
Cooper Jr., Frankline9d85272017-04-20 10:25:43 -0500433
434#else /* CONFIG_DM_I2C */
435
436static int davinci_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
437 int nmsgs)
438{
439 struct i2c_bus *i2c_bus = dev_get_priv(bus);
440 int ret;
441
442 debug("i2c_xfer: %d messages\n", nmsgs);
443 for (; nmsgs > 0; nmsgs--, msg++) {
444 debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
445 if (msg->flags & I2C_M_RD) {
446 ret = _davinci_i2c_read(i2c_bus->regs, msg->addr,
447 0, 0, msg->buf, msg->len);
448 } else {
449 ret = _davinci_i2c_write(i2c_bus->regs, msg->addr,
450 0, 0, msg->buf, msg->len);
451 }
452 if (ret) {
453 debug("i2c_write: error sending\n");
454 return -EREMOTEIO;
455 }
456 }
457
458 return ret;
459}
460
461static int davinci_i2c_set_speed(struct udevice *dev, uint speed)
462{
463 struct i2c_bus *i2c_bus = dev_get_priv(dev);
464
465 i2c_bus->speed = speed;
466 return _davinci_i2c_setspeed(i2c_bus->regs, speed);
467}
468
469static int davinci_i2c_probe(struct udevice *dev)
470{
471 struct i2c_bus *i2c_bus = dev_get_priv(dev);
472
Simon Glass75e534b2020-12-16 21:20:07 -0700473 i2c_bus->id = dev_seq(dev);
Masahiro Yamada1096ae12020-07-17 14:36:46 +0900474 i2c_bus->regs = dev_read_addr_ptr(dev);
Cooper Jr., Frankline9d85272017-04-20 10:25:43 -0500475
476 i2c_bus->speed = 100000;
477 _davinci_i2c_init(i2c_bus->regs, i2c_bus->speed, 0);
478
479 return 0;
480}
481
482static int davinci_i2c_probe_chip(struct udevice *bus, uint chip_addr,
483 uint chip_flags)
484{
485 struct i2c_bus *i2c_bus = dev_get_priv(bus);
486
487 return _davinci_i2c_probe_chip(i2c_bus->regs, chip_addr);
488}
489
490static const struct dm_i2c_ops davinci_i2c_ops = {
491 .xfer = davinci_i2c_xfer,
492 .probe_chip = davinci_i2c_probe_chip,
493 .set_bus_speed = davinci_i2c_set_speed,
494};
495
496static const struct udevice_id davinci_i2c_ids[] = {
497 { .compatible = "ti,davinci-i2c"},
498 { .compatible = "ti,keystone-i2c"},
499 { }
500};
501
502U_BOOT_DRIVER(i2c_davinci) = {
503 .name = "i2c_davinci",
504 .id = UCLASS_I2C,
505 .of_match = davinci_i2c_ids,
506 .probe = davinci_i2c_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700507 .priv_auto = sizeof(struct i2c_bus),
Cooper Jr., Frankline9d85272017-04-20 10:25:43 -0500508 .ops = &davinci_i2c_ops,
509};
510
511#endif /* CONFIG_DM_I2C */