Lines Matching +full:i2c +full:- +full:scl +full:- +full:internal +full:- +full:delay +full:- +full:ns

1 // SPDX-License-Identifier: GPL-2.0+
3 * drivers/i2c/rcar_i2c.c
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.
17 #include <i2c.h>
23 #define RCAR_I2C_ICMCR_MDBS BIT(7) /* non-fifo mode switch */
24 #define RCAR_I2C_ICMCR_FSCL BIT(6) /* override SCL pin */
50 * Defines 1st bit delay between SDA and SCL.
74 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, RCAR_I2C_ICMSR_MST, in rcar_i2c_finish()
77 writel(0, priv->base + RCAR_I2C_ICSSR); in rcar_i2c_finish()
78 writel(0, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_finish()
79 writel(0, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_finish()
92 /* Send 9 SCL pulses */ in rcar_i2c_recover()
94 writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_recover()
96 writel(mcra, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_recover()
102 writel(mcra, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_recover()
104 writel(mcr, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_recover()
106 writel(mcr | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_recover()
108 writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_recover()
111 mstat = readl(priv->base + RCAR_I2C_ICMSR); in rcar_i2c_recover()
112 return mstat & RCAR_I2C_ICMCR_FSDA ? -EBUSY : 0; in rcar_i2c_recover()
122 writel(0, priv->base + RCAR_I2C_ICMIER); in rcar_i2c_set_addr()
123 writel(RCAR_I2C_ICMCR_MDBS, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_set_addr()
124 writel(0, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_set_addr()
125 writel(priv->icccr, priv->base + RCAR_I2C_ICCCR); in rcar_i2c_set_addr()
128 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMCR, in rcar_i2c_set_addr()
137 writel((chip << 1) | read, priv->base + RCAR_I2C_ICMAR); in rcar_i2c_set_addr()
140 priv->base + RCAR_I2C_ICMCR); in rcar_i2c_set_addr()
142 writel(0, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_set_addr()
144 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, mask, in rcar_i2c_set_addr()
150 if (readl(priv->base + RCAR_I2C_ICMSR) & RCAR_I2C_ICMSR_MNR) in rcar_i2c_set_addr()
151 return -EREMOTEIO; in rcar_i2c_set_addr()
160 int i, ret = -EREMOTEIO; in rcar_i2c_read_common()
162 for (i = 0; i < msg->len; i++) { in rcar_i2c_read_common()
163 if (msg->len - 1 == i) in rcar_i2c_read_common()
166 writel(icmcr, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_read_common()
167 writel((u32)~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_read_common()
169 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, in rcar_i2c_read_common()
174 msg->buf[i] = readl(priv->base + RCAR_I2C_ICRXD_ICTXD) & 0xff; in rcar_i2c_read_common()
177 writel((u32)~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_read_common()
186 int i, ret = -EREMOTEIO; in rcar_i2c_write_common()
188 for (i = 0; i < msg->len; i++) { in rcar_i2c_write_common()
189 writel(msg->buf[i], priv->base + RCAR_I2C_ICRXD_ICTXD); in rcar_i2c_write_common()
190 writel(icmcr, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_write_common()
191 writel((u32)~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_write_common()
193 ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, in rcar_i2c_write_common()
199 writel((u32)~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_write_common()
201 writel(icmcr, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_write_common()
210 for (; nmsgs > 0; nmsgs--, msg++) { in rcar_i2c_xfer()
211 ret = rcar_i2c_set_addr(dev, msg->addr, 1); in rcar_i2c_xfer()
215 if (msg->flags & I2C_M_RD) in rcar_i2c_xfer()
234 return -EINVAL; in rcar_i2c_probe_chip()
237 writel(0, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_probe_chip()
244 u32 scgd, cdf, round, ick, sum, scl; in rcar_i2c_set_speed() local
248 * calculate SCL clock in rcar_i2c_set_speed()
253 * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick]) in rcar_i2c_set_speed()
255 * ick : I2C internal clock < 20 MHz in rcar_i2c_set_speed()
256 * ticf : I2C SCL falling time in rcar_i2c_set_speed()
257 * tr : I2C SCL rising time in rcar_i2c_set_speed()
258 * intd : LSI internal delay in rcar_i2c_set_speed()
260 * F[] : integer up-valuation in rcar_i2c_set_speed()
262 rate = clk_get_rate(&priv->clk); in rcar_i2c_set_speed()
266 return -EIO; in rcar_i2c_set_speed()
278 sum = 35 + 200 + priv->intdelay; in rcar_i2c_set_speed()
283 * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick]) in rcar_i2c_set_speed()
285 * Calculation result (= SCL) should be less than in rcar_i2c_set_speed()
290 * scgd = (div - 20 - round + 7) / 8; in rcar_i2c_set_speed()
291 * scl = ick / (20 + (scgd * 8) + round); in rcar_i2c_set_speed()
295 scl = ick / (20 + (scgd * 8) + round); in rcar_i2c_set_speed()
296 if (scl <= bus_freq_hz) in rcar_i2c_set_speed()
299 dev_err(dev, "it is impossible to calculate best SCL\n"); in rcar_i2c_set_speed()
300 return -EIO; in rcar_i2c_set_speed()
304 scl, bus_freq_hz, clk_get_rate(&priv->clk), round, cdf, scgd); in rcar_i2c_set_speed()
306 priv->icccr = (scgd << RCAR_I2C_ICCCR_SCGD_OFF) | cdf; in rcar_i2c_set_speed()
307 writel(priv->icccr, priv->base + RCAR_I2C_ICCCR); in rcar_i2c_set_speed()
309 if (priv->type == RCAR_I2C_TYPE_GEN3) { in rcar_i2c_set_speed()
310 /* Set SCL/SDA delay */ in rcar_i2c_set_speed()
311 writel(RCAR_I2C_ICFBSCR_TCYC17, priv->base + RCAR_I2C_ICFBSCR); in rcar_i2c_set_speed()
322 priv->base = dev_read_addr_ptr(dev); in rcar_i2c_probe()
323 priv->intdelay = dev_read_u32_default(dev, in rcar_i2c_probe()
324 "i2c-scl-internal-delay-ns", 5); in rcar_i2c_probe()
325 priv->type = dev_get_driver_data(dev); in rcar_i2c_probe()
327 ret = clk_get_by_index(dev, 0, &priv->clk); in rcar_i2c_probe()
331 ret = clk_enable(&priv->clk); in rcar_i2c_probe()
336 writel(0, priv->base + RCAR_I2C_ICSIER); in rcar_i2c_probe()
337 writel(0, priv->base + RCAR_I2C_ICSAR); in rcar_i2c_probe()
338 writel(0, priv->base + RCAR_I2C_ICSCR); in rcar_i2c_probe()
339 writel(0, priv->base + RCAR_I2C_ICSSR); in rcar_i2c_probe()
342 writel(0, priv->base + RCAR_I2C_ICMIER); in rcar_i2c_probe()
343 writel(0, priv->base + RCAR_I2C_ICMCR); in rcar_i2c_probe()
344 writel(0, priv->base + RCAR_I2C_ICMSR); in rcar_i2c_probe()
345 writel(0, priv->base + RCAR_I2C_ICMAR); in rcar_i2c_probe()
349 clk_disable(&priv->clk); in rcar_i2c_probe()
361 { .compatible = "renesas,rcar-gen2-i2c", .data = RCAR_I2C_TYPE_GEN2 },
362 { .compatible = "renesas,rcar-gen3-i2c", .data = RCAR_I2C_TYPE_GEN3 },