blob: ec6afc973489d26320e6fb3348ca5399226406a9 [file] [log] [blame]
Kuo-Jung Su3cff8422013-05-08 15:36:26 +08001/*
2 * Faraday I2C Controller
3 *
4 * (C) Copyright 2010 Faraday Technology
5 * Dante Su <dantesu@faraday-tech.com>
6 *
Tom Rini8dde4ca2013-07-24 09:25:40 -04007 * SPDX-License-Identifier: GPL-2.0+
Kuo-Jung Su3cff8422013-05-08 15:36:26 +08008 */
9
10#include <common.h>
11#include <asm/io.h>
12#include <i2c.h>
13
14#include "fti2c010.h"
15
16#ifndef CONFIG_HARD_I2C
17#error "fti2c010: CONFIG_HARD_I2C is not defined"
18#endif
19
20#ifndef CONFIG_SYS_I2C_SPEED
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080021#define CONFIG_SYS_I2C_SPEED 5000
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080022#endif
23
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080024#ifndef CONFIG_FTI2C010_CLOCK
25#define CONFIG_FTI2C010_CLOCK clk_get_rate("I2C")
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080026#endif
27
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080028#ifndef CONFIG_FTI2C010_TIMEOUT
29#define CONFIG_FTI2C010_TIMEOUT 10 /* ms */
30#endif
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080031
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080032/* 7-bit dev address + 1-bit read/write */
33#define I2C_RD(dev) ((((dev) << 1) & 0xfe) | 1)
34#define I2C_WR(dev) (((dev) << 1) & 0xfe)
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080035
36struct fti2c010_chip {
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080037 struct fti2c010_regs *regs;
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080038 uint bus;
39 uint speed;
40};
41
42static struct fti2c010_chip chip_list[] = {
43 {
44 .bus = 0,
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080045 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE,
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080046 },
47#ifdef CONFIG_I2C_MULTI_BUS
48# ifdef CONFIG_FTI2C010_BASE1
49 {
50 .bus = 1,
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080051 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE1,
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080052 },
53# endif
54# ifdef CONFIG_FTI2C010_BASE2
55 {
56 .bus = 2,
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080057 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE2,
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080058 },
59# endif
60# ifdef CONFIG_FTI2C010_BASE3
61 {
62 .bus = 3,
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080063 .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE3,
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080064 },
65# endif
66#endif /* #ifdef CONFIG_I2C_MULTI_BUS */
67};
68
69static struct fti2c010_chip *curr = chip_list;
70
71static int fti2c010_wait(uint32_t mask)
72{
73 int ret = -1;
74 uint32_t stat, ts;
75 struct fti2c010_regs *regs = curr->regs;
76
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +080077 for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) {
Kuo-Jung Su3cff8422013-05-08 15:36:26 +080078 stat = readl(&regs->sr);
79 if ((stat & mask) == mask) {
80 ret = 0;
81 break;
82 }
83 }
84
85 return ret;
86}
87
88/*
89 * u-boot I2C API
90 */
91
92/*
93 * Initialization, must be called once on start up, may be called
94 * repeatedly to change the speed and slave addresses.
95 */
96void i2c_init(int speed, int slaveaddr)
97{
98 if (speed || !curr->speed)
99 i2c_set_bus_speed(speed);
100
101 /* if slave mode disabled */
102 if (!slaveaddr)
103 return;
104
105 /*
106 * TODO:
107 * Implement slave mode, but is it really necessary?
108 */
109}
110
111/*
112 * Probe the given I2C chip address. Returns 0 if a chip responded,
113 * not 0 on failure.
114 */
115int i2c_probe(uchar chip)
116{
117 int ret;
118 struct fti2c010_regs *regs = curr->regs;
119
120 i2c_init(0, 0);
121
122 /* 1. Select slave device (7bits Address + 1bit R/W) */
123 writel(I2C_WR(chip), &regs->dr);
124 writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
125 ret = fti2c010_wait(SR_DT);
126 if (ret)
127 return ret;
128
129 /* 2. Select device register */
130 writel(0, &regs->dr);
131 writel(CR_ENABLE | CR_TBEN, &regs->cr);
132 ret = fti2c010_wait(SR_DT);
133
134 return ret;
135}
136
137/*
138 * Read/Write interface:
139 * chip: I2C chip address, range 0..127
140 * addr: Memory (register) address within the chip
141 * alen: Number of bytes to use for addr (typically 1, 2 for larger
142 * memories, 0 for register type devices with only one
143 * register)
144 * buffer: Where to read/write the data
145 * len: How many bytes to read/write
146 *
147 * Returns: 0 on success, not 0 on failure
148 */
149int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
150{
151 int ret, pos;
152 uchar paddr[4];
153 struct fti2c010_regs *regs = curr->regs;
154
155 i2c_init(0, 0);
156
157 paddr[0] = (addr >> 0) & 0xFF;
158 paddr[1] = (addr >> 8) & 0xFF;
159 paddr[2] = (addr >> 16) & 0xFF;
160 paddr[3] = (addr >> 24) & 0xFF;
161
162 /*
163 * Phase A. Set register address
164 */
165
166 /* A.1 Select slave device (7bits Address + 1bit R/W) */
167 writel(I2C_WR(chip), &regs->dr);
168 writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
169 ret = fti2c010_wait(SR_DT);
170 if (ret)
171 return ret;
172
173 /* A.2 Select device register */
174 for (pos = 0; pos < alen; ++pos) {
175 uint32_t ctrl = CR_ENABLE | CR_TBEN;
176
177 writel(paddr[pos], &regs->dr);
178 writel(ctrl, &regs->cr);
179 ret = fti2c010_wait(SR_DT);
180 if (ret)
181 return ret;
182 }
183
184 /*
185 * Phase B. Get register data
186 */
187
188 /* B.1 Select slave device (7bits Address + 1bit R/W) */
189 writel(I2C_RD(chip), &regs->dr);
190 writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
191 ret = fti2c010_wait(SR_DT);
192 if (ret)
193 return ret;
194
195 /* B.2 Get register data */
196 for (pos = 0; pos < len; ++pos) {
197 uint32_t ctrl = CR_ENABLE | CR_TBEN;
198 uint32_t stat = SR_DR;
199
200 if (pos == len - 1) {
201 ctrl |= CR_NAK | CR_STOP;
202 stat |= SR_ACK;
203 }
204 writel(ctrl, &regs->cr);
205 ret = fti2c010_wait(stat);
206 if (ret)
207 break;
208 buf[pos] = (uchar)(readl(&regs->dr) & 0xFF);
209 }
210
211 return ret;
212}
213
214/*
215 * Read/Write interface:
216 * chip: I2C chip address, range 0..127
217 * addr: Memory (register) address within the chip
218 * alen: Number of bytes to use for addr (typically 1, 2 for larger
219 * memories, 0 for register type devices with only one
220 * register)
221 * buffer: Where to read/write the data
222 * len: How many bytes to read/write
223 *
224 * Returns: 0 on success, not 0 on failure
225 */
226int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
227{
228 int ret, pos;
229 uchar paddr[4];
230 struct fti2c010_regs *regs = curr->regs;
231
232 i2c_init(0, 0);
233
234 paddr[0] = (addr >> 0) & 0xFF;
235 paddr[1] = (addr >> 8) & 0xFF;
236 paddr[2] = (addr >> 16) & 0xFF;
237 paddr[3] = (addr >> 24) & 0xFF;
238
239 /*
240 * Phase A. Set register address
241 *
242 * A.1 Select slave device (7bits Address + 1bit R/W)
243 */
244 writel(I2C_WR(chip), &regs->dr);
245 writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
246 ret = fti2c010_wait(SR_DT);
247 if (ret)
248 return ret;
249
250 /* A.2 Select device register */
251 for (pos = 0; pos < alen; ++pos) {
252 uint32_t ctrl = CR_ENABLE | CR_TBEN;
253
254 writel(paddr[pos], &regs->dr);
255 writel(ctrl, &regs->cr);
256 ret = fti2c010_wait(SR_DT);
257 if (ret)
258 return ret;
259 }
260
261 /*
262 * Phase B. Set register data
263 */
264 for (pos = 0; pos < len; ++pos) {
265 uint32_t ctrl = CR_ENABLE | CR_TBEN;
266
267 if (pos == len - 1)
268 ctrl |= CR_STOP;
269 writel(buf[pos], &regs->dr);
270 writel(ctrl, &regs->cr);
271 ret = fti2c010_wait(SR_DT);
272 if (ret)
273 break;
274 }
275
276 return ret;
277}
278
279/*
280 * Functions for setting the current I2C bus and its speed
281 */
282#ifdef CONFIG_I2C_MULTI_BUS
283
284/*
285 * i2c_set_bus_num:
286 *
287 * Change the active I2C bus. Subsequent read/write calls will
288 * go to this one.
289 *
290 * bus - bus index, zero based
291 *
292 * Returns: 0 on success, not 0 on failure
293 */
294int i2c_set_bus_num(uint bus)
295{
296 if (bus >= ARRAY_SIZE(chip_list))
297 return -1;
298 curr = chip_list + bus;
299 i2c_init(0, 0);
300 return 0;
301}
302
303/*
304 * i2c_get_bus_num:
305 *
306 * Returns index of currently active I2C bus. Zero-based.
307 */
308
309uint i2c_get_bus_num(void)
310{
311 return curr->bus;
312}
313
314#endif /* #ifdef CONFIG_I2C_MULTI_BUS */
315
316/*
317 * i2c_set_bus_speed:
318 *
319 * Change the speed of the active I2C bus
320 *
321 * speed - bus speed in Hz
322 *
323 * Returns: 0 on success, not 0 on failure
324 */
325int i2c_set_bus_speed(uint speed)
326{
327 struct fti2c010_regs *regs = curr->regs;
Kuo-Jung Sue6d3ab82013-12-02 16:02:56 +0800328 uint clk = CONFIG_FTI2C010_CLOCK;
Kuo-Jung Su3cff8422013-05-08 15:36:26 +0800329 uint gsr = 0, tsr = 32;
330 uint spd, div;
331
332 if (!speed)
333 speed = CONFIG_SYS_I2C_SPEED;
334
335 for (div = 0; div < 0x3ffff; ++div) {
336 /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */
337 spd = clk / (2 * (div + 2) + gsr);
338 if (spd <= speed)
339 break;
340 }
341
342 if (curr->speed == spd)
343 return 0;
344
345 writel(CR_I2CRST, &regs->cr);
346 mdelay(100);
347 if (readl(&regs->cr) & CR_I2CRST) {
348 printf("fti2c010: reset timeout\n");
349 return -1;
350 }
351
352 curr->speed = spd;
353
354 writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), &regs->tgsr);
355 writel(CDR_DIV(div), &regs->cdr);
356
357 return 0;
358}
359
360/*
361 * i2c_get_bus_speed:
362 *
363 * Returns speed of currently active I2C bus in Hz
364 */
365
366uint i2c_get_bus_speed(void)
367{
368 return curr->speed;
369}