]>
Commit | Line | Data |
---|---|---|
238bd0b8 MY |
1 | /* |
2 | * Copyright (C) 2014 Panasonic Corporation | |
6462cded MY |
3 | * Copyright (C) 2015 Socionext Inc. |
4 | * Author: Masahiro Yamada <yamada.masahiro@socionext.com> | |
238bd0b8 MY |
5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <linux/types.h> | |
11 | #include <asm/io.h> | |
12 | #include <asm/errno.h> | |
13 | #include <dm/device.h> | |
14 | #include <dm/root.h> | |
15 | #include <i2c.h> | |
16 | #include <fdtdec.h> | |
17 | ||
18 | DECLARE_GLOBAL_DATA_PTR; | |
19 | ||
20 | struct uniphier_fi2c_regs { | |
21 | u32 cr; /* control register */ | |
22 | #define I2C_CR_MST (1 << 3) /* master mode */ | |
23 | #define I2C_CR_STA (1 << 2) /* start condition */ | |
24 | #define I2C_CR_STO (1 << 1) /* stop condition */ | |
25 | #define I2C_CR_NACK (1 << 0) /* not ACK */ | |
26 | u32 dttx; /* send FIFO (write-only) */ | |
27 | #define dtrx dttx /* receive FIFO (read-only) */ | |
28 | #define I2C_DTTX_CMD (1 << 8) /* send command (slave addr) */ | |
29 | #define I2C_DTTX_RD (1 << 0) /* read */ | |
30 | u32 __reserved; /* no register at offset 0x08 */ | |
31 | u32 slad; /* slave address */ | |
32 | u32 cyc; /* clock cycle control */ | |
33 | u32 lctl; /* clock low period control */ | |
34 | u32 ssut; /* restart/stop setup time control */ | |
35 | u32 dsut; /* data setup time control */ | |
36 | u32 intr; /* interrupt status */ | |
37 | u32 ie; /* interrupt enable */ | |
38 | u32 ic; /* interrupt clear */ | |
39 | #define I2C_INT_TE (1 << 9) /* TX FIFO empty */ | |
40 | #define I2C_INT_RB (1 << 4) /* received specified bytes */ | |
41 | #define I2C_INT_NA (1 << 2) /* no answer */ | |
42 | #define I2C_INT_AL (1 << 1) /* arbitration lost */ | |
43 | u32 sr; /* status register */ | |
44 | #define I2C_SR_DB (1 << 12) /* device busy */ | |
45 | #define I2C_SR_BB (1 << 8) /* bus busy */ | |
46 | #define I2C_SR_RFF (1 << 3) /* Rx FIFO full */ | |
47 | #define I2C_SR_RNE (1 << 2) /* Rx FIFO not empty */ | |
48 | #define I2C_SR_TNF (1 << 1) /* Tx FIFO not full */ | |
49 | #define I2C_SR_TFE (1 << 0) /* Tx FIFO empty */ | |
50 | u32 __reserved2; /* no register at offset 0x30 */ | |
51 | u32 rst; /* reset control */ | |
52 | #define I2C_RST_TBRST (1 << 2) /* clear Tx FIFO */ | |
53 | #define I2C_RST_RBRST (1 << 1) /* clear Rx FIFO */ | |
54 | #define I2C_RST_RST (1 << 0) /* forcible bus reset */ | |
55 | u32 bm; /* bus monitor */ | |
56 | u32 noise; /* noise filter control */ | |
57 | u32 tbc; /* Tx byte count setting */ | |
58 | u32 rbc; /* Rx byte count setting */ | |
59 | u32 tbcm; /* Tx byte count monitor */ | |
60 | u32 rbcm; /* Rx byte count monitor */ | |
61 | u32 brst; /* bus reset */ | |
62 | #define I2C_BRST_FOEN (1 << 1) /* normal operation */ | |
63 | #define I2C_BRST_RSCLO (1 << 0) /* release SCL low fixing */ | |
64 | }; | |
65 | ||
66 | #define FIOCLK 50000000 | |
67 | ||
68 | struct uniphier_fi2c_dev { | |
69 | struct uniphier_fi2c_regs __iomem *regs; /* register base */ | |
70 | unsigned long fioclk; /* internal operation clock */ | |
71 | unsigned long timeout; /* time out (us) */ | |
72 | }; | |
73 | ||
74 | static int poll_status(u32 __iomem *reg, u32 flag) | |
75 | { | |
76 | int wait = 1000000; /* 1 sec is long enough */ | |
77 | ||
78 | while (readl(reg) & flag) { | |
79 | if (wait-- < 0) | |
80 | return -EREMOTEIO; | |
81 | udelay(1); | |
82 | } | |
83 | ||
84 | return 0; | |
85 | } | |
86 | ||
87 | static int reset_bus(struct uniphier_fi2c_regs __iomem *regs) | |
88 | { | |
89 | int ret; | |
90 | ||
91 | /* bus forcible reset */ | |
92 | writel(I2C_RST_RST, ®s->rst); | |
93 | ret = poll_status(®s->rst, I2C_RST_RST); | |
94 | if (ret < 0) | |
95 | debug("error: fail to reset I2C controller\n"); | |
96 | ||
97 | return ret; | |
98 | } | |
99 | ||
100 | static int check_device_busy(struct uniphier_fi2c_regs __iomem *regs) | |
101 | { | |
102 | int ret; | |
103 | ||
104 | ret = poll_status(®s->sr, I2C_SR_DB); | |
105 | if (ret < 0) { | |
106 | debug("error: device busy too long. reset...\n"); | |
107 | ret = reset_bus(regs); | |
108 | } | |
109 | ||
110 | return ret; | |
111 | } | |
112 | ||
113 | static int uniphier_fi2c_probe(struct udevice *dev) | |
114 | { | |
115 | fdt_addr_t addr; | |
116 | fdt_size_t size; | |
117 | struct uniphier_fi2c_dev *priv = dev_get_priv(dev); | |
118 | int ret; | |
119 | ||
120 | addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", | |
121 | &size); | |
122 | ||
123 | priv->regs = map_sysmem(addr, size); | |
124 | ||
125 | if (!priv->regs) | |
126 | return -ENOMEM; | |
127 | ||
128 | priv->fioclk = FIOCLK; | |
129 | ||
130 | /* bus forcible reset */ | |
131 | ret = reset_bus(priv->regs); | |
132 | if (ret < 0) | |
133 | return ret; | |
134 | ||
135 | writel(I2C_BRST_FOEN | I2C_BRST_RSCLO, &priv->regs->brst); | |
136 | ||
137 | return 0; | |
138 | } | |
139 | ||
140 | static int uniphier_fi2c_remove(struct udevice *dev) | |
141 | { | |
142 | struct uniphier_fi2c_dev *priv = dev_get_priv(dev); | |
143 | ||
144 | unmap_sysmem(priv->regs); | |
145 | ||
146 | return 0; | |
147 | } | |
148 | ||
238bd0b8 MY |
149 | static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags, |
150 | bool *stop) | |
151 | { | |
152 | u32 irq; | |
153 | unsigned long wait = dev->timeout; | |
154 | int ret = -EREMOTEIO; | |
155 | ||
156 | do { | |
157 | udelay(1); | |
158 | irq = readl(&dev->regs->intr); | |
159 | } while (!(irq & flags) && wait--); | |
160 | ||
161 | if (wait < 0) { | |
162 | debug("error: time out\n"); | |
163 | return ret; | |
164 | } | |
165 | ||
166 | if (irq & I2C_INT_AL) { | |
167 | debug("error: arbitration lost\n"); | |
168 | *stop = false; | |
169 | return ret; | |
170 | } | |
171 | ||
172 | if (irq & I2C_INT_NA) { | |
173 | debug("error: no answer\n"); | |
174 | return ret; | |
175 | } | |
176 | ||
177 | return 0; | |
178 | } | |
179 | ||
180 | static int issue_stop(struct uniphier_fi2c_dev *dev, int old_ret) | |
181 | { | |
182 | int ret; | |
183 | ||
184 | debug("stop condition\n"); | |
185 | writel(I2C_CR_MST | I2C_CR_STO, &dev->regs->cr); | |
186 | ||
187 | ret = poll_status(&dev->regs->sr, I2C_SR_DB); | |
188 | if (ret < 0) | |
189 | debug("error: device busy after operation\n"); | |
190 | ||
191 | return old_ret ? old_ret : ret; | |
192 | } | |
193 | ||
194 | static int uniphier_fi2c_transmit(struct uniphier_fi2c_dev *dev, uint addr, | |
195 | uint len, const u8 *buf, bool *stop) | |
196 | { | |
197 | int ret; | |
198 | const u32 irq_flags = I2C_INT_TE | I2C_INT_NA | I2C_INT_AL; | |
199 | struct uniphier_fi2c_regs __iomem *regs = dev->regs; | |
200 | ||
201 | debug("%s: addr = %x, len = %d\n", __func__, addr, len); | |
202 | ||
203 | writel(I2C_DTTX_CMD | addr << 1, ®s->dttx); | |
204 | ||
205 | writel(irq_flags, ®s->ie); | |
206 | writel(irq_flags, ®s->ic); | |
207 | ||
208 | debug("start condition\n"); | |
209 | writel(I2C_CR_MST | I2C_CR_STA, ®s->cr); | |
210 | ||
211 | ret = wait_for_irq(dev, irq_flags, stop); | |
212 | if (ret < 0) | |
213 | goto error; | |
214 | ||
215 | while (len--) { | |
216 | debug("sending %x\n", *buf); | |
217 | writel(*buf++, ®s->dttx); | |
218 | ||
219 | writel(irq_flags, ®s->ic); | |
220 | ||
221 | ret = wait_for_irq(dev, irq_flags, stop); | |
222 | if (ret < 0) | |
223 | goto error; | |
224 | } | |
225 | ||
226 | error: | |
227 | writel(irq_flags, ®s->ic); | |
228 | ||
229 | if (*stop) | |
230 | ret = issue_stop(dev, ret); | |
231 | ||
232 | return ret; | |
233 | } | |
234 | ||
235 | static int uniphier_fi2c_receive(struct uniphier_fi2c_dev *dev, uint addr, | |
236 | uint len, u8 *buf, bool *stop) | |
237 | { | |
238 | int ret = 0; | |
239 | const u32 irq_flags = I2C_INT_RB | I2C_INT_NA | I2C_INT_AL; | |
240 | struct uniphier_fi2c_regs __iomem *regs = dev->regs; | |
241 | ||
242 | debug("%s: addr = %x, len = %d\n", __func__, addr, len); | |
243 | ||
244 | /* | |
245 | * In case 'len == 0', only the slave address should be sent | |
246 | * for probing, which is covered by the transmit function. | |
247 | */ | |
248 | if (len == 0) | |
249 | return uniphier_fi2c_transmit(dev, addr, len, buf, stop); | |
250 | ||
251 | writel(I2C_DTTX_CMD | I2C_DTTX_RD | addr << 1, ®s->dttx); | |
252 | ||
253 | writel(0, ®s->rbc); | |
254 | writel(irq_flags, ®s->ie); | |
255 | writel(irq_flags, ®s->ic); | |
256 | ||
257 | debug("start condition\n"); | |
258 | writel(I2C_CR_MST | I2C_CR_STA | (len == 1 ? I2C_CR_NACK : 0), | |
259 | ®s->cr); | |
260 | ||
261 | while (len--) { | |
262 | ret = wait_for_irq(dev, irq_flags, stop); | |
263 | if (ret < 0) | |
264 | goto error; | |
265 | ||
266 | *buf++ = readl(®s->dtrx); | |
267 | debug("received %x\n", *(buf - 1)); | |
268 | ||
269 | if (len == 1) | |
270 | writel(I2C_CR_MST | I2C_CR_NACK, ®s->cr); | |
271 | ||
272 | writel(irq_flags, ®s->ic); | |
273 | } | |
274 | ||
275 | error: | |
276 | writel(irq_flags, ®s->ic); | |
277 | ||
278 | if (*stop) | |
279 | ret = issue_stop(dev, ret); | |
280 | ||
281 | return ret; | |
282 | } | |
283 | ||
284 | static int uniphier_fi2c_xfer(struct udevice *bus, struct i2c_msg *msg, | |
285 | int nmsgs) | |
286 | { | |
287 | int ret; | |
288 | struct uniphier_fi2c_dev *dev = dev_get_priv(bus); | |
289 | bool stop; | |
290 | ||
291 | ret = check_device_busy(dev->regs); | |
292 | if (ret < 0) | |
293 | return ret; | |
294 | ||
295 | for (; nmsgs > 0; nmsgs--, msg++) { | |
296 | /* If next message is read, skip the stop condition */ | |
297 | stop = nmsgs > 1 && msg[1].flags & I2C_M_RD ? false : true; | |
298 | ||
299 | if (msg->flags & I2C_M_RD) | |
300 | ret = uniphier_fi2c_receive(dev, msg->addr, msg->len, | |
301 | msg->buf, &stop); | |
302 | else | |
303 | ret = uniphier_fi2c_transmit(dev, msg->addr, msg->len, | |
304 | msg->buf, &stop); | |
305 | ||
306 | if (ret < 0) | |
307 | break; | |
308 | } | |
309 | ||
310 | return ret; | |
311 | } | |
312 | ||
313 | static int uniphier_fi2c_set_bus_speed(struct udevice *bus, unsigned int speed) | |
314 | { | |
315 | int ret; | |
316 | unsigned int clk_count; | |
317 | struct uniphier_fi2c_dev *dev = dev_get_priv(bus); | |
318 | struct uniphier_fi2c_regs __iomem *regs = dev->regs; | |
319 | ||
320 | /* max supported frequency is 400 kHz */ | |
321 | if (speed > 400000) | |
322 | return -EINVAL; | |
323 | ||
324 | ret = check_device_busy(dev->regs); | |
325 | if (ret < 0) | |
326 | return ret; | |
327 | ||
328 | /* make sure the bus is idle when changing the frequency */ | |
329 | writel(I2C_BRST_RSCLO, ®s->brst); | |
330 | ||
331 | clk_count = dev->fioclk / speed; | |
332 | ||
333 | writel(clk_count, ®s->cyc); | |
334 | writel(clk_count / 2, ®s->lctl); | |
335 | writel(clk_count / 2, ®s->ssut); | |
336 | writel(clk_count / 16, ®s->dsut); | |
337 | ||
338 | writel(I2C_BRST_FOEN | I2C_BRST_RSCLO, ®s->brst); | |
339 | ||
340 | /* | |
341 | * Theoretically, each byte can be transferred in | |
342 | * 1000000 * 9 / speed usec. | |
343 | * This time out value is long enough. | |
344 | */ | |
345 | dev->timeout = 100000000L / speed; | |
346 | ||
347 | return 0; | |
348 | } | |
349 | ||
350 | static const struct dm_i2c_ops uniphier_fi2c_ops = { | |
351 | .xfer = uniphier_fi2c_xfer, | |
352 | .set_bus_speed = uniphier_fi2c_set_bus_speed, | |
353 | }; | |
354 | ||
355 | static const struct udevice_id uniphier_fi2c_of_match[] = { | |
6462cded MY |
356 | { .compatible = "socionext,uniphier-fi2c" }, |
357 | { /* sentinel */ } | |
238bd0b8 MY |
358 | }; |
359 | ||
360 | U_BOOT_DRIVER(uniphier_fi2c) = { | |
361 | .name = "uniphier-fi2c", | |
362 | .id = UCLASS_I2C, | |
363 | .of_match = uniphier_fi2c_of_match, | |
364 | .probe = uniphier_fi2c_probe, | |
365 | .remove = uniphier_fi2c_remove, | |
238bd0b8 MY |
366 | .priv_auto_alloc_size = sizeof(struct uniphier_fi2c_dev), |
367 | .ops = &uniphier_fi2c_ops, | |
368 | }; |