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