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