blob: f0f9b2afacfbb7f9a48a497c92126bfb7773601c [file] [log] [blame]
Marek Vasut27165962018-04-21 18:57:28 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * drivers/i2c/rcar_i2c.c
4 *
5 * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com>
6 *
7 * Clock configuration based on Linux i2c-rcar.c:
8 * Copyright (C) 2014-15 Wolfram Sang <wsa@sang-engineering.com>
9 * Copyright (C) 2011-2015 Renesas Electronics Corporation
10 * Copyright (C) 2012-14 Renesas Solutions Corp.
11 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
12 */
13
Marek Vasut27165962018-04-21 18:57:28 +020014#include <clk.h>
15#include <dm.h>
16#include <i2c.h>
17#include <asm/io.h>
18#include <wait_bit.h>
Simon Glass9bc15642020-02-03 07:36:16 -070019#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060020#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060021#include <linux/delay.h>
Marek Vasut27165962018-04-21 18:57:28 +020022
Ismael Luceno Cortesaf996752019-03-07 18:00:51 +000023#define RCAR_I2C_ICSCR 0x00 /* slave ctrl */
24#define RCAR_I2C_ICMCR 0x04 /* master ctrl */
25#define RCAR_I2C_ICMCR_MDBS BIT(7) /* non-fifo mode switch */
26#define RCAR_I2C_ICMCR_FSCL BIT(6) /* override SCL pin */
27#define RCAR_I2C_ICMCR_FSDA BIT(5) /* override SDA pin */
28#define RCAR_I2C_ICMCR_OBPC BIT(4) /* override pins */
29#define RCAR_I2C_ICMCR_MIE BIT(3) /* master if enable */
Marek Vasut27165962018-04-21 18:57:28 +020030#define RCAR_I2C_ICMCR_TSBE BIT(2)
Ismael Luceno Cortesaf996752019-03-07 18:00:51 +000031#define RCAR_I2C_ICMCR_FSB BIT(1) /* force stop bit */
32#define RCAR_I2C_ICMCR_ESG BIT(0) /* enable start bit gen */
33#define RCAR_I2C_ICSSR 0x08 /* slave status */
34#define RCAR_I2C_ICMSR 0x0c /* master status */
Marek Vasut27165962018-04-21 18:57:28 +020035#define RCAR_I2C_ICMSR_MASK 0x7f
Ismael Luceno Cortesaf996752019-03-07 18:00:51 +000036#define RCAR_I2C_ICMSR_MNR BIT(6) /* Nack */
37#define RCAR_I2C_ICMSR_MAL BIT(5) /* Arbitration lost */
38#define RCAR_I2C_ICMSR_MST BIT(4) /* Stop */
Marek Vasut27165962018-04-21 18:57:28 +020039#define RCAR_I2C_ICMSR_MDE BIT(3)
40#define RCAR_I2C_ICMSR_MDT BIT(2)
41#define RCAR_I2C_ICMSR_MDR BIT(1)
42#define RCAR_I2C_ICMSR_MAT BIT(0)
Ismael Luceno Cortesaf996752019-03-07 18:00:51 +000043#define RCAR_I2C_ICSIER 0x10 /* slave irq enable */
44#define RCAR_I2C_ICMIER 0x14 /* master irq enable */
45#define RCAR_I2C_ICCCR 0x18 /* clock dividers */
Marek Vasut27165962018-04-21 18:57:28 +020046#define RCAR_I2C_ICCCR_SCGD_OFF 3
Ismael Luceno Cortesaf996752019-03-07 18:00:51 +000047#define RCAR_I2C_ICSAR 0x1c /* slave address */
48#define RCAR_I2C_ICMAR 0x20 /* master address */
49#define RCAR_I2C_ICRXD_ICTXD 0x24 /* data port */
50/*
51 * First Bit Setup Cycle (Gen3).
52 * Defines 1st bit delay between SDA and SCL.
53 */
Marek Vasut55e57802019-03-02 17:17:11 +010054#define RCAR_I2C_ICFBSCR 0x38
Ismael Luceno Cortesaf996752019-03-07 18:00:51 +000055#define RCAR_I2C_ICFBSCR_TCYC17 0x0f /* 17*Tcyc */
56
Marek Vasut55e57802019-03-02 17:17:11 +010057
58enum rcar_i2c_type {
59 RCAR_I2C_TYPE_GEN2,
60 RCAR_I2C_TYPE_GEN3,
61};
Marek Vasut27165962018-04-21 18:57:28 +020062
63struct rcar_i2c_priv {
64 void __iomem *base;
65 struct clk clk;
Adam Ford62f27e42021-08-24 09:10:31 -050066 u32 fall_ns;
67 u32 rise_ns;
Marek Vasut27165962018-04-21 18:57:28 +020068 u32 intdelay;
69 u32 icccr;
Marek Vasut55e57802019-03-02 17:17:11 +010070 enum rcar_i2c_type type;
Marek Vasut27165962018-04-21 18:57:28 +020071};
72
73static int rcar_i2c_finish(struct udevice *dev)
74{
75 struct rcar_i2c_priv *priv = dev_get_priv(dev);
76 int ret;
77
78 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, RCAR_I2C_ICMSR_MST,
79 true, 10, true);
80
81 writel(0, priv->base + RCAR_I2C_ICSSR);
82 writel(0, priv->base + RCAR_I2C_ICMSR);
83 writel(0, priv->base + RCAR_I2C_ICMCR);
84
85 return ret;
86}
87
Ismael Luceno Cortes099a7732019-03-07 18:00:55 +000088static int rcar_i2c_recover(struct udevice *dev)
Marek Vasut27165962018-04-21 18:57:28 +020089{
90 struct rcar_i2c_priv *priv = dev_get_priv(dev);
91 u32 mcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_OBPC;
92 u32 mcra = mcr | RCAR_I2C_ICMCR_FSDA;
93 int i;
Ismael Luceno Cortes099a7732019-03-07 18:00:55 +000094 u32 mstat;
Marek Vasut27165962018-04-21 18:57:28 +020095
96 /* Send 9 SCL pulses */
97 for (i = 0; i < 9; i++) {
98 writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR);
99 udelay(5);
100 writel(mcra, priv->base + RCAR_I2C_ICMCR);
101 udelay(5);
102 }
103
104 /* Send stop condition */
105 udelay(5);
106 writel(mcra, priv->base + RCAR_I2C_ICMCR);
107 udelay(5);
108 writel(mcr, priv->base + RCAR_I2C_ICMCR);
109 udelay(5);
110 writel(mcr | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR);
111 udelay(5);
112 writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR);
113 udelay(5);
Ismael Luceno Cortes099a7732019-03-07 18:00:55 +0000114
115 mstat = readl(priv->base + RCAR_I2C_ICMSR);
116 return mstat & RCAR_I2C_ICMCR_FSDA ? -EBUSY : 0;
Marek Vasut27165962018-04-21 18:57:28 +0200117}
118
119static int rcar_i2c_set_addr(struct udevice *dev, u8 chip, u8 read)
120{
121 struct rcar_i2c_priv *priv = dev_get_priv(dev);
122 u32 mask = RCAR_I2C_ICMSR_MAT |
123 (read ? RCAR_I2C_ICMSR_MDR : RCAR_I2C_ICMSR_MDE);
Marek Vasut27165962018-04-21 18:57:28 +0200124 int ret;
125
126 writel(0, priv->base + RCAR_I2C_ICMIER);
127 writel(RCAR_I2C_ICMCR_MDBS, priv->base + RCAR_I2C_ICMCR);
128 writel(0, priv->base + RCAR_I2C_ICMSR);
129 writel(priv->icccr, priv->base + RCAR_I2C_ICCCR);
130
Ismael Luceno Cortes4bace812019-03-07 18:00:49 +0000131 /* Wait for the bus */
Marek Vasut27165962018-04-21 18:57:28 +0200132 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMCR,
133 RCAR_I2C_ICMCR_FSDA, false, 2, true);
134 if (ret) {
Ismael Luceno Cortes099a7732019-03-07 18:00:55 +0000135 if (rcar_i2c_recover(dev)) {
Marek Vasut27165962018-04-21 18:57:28 +0200136 dev_err(dev, "Bus busy, aborting\n");
137 return ret;
138 }
139 }
140
141 writel((chip << 1) | read, priv->base + RCAR_I2C_ICMAR);
Ismael Luceno Cortes3be2ea62019-03-07 18:00:52 +0000142 /* Reset */
Marek Vasut27165962018-04-21 18:57:28 +0200143 writel(RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE | RCAR_I2C_ICMCR_ESG,
144 priv->base + RCAR_I2C_ICMCR);
Ismael Luceno Cortes3be2ea62019-03-07 18:00:52 +0000145 /* Clear Status */
146 writel(0, priv->base + RCAR_I2C_ICMSR);
Marek Vasut27165962018-04-21 18:57:28 +0200147
148 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, mask,
149 true, 100, true);
150 if (ret)
151 return ret;
152
153 /* Check NAK */
154 if (readl(priv->base + RCAR_I2C_ICMSR) & RCAR_I2C_ICMSR_MNR)
155 return -EREMOTEIO;
156
157 return 0;
158}
159
160static int rcar_i2c_read_common(struct udevice *dev, struct i2c_msg *msg)
161{
162 struct rcar_i2c_priv *priv = dev_get_priv(dev);
163 u32 icmcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE;
164 int i, ret = -EREMOTEIO;
165
Marek Vasut27165962018-04-21 18:57:28 +0200166 for (i = 0; i < msg->len; i++) {
167 if (msg->len - 1 == i)
168 icmcr |= RCAR_I2C_ICMCR_FSB;
169
170 writel(icmcr, priv->base + RCAR_I2C_ICMCR);
Marek Vasut55e57802019-03-02 17:17:11 +0100171 writel((u32)~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR);
Marek Vasut27165962018-04-21 18:57:28 +0200172
173 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR,
174 RCAR_I2C_ICMSR_MDR, true, 100, true);
175 if (ret)
176 return ret;
177
178 msg->buf[i] = readl(priv->base + RCAR_I2C_ICRXD_ICTXD) & 0xff;
179 }
180
Marek Vasut55e57802019-03-02 17:17:11 +0100181 writel((u32)~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR);
Marek Vasut27165962018-04-21 18:57:28 +0200182
183 return rcar_i2c_finish(dev);
184}
185
186static int rcar_i2c_write_common(struct udevice *dev, struct i2c_msg *msg)
187{
188 struct rcar_i2c_priv *priv = dev_get_priv(dev);
189 u32 icmcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE;
190 int i, ret = -EREMOTEIO;
191
Marek Vasut27165962018-04-21 18:57:28 +0200192 for (i = 0; i < msg->len; i++) {
193 writel(msg->buf[i], priv->base + RCAR_I2C_ICRXD_ICTXD);
194 writel(icmcr, priv->base + RCAR_I2C_ICMCR);
Marek Vasut55e57802019-03-02 17:17:11 +0100195 writel((u32)~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR);
Marek Vasut27165962018-04-21 18:57:28 +0200196
197 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR,
198 RCAR_I2C_ICMSR_MDE, true, 100, true);
199 if (ret)
200 return ret;
201 }
202
Marek Vasut55e57802019-03-02 17:17:11 +0100203 writel((u32)~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR);
Marek Vasut27165962018-04-21 18:57:28 +0200204 icmcr |= RCAR_I2C_ICMCR_FSB;
205 writel(icmcr, priv->base + RCAR_I2C_ICMCR);
206
207 return rcar_i2c_finish(dev);
208}
209
210static int rcar_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
211{
212 int ret;
213
214 for (; nmsgs > 0; nmsgs--, msg++) {
Lad Prabhakar9c67b1f2020-09-30 13:24:12 +0100215 ret = rcar_i2c_set_addr(dev, msg->addr, !!(msg->flags & I2C_M_RD));
Ismael Luceno Cortesac14ca52019-03-07 18:00:54 +0000216 if (ret)
217 return ret;
218
Marek Vasut27165962018-04-21 18:57:28 +0200219 if (msg->flags & I2C_M_RD)
220 ret = rcar_i2c_read_common(dev, msg);
221 else
222 ret = rcar_i2c_write_common(dev, msg);
223
224 if (ret)
Ismael Luceno Cortes274ae402019-03-07 18:00:53 +0000225 return ret;
Marek Vasut27165962018-04-21 18:57:28 +0200226 }
227
Ismael Luceno Cortesac14ca52019-03-07 18:00:54 +0000228 return 0;
Marek Vasut27165962018-04-21 18:57:28 +0200229}
230
231static int rcar_i2c_probe_chip(struct udevice *dev, uint addr, uint flags)
232{
233 struct rcar_i2c_priv *priv = dev_get_priv(dev);
234 int ret;
235
236 /* Ignore address 0, slave address */
237 if (addr == 0)
238 return -EINVAL;
239
240 ret = rcar_i2c_set_addr(dev, addr, 1);
241 writel(0, priv->base + RCAR_I2C_ICMSR);
242 return ret;
243}
244
245static int rcar_i2c_set_speed(struct udevice *dev, uint bus_freq_hz)
246{
247 struct rcar_i2c_priv *priv = dev_get_priv(dev);
248 u32 scgd, cdf, round, ick, sum, scl;
249 unsigned long rate;
250
251 /*
252 * calculate SCL clock
253 * see
254 * ICCCR
255 *
256 * ick = clkp / (1 + CDF)
257 * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
258 *
259 * ick : I2C internal clock < 20 MHz
260 * ticf : I2C SCL falling time
261 * tr : I2C SCL rising time
262 * intd : LSI internal delay
263 * clkp : peripheral_clk
264 * F[] : integer up-valuation
265 */
266 rate = clk_get_rate(&priv->clk);
267 cdf = rate / 20000000;
268 if (cdf >= 8) {
269 dev_err(dev, "Input clock %lu too high\n", rate);
270 return -EIO;
271 }
272 ick = rate / (cdf + 1);
273
274 /*
275 * it is impossible to calculate large scale
276 * number on u32. separate it
277 *
278 * F[(ticf + tr + intd) * ick] with sum = (ticf + tr + intd)
279 * = F[sum * ick / 1000000000]
280 * = F[(ick / 1000000) * sum / 1000]
281 */
Adam Ford62f27e42021-08-24 09:10:31 -0500282 sum = priv->fall_ns + priv->rise_ns + priv->intdelay;
Marek Vasut27165962018-04-21 18:57:28 +0200283 round = (ick + 500000) / 1000000 * sum;
284 round = (round + 500) / 1000;
285
286 /*
287 * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
288 *
289 * Calculation result (= SCL) should be less than
290 * bus_speed for hardware safety
291 *
292 * We could use something along the lines of
293 * div = ick / (bus_speed + 1) + 1;
294 * scgd = (div - 20 - round + 7) / 8;
295 * scl = ick / (20 + (scgd * 8) + round);
296 * (not fully verified) but that would get pretty involved
297 */
298 for (scgd = 0; scgd < 0x40; scgd++) {
299 scl = ick / (20 + (scgd * 8) + round);
300 if (scl <= bus_freq_hz)
301 goto scgd_find;
302 }
303 dev_err(dev, "it is impossible to calculate best SCL\n");
304 return -EIO;
305
306scgd_find:
307 dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
308 scl, bus_freq_hz, clk_get_rate(&priv->clk), round, cdf, scgd);
309
310 priv->icccr = (scgd << RCAR_I2C_ICCCR_SCGD_OFF) | cdf;
311 writel(priv->icccr, priv->base + RCAR_I2C_ICCCR);
312
Ismael Luceno Cortes4bace812019-03-07 18:00:49 +0000313 if (priv->type == RCAR_I2C_TYPE_GEN3) {
314 /* Set SCL/SDA delay */
315 writel(RCAR_I2C_ICFBSCR_TCYC17, priv->base + RCAR_I2C_ICFBSCR);
316 }
317
Marek Vasut27165962018-04-21 18:57:28 +0200318 return 0;
319}
320
321static int rcar_i2c_probe(struct udevice *dev)
322{
323 struct rcar_i2c_priv *priv = dev_get_priv(dev);
324 int ret;
325
326 priv->base = dev_read_addr_ptr(dev);
Adam Ford62f27e42021-08-24 09:10:31 -0500327 priv->rise_ns = dev_read_u32_default(dev,
328 "i2c-scl-rising-time-ns", 200);
329 priv->fall_ns = dev_read_u32_default(dev,
330 "i2c-scl-falling-time-ns", 35);
Marek Vasut27165962018-04-21 18:57:28 +0200331 priv->intdelay = dev_read_u32_default(dev,
332 "i2c-scl-internal-delay-ns", 5);
Marek Vasut55e57802019-03-02 17:17:11 +0100333 priv->type = dev_get_driver_data(dev);
Marek Vasut27165962018-04-21 18:57:28 +0200334
335 ret = clk_get_by_index(dev, 0, &priv->clk);
336 if (ret)
337 return ret;
338
339 ret = clk_enable(&priv->clk);
340 if (ret)
341 return ret;
342
343 /* reset slave mode */
344 writel(0, priv->base + RCAR_I2C_ICSIER);
345 writel(0, priv->base + RCAR_I2C_ICSAR);
346 writel(0, priv->base + RCAR_I2C_ICSCR);
347 writel(0, priv->base + RCAR_I2C_ICSSR);
348
349 /* reset master mode */
350 writel(0, priv->base + RCAR_I2C_ICMIER);
351 writel(0, priv->base + RCAR_I2C_ICMCR);
352 writel(0, priv->base + RCAR_I2C_ICMSR);
353 writel(0, priv->base + RCAR_I2C_ICMAR);
354
Simon Glassf0c99c52020-01-23 11:48:22 -0700355 ret = rcar_i2c_set_speed(dev, I2C_SPEED_STANDARD_RATE);
Marek Vasut27165962018-04-21 18:57:28 +0200356 if (ret)
357 clk_disable(&priv->clk);
358
359 return ret;
360}
361
362static const struct dm_i2c_ops rcar_i2c_ops = {
363 .xfer = rcar_i2c_xfer,
364 .probe_chip = rcar_i2c_probe_chip,
365 .set_bus_speed = rcar_i2c_set_speed,
366};
367
368static const struct udevice_id rcar_i2c_ids[] = {
Marek Vasut55e57802019-03-02 17:17:11 +0100369 { .compatible = "renesas,rcar-gen2-i2c", .data = RCAR_I2C_TYPE_GEN2 },
370 { .compatible = "renesas,rcar-gen3-i2c", .data = RCAR_I2C_TYPE_GEN3 },
Hai Phamf39867d32023-02-28 22:25:51 +0100371 { .compatible = "renesas,rcar-gen4-i2c", .data = RCAR_I2C_TYPE_GEN3 },
Marek Vasut27165962018-04-21 18:57:28 +0200372 { }
373};
374
375U_BOOT_DRIVER(i2c_rcar) = {
376 .name = "i2c_rcar",
377 .id = UCLASS_I2C,
378 .of_match = rcar_i2c_ids,
379 .probe = rcar_i2c_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700380 .priv_auto = sizeof(struct rcar_i2c_priv),
Marek Vasut27165962018-04-21 18:57:28 +0200381 .ops = &rcar_i2c_ops,
382};