18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Renesas RIIC driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Wolfram Sang <wsa@sang-engineering.com>
68c2ecf20Sopenharmony_ci * Copyright (C) 2013 Renesas Solutions Corp.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci/*
108c2ecf20Sopenharmony_ci * This i2c core has a lot of interrupts, namely 8. We use their chaining as
118c2ecf20Sopenharmony_ci * some kind of state machine.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * 1) The main xfer routine kicks off a transmission by putting the start bit
148c2ecf20Sopenharmony_ci * (or repeated start) on the bus and enabling the transmit interrupt (TIE)
158c2ecf20Sopenharmony_ci * since we need to send the slave address + RW bit in every case.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * 2) TIE sends slave address + RW bit and selects how to continue.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * 3a) Write case: We keep utilizing TIE as long as we have data to send. If we
208c2ecf20Sopenharmony_ci * are done, we switch over to the transmission done interrupt (TEIE) and mark
218c2ecf20Sopenharmony_ci * the message as completed (includes sending STOP) there.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * 3b) Read case: We switch over to receive interrupt (RIE). One dummy read is
248c2ecf20Sopenharmony_ci * needed to start clocking, then we keep receiving until we are done. Note
258c2ecf20Sopenharmony_ci * that we use the RDRFS mode all the time, i.e. we ACK/NACK every byte by
268c2ecf20Sopenharmony_ci * writing to the ACKBT bit. I tried using the RDRFS mode only at the end of a
278c2ecf20Sopenharmony_ci * message to create the final NACK as sketched in the datasheet. This caused
288c2ecf20Sopenharmony_ci * some subtle races (when byte n was processed and byte n+1 was already
298c2ecf20Sopenharmony_ci * waiting), though, and I started with the safe approach.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * 4) If we got a NACK somewhere, we flag the error and stop the transmission
328c2ecf20Sopenharmony_ci * via NAKIE.
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Also check the comments in the interrupt routines for some gory details.
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include <linux/clk.h>
388c2ecf20Sopenharmony_ci#include <linux/completion.h>
398c2ecf20Sopenharmony_ci#include <linux/err.h>
408c2ecf20Sopenharmony_ci#include <linux/i2c.h>
418c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
428c2ecf20Sopenharmony_ci#include <linux/io.h>
438c2ecf20Sopenharmony_ci#include <linux/module.h>
448c2ecf20Sopenharmony_ci#include <linux/of.h>
458c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
468c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define RIIC_ICCR1	0x00
498c2ecf20Sopenharmony_ci#define RIIC_ICCR2	0x04
508c2ecf20Sopenharmony_ci#define RIIC_ICMR1	0x08
518c2ecf20Sopenharmony_ci#define RIIC_ICMR3	0x10
528c2ecf20Sopenharmony_ci#define RIIC_ICSER	0x18
538c2ecf20Sopenharmony_ci#define RIIC_ICIER	0x1c
548c2ecf20Sopenharmony_ci#define RIIC_ICSR2	0x24
558c2ecf20Sopenharmony_ci#define RIIC_ICBRL	0x34
568c2ecf20Sopenharmony_ci#define RIIC_ICBRH	0x38
578c2ecf20Sopenharmony_ci#define RIIC_ICDRT	0x3c
588c2ecf20Sopenharmony_ci#define RIIC_ICDRR	0x40
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define ICCR1_ICE	0x80
618c2ecf20Sopenharmony_ci#define ICCR1_IICRST	0x40
628c2ecf20Sopenharmony_ci#define ICCR1_SOWP	0x10
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define ICCR2_BBSY	0x80
658c2ecf20Sopenharmony_ci#define ICCR2_SP	0x08
668c2ecf20Sopenharmony_ci#define ICCR2_RS	0x04
678c2ecf20Sopenharmony_ci#define ICCR2_ST	0x02
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define ICMR1_CKS_MASK	0x70
708c2ecf20Sopenharmony_ci#define ICMR1_BCWP	0x08
718c2ecf20Sopenharmony_ci#define ICMR1_CKS(_x)	((((_x) << 4) & ICMR1_CKS_MASK) | ICMR1_BCWP)
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define ICMR3_RDRFS	0x20
748c2ecf20Sopenharmony_ci#define ICMR3_ACKWP	0x10
758c2ecf20Sopenharmony_ci#define ICMR3_ACKBT	0x08
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define ICIER_TIE	0x80
788c2ecf20Sopenharmony_ci#define ICIER_TEIE	0x40
798c2ecf20Sopenharmony_ci#define ICIER_RIE	0x20
808c2ecf20Sopenharmony_ci#define ICIER_NAKIE	0x10
818c2ecf20Sopenharmony_ci#define ICIER_SPIE	0x08
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define ICSR2_NACKF	0x10
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define ICBR_RESERVED	0xe0 /* Should be 1 on writes */
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define RIIC_INIT_MSG	-1
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistruct riic_dev {
908c2ecf20Sopenharmony_ci	void __iomem *base;
918c2ecf20Sopenharmony_ci	u8 *buf;
928c2ecf20Sopenharmony_ci	struct i2c_msg *msg;
938c2ecf20Sopenharmony_ci	int bytes_left;
948c2ecf20Sopenharmony_ci	int err;
958c2ecf20Sopenharmony_ci	int is_last;
968c2ecf20Sopenharmony_ci	struct completion msg_done;
978c2ecf20Sopenharmony_ci	struct i2c_adapter adapter;
988c2ecf20Sopenharmony_ci	struct clk *clk;
998c2ecf20Sopenharmony_ci};
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistruct riic_irq_desc {
1028c2ecf20Sopenharmony_ci	int res_num;
1038c2ecf20Sopenharmony_ci	irq_handler_t isr;
1048c2ecf20Sopenharmony_ci	char *name;
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u8 reg)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	writeb((readb(riic->base + reg) & ~clear) | set, riic->base + reg);
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	struct riic_dev *riic = i2c_get_adapdata(adap);
1158c2ecf20Sopenharmony_ci	unsigned long time_left;
1168c2ecf20Sopenharmony_ci	int i;
1178c2ecf20Sopenharmony_ci	u8 start_bit;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	pm_runtime_get_sync(adap->dev.parent);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	if (readb(riic->base + RIIC_ICCR2) & ICCR2_BBSY) {
1228c2ecf20Sopenharmony_ci		riic->err = -EBUSY;
1238c2ecf20Sopenharmony_ci		goto out;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	reinit_completion(&riic->msg_done);
1278c2ecf20Sopenharmony_ci	riic->err = 0;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	writeb(0, riic->base + RIIC_ICSR2);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	for (i = 0, start_bit = ICCR2_ST; i < num; i++) {
1328c2ecf20Sopenharmony_ci		riic->bytes_left = RIIC_INIT_MSG;
1338c2ecf20Sopenharmony_ci		riic->buf = msgs[i].buf;
1348c2ecf20Sopenharmony_ci		riic->msg = &msgs[i];
1358c2ecf20Sopenharmony_ci		riic->is_last = (i == num - 1);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci		writeb(ICIER_NAKIE | ICIER_TIE, riic->base + RIIC_ICIER);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci		writeb(start_bit, riic->base + RIIC_ICCR2);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci		time_left = wait_for_completion_timeout(&riic->msg_done, riic->adapter.timeout);
1428c2ecf20Sopenharmony_ci		if (time_left == 0)
1438c2ecf20Sopenharmony_ci			riic->err = -ETIMEDOUT;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci		if (riic->err)
1468c2ecf20Sopenharmony_ci			break;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		start_bit = ICCR2_RS;
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci out:
1528c2ecf20Sopenharmony_ci	pm_runtime_put(adap->dev.parent);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return riic->err ?: num;
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic irqreturn_t riic_tdre_isr(int irq, void *data)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct riic_dev *riic = data;
1608c2ecf20Sopenharmony_ci	u8 val;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	if (!riic->bytes_left)
1638c2ecf20Sopenharmony_ci		return IRQ_NONE;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (riic->bytes_left == RIIC_INIT_MSG) {
1668c2ecf20Sopenharmony_ci		if (riic->msg->flags & I2C_M_RD)
1678c2ecf20Sopenharmony_ci			/* On read, switch over to receive interrupt */
1688c2ecf20Sopenharmony_ci			riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER);
1698c2ecf20Sopenharmony_ci		else
1708c2ecf20Sopenharmony_ci			/* On write, initialize length */
1718c2ecf20Sopenharmony_ci			riic->bytes_left = riic->msg->len;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci		val = i2c_8bit_addr_from_msg(riic->msg);
1748c2ecf20Sopenharmony_ci	} else {
1758c2ecf20Sopenharmony_ci		val = *riic->buf;
1768c2ecf20Sopenharmony_ci		riic->buf++;
1778c2ecf20Sopenharmony_ci		riic->bytes_left--;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	/*
1818c2ecf20Sopenharmony_ci	 * Switch to transmission ended interrupt when done. Do check here
1828c2ecf20Sopenharmony_ci	 * after bytes_left was initialized to support SMBUS_QUICK (new msg has
1838c2ecf20Sopenharmony_ci	 * 0 length then)
1848c2ecf20Sopenharmony_ci	 */
1858c2ecf20Sopenharmony_ci	if (riic->bytes_left == 0)
1868c2ecf20Sopenharmony_ci		riic_clear_set_bit(riic, ICIER_TIE, ICIER_TEIE, RIIC_ICIER);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	/*
1898c2ecf20Sopenharmony_ci	 * This acks the TIE interrupt. We get another TIE immediately if our
1908c2ecf20Sopenharmony_ci	 * value could be moved to the shadow shift register right away. So
1918c2ecf20Sopenharmony_ci	 * this must be after updates to ICIER (where we want to disable TIE)!
1928c2ecf20Sopenharmony_ci	 */
1938c2ecf20Sopenharmony_ci	writeb(val, riic->base + RIIC_ICDRT);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic irqreturn_t riic_tend_isr(int irq, void *data)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	struct riic_dev *riic = data;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	if (readb(riic->base + RIIC_ICSR2) & ICSR2_NACKF) {
2038c2ecf20Sopenharmony_ci		/* We got a NACKIE */
2048c2ecf20Sopenharmony_ci		readb(riic->base + RIIC_ICDRR);	/* dummy read */
2058c2ecf20Sopenharmony_ci		riic_clear_set_bit(riic, ICSR2_NACKF, 0, RIIC_ICSR2);
2068c2ecf20Sopenharmony_ci		riic->err = -ENXIO;
2078c2ecf20Sopenharmony_ci	} else if (riic->bytes_left) {
2088c2ecf20Sopenharmony_ci		return IRQ_NONE;
2098c2ecf20Sopenharmony_ci	}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	if (riic->is_last || riic->err) {
2128c2ecf20Sopenharmony_ci		riic_clear_set_bit(riic, ICIER_TEIE, ICIER_SPIE, RIIC_ICIER);
2138c2ecf20Sopenharmony_ci		writeb(ICCR2_SP, riic->base + RIIC_ICCR2);
2148c2ecf20Sopenharmony_ci	} else {
2158c2ecf20Sopenharmony_ci		/* Transfer is complete, but do not send STOP */
2168c2ecf20Sopenharmony_ci		riic_clear_set_bit(riic, ICIER_TEIE, 0, RIIC_ICIER);
2178c2ecf20Sopenharmony_ci		complete(&riic->msg_done);
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic irqreturn_t riic_rdrf_isr(int irq, void *data)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	struct riic_dev *riic = data;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (!riic->bytes_left)
2288c2ecf20Sopenharmony_ci		return IRQ_NONE;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (riic->bytes_left == RIIC_INIT_MSG) {
2318c2ecf20Sopenharmony_ci		riic->bytes_left = riic->msg->len;
2328c2ecf20Sopenharmony_ci		readb(riic->base + RIIC_ICDRR);	/* dummy read */
2338c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (riic->bytes_left == 1) {
2378c2ecf20Sopenharmony_ci		/* STOP must come before we set ACKBT! */
2388c2ecf20Sopenharmony_ci		if (riic->is_last) {
2398c2ecf20Sopenharmony_ci			riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER);
2408c2ecf20Sopenharmony_ci			writeb(ICCR2_SP, riic->base + RIIC_ICCR2);
2418c2ecf20Sopenharmony_ci		}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		riic_clear_set_bit(riic, 0, ICMR3_ACKBT, RIIC_ICMR3);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	} else {
2468c2ecf20Sopenharmony_ci		riic_clear_set_bit(riic, ICMR3_ACKBT, 0, RIIC_ICMR3);
2478c2ecf20Sopenharmony_ci	}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	/* Reading acks the RIE interrupt */
2508c2ecf20Sopenharmony_ci	*riic->buf = readb(riic->base + RIIC_ICDRR);
2518c2ecf20Sopenharmony_ci	riic->buf++;
2528c2ecf20Sopenharmony_ci	riic->bytes_left--;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic irqreturn_t riic_stop_isr(int irq, void *data)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	struct riic_dev *riic = data;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	/* read back registers to confirm writes have fully propagated */
2628c2ecf20Sopenharmony_ci	writeb(0, riic->base + RIIC_ICSR2);
2638c2ecf20Sopenharmony_ci	readb(riic->base + RIIC_ICSR2);
2648c2ecf20Sopenharmony_ci	writeb(0, riic->base + RIIC_ICIER);
2658c2ecf20Sopenharmony_ci	readb(riic->base + RIIC_ICIER);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	complete(&riic->msg_done);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic u32 riic_func(struct i2c_adapter *adap)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic const struct i2c_algorithm riic_algo = {
2788c2ecf20Sopenharmony_ci	.master_xfer	= riic_xfer,
2798c2ecf20Sopenharmony_ci	.functionality	= riic_func,
2808c2ecf20Sopenharmony_ci};
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	int ret = 0;
2858c2ecf20Sopenharmony_ci	unsigned long rate;
2868c2ecf20Sopenharmony_ci	int total_ticks, cks, brl, brh;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	pm_runtime_get_sync(riic->adapter.dev.parent);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	if (t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ) {
2918c2ecf20Sopenharmony_ci		dev_err(&riic->adapter.dev,
2928c2ecf20Sopenharmony_ci			"unsupported bus speed (%dHz). %d max\n",
2938c2ecf20Sopenharmony_ci			t->bus_freq_hz, I2C_MAX_FAST_MODE_FREQ);
2948c2ecf20Sopenharmony_ci		ret = -EINVAL;
2958c2ecf20Sopenharmony_ci		goto out;
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	rate = clk_get_rate(riic->clk);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/*
3018c2ecf20Sopenharmony_ci	 * Assume the default register settings:
3028c2ecf20Sopenharmony_ci	 *  FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles)
3038c2ecf20Sopenharmony_ci	 *  FER.NFE = 1 (noise circuit enabled)
3048c2ecf20Sopenharmony_ci	 *  MR3.NF = 0 (1 cycle of noise filtered out)
3058c2ecf20Sopenharmony_ci	 *
3068c2ecf20Sopenharmony_ci	 * Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1)
3078c2ecf20Sopenharmony_ci	 * Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1)
3088c2ecf20Sopenharmony_ci	 */
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	/*
3118c2ecf20Sopenharmony_ci	 * Determine reference clock rate. We must be able to get the desired
3128c2ecf20Sopenharmony_ci	 * frequency with only 62 clock ticks max (31 high, 31 low).
3138c2ecf20Sopenharmony_ci	 * Aim for a duty of 60% LOW, 40% HIGH.
3148c2ecf20Sopenharmony_ci	 */
3158c2ecf20Sopenharmony_ci	total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	for (cks = 0; cks < 7; cks++) {
3188c2ecf20Sopenharmony_ci		/*
3198c2ecf20Sopenharmony_ci		 * 60% low time must be less than BRL + 2 + 1
3208c2ecf20Sopenharmony_ci		 * BRL max register value is 0x1F.
3218c2ecf20Sopenharmony_ci		 */
3228c2ecf20Sopenharmony_ci		brl = ((total_ticks * 6) / 10);
3238c2ecf20Sopenharmony_ci		if (brl <= (0x1F + 3))
3248c2ecf20Sopenharmony_ci			break;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		total_ticks /= 2;
3278c2ecf20Sopenharmony_ci		rate /= 2;
3288c2ecf20Sopenharmony_ci	}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (brl > (0x1F + 3)) {
3318c2ecf20Sopenharmony_ci		dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n",
3328c2ecf20Sopenharmony_ci			(unsigned long)t->bus_freq_hz);
3338c2ecf20Sopenharmony_ci		ret = -EINVAL;
3348c2ecf20Sopenharmony_ci		goto out;
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	brh = total_ticks - brl;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	/* Remove automatic clock ticks for sync circuit and NF */
3408c2ecf20Sopenharmony_ci	if (cks == 0) {
3418c2ecf20Sopenharmony_ci		brl -= 4;
3428c2ecf20Sopenharmony_ci		brh -= 4;
3438c2ecf20Sopenharmony_ci	} else {
3448c2ecf20Sopenharmony_ci		brl -= 3;
3458c2ecf20Sopenharmony_ci		brh -= 3;
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	/*
3498c2ecf20Sopenharmony_ci	 * Remove clock ticks for rise and fall times. Convert ns to clock
3508c2ecf20Sopenharmony_ci	 * ticks.
3518c2ecf20Sopenharmony_ci	 */
3528c2ecf20Sopenharmony_ci	brl -= t->scl_fall_ns / (1000000000 / rate);
3538c2ecf20Sopenharmony_ci	brh -= t->scl_rise_ns / (1000000000 / rate);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	/* Adjust for min register values for when SCLE=1 and NFE=1 */
3568c2ecf20Sopenharmony_ci	if (brl < 1)
3578c2ecf20Sopenharmony_ci		brl = 1;
3588c2ecf20Sopenharmony_ci	if (brh < 1)
3598c2ecf20Sopenharmony_ci		brh = 1;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n",
3628c2ecf20Sopenharmony_ci		 rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6),
3638c2ecf20Sopenharmony_ci		 t->scl_fall_ns / (1000000000 / rate),
3648c2ecf20Sopenharmony_ci		 t->scl_rise_ns / (1000000000 / rate), cks, brl, brh);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* Changing the order of accessing IICRST and ICE may break things! */
3678c2ecf20Sopenharmony_ci	writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1);
3688c2ecf20Sopenharmony_ci	riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1);
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1);
3718c2ecf20Sopenharmony_ci	writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH);
3728c2ecf20Sopenharmony_ci	writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	writeb(0, riic->base + RIIC_ICSER);
3758c2ecf20Sopenharmony_ci	writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	riic_clear_set_bit(riic, ICCR1_IICRST, 0, RIIC_ICCR1);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ciout:
3808c2ecf20Sopenharmony_ci	pm_runtime_put(riic->adapter.dev.parent);
3818c2ecf20Sopenharmony_ci	return ret;
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic struct riic_irq_desc riic_irqs[] = {
3858c2ecf20Sopenharmony_ci	{ .res_num = 0, .isr = riic_tend_isr, .name = "riic-tend" },
3868c2ecf20Sopenharmony_ci	{ .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rdrf" },
3878c2ecf20Sopenharmony_ci	{ .res_num = 2, .isr = riic_tdre_isr, .name = "riic-tdre" },
3888c2ecf20Sopenharmony_ci	{ .res_num = 3, .isr = riic_stop_isr, .name = "riic-stop" },
3898c2ecf20Sopenharmony_ci	{ .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" },
3908c2ecf20Sopenharmony_ci};
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic int riic_i2c_probe(struct platform_device *pdev)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	struct riic_dev *riic;
3958c2ecf20Sopenharmony_ci	struct i2c_adapter *adap;
3968c2ecf20Sopenharmony_ci	struct resource *res;
3978c2ecf20Sopenharmony_ci	struct i2c_timings i2c_t;
3988c2ecf20Sopenharmony_ci	int i, ret;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL);
4018c2ecf20Sopenharmony_ci	if (!riic)
4028c2ecf20Sopenharmony_ci		return -ENOMEM;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4058c2ecf20Sopenharmony_ci	riic->base = devm_ioremap_resource(&pdev->dev, res);
4068c2ecf20Sopenharmony_ci	if (IS_ERR(riic->base))
4078c2ecf20Sopenharmony_ci		return PTR_ERR(riic->base);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	riic->clk = devm_clk_get(&pdev->dev, NULL);
4108c2ecf20Sopenharmony_ci	if (IS_ERR(riic->clk)) {
4118c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "missing controller clock");
4128c2ecf20Sopenharmony_ci		return PTR_ERR(riic->clk);
4138c2ecf20Sopenharmony_ci	}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) {
4168c2ecf20Sopenharmony_ci		res = platform_get_resource(pdev, IORESOURCE_IRQ, riic_irqs[i].res_num);
4178c2ecf20Sopenharmony_ci		if (!res)
4188c2ecf20Sopenharmony_ci			return -ENODEV;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci		ret = devm_request_irq(&pdev->dev, res->start, riic_irqs[i].isr,
4218c2ecf20Sopenharmony_ci					0, riic_irqs[i].name, riic);
4228c2ecf20Sopenharmony_ci		if (ret) {
4238c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "failed to request irq %s\n", riic_irqs[i].name);
4248c2ecf20Sopenharmony_ci			return ret;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	adap = &riic->adapter;
4298c2ecf20Sopenharmony_ci	i2c_set_adapdata(adap, riic);
4308c2ecf20Sopenharmony_ci	strlcpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name));
4318c2ecf20Sopenharmony_ci	adap->owner = THIS_MODULE;
4328c2ecf20Sopenharmony_ci	adap->algo = &riic_algo;
4338c2ecf20Sopenharmony_ci	adap->dev.parent = &pdev->dev;
4348c2ecf20Sopenharmony_ci	adap->dev.of_node = pdev->dev.of_node;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	init_completion(&riic->msg_done);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	i2c_parse_fw_timings(&pdev->dev, &i2c_t, true);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	ret = riic_init_hw(riic, &i2c_t);
4438c2ecf20Sopenharmony_ci	if (ret)
4448c2ecf20Sopenharmony_ci		goto out;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	ret = i2c_add_adapter(adap);
4478c2ecf20Sopenharmony_ci	if (ret)
4488c2ecf20Sopenharmony_ci		goto out;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, riic);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "registered with %dHz bus speed\n",
4538c2ecf20Sopenharmony_ci		 i2c_t.bus_freq_hz);
4548c2ecf20Sopenharmony_ci	return 0;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ciout:
4578c2ecf20Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
4588c2ecf20Sopenharmony_ci	return ret;
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic int riic_i2c_remove(struct platform_device *pdev)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct riic_dev *riic = platform_get_drvdata(pdev);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	pm_runtime_get_sync(&pdev->dev);
4668c2ecf20Sopenharmony_ci	writeb(0, riic->base + RIIC_ICIER);
4678c2ecf20Sopenharmony_ci	pm_runtime_put(&pdev->dev);
4688c2ecf20Sopenharmony_ci	i2c_del_adapter(&riic->adapter);
4698c2ecf20Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	return 0;
4728c2ecf20Sopenharmony_ci}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_cistatic const struct of_device_id riic_i2c_dt_ids[] = {
4758c2ecf20Sopenharmony_ci	{ .compatible = "renesas,riic-rz" },
4768c2ecf20Sopenharmony_ci	{ /* Sentinel */ },
4778c2ecf20Sopenharmony_ci};
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_cistatic struct platform_driver riic_i2c_driver = {
4808c2ecf20Sopenharmony_ci	.probe		= riic_i2c_probe,
4818c2ecf20Sopenharmony_ci	.remove		= riic_i2c_remove,
4828c2ecf20Sopenharmony_ci	.driver		= {
4838c2ecf20Sopenharmony_ci		.name	= "i2c-riic",
4848c2ecf20Sopenharmony_ci		.of_match_table = riic_i2c_dt_ids,
4858c2ecf20Sopenharmony_ci	},
4868c2ecf20Sopenharmony_ci};
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cimodule_platform_driver(riic_i2c_driver);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Renesas RIIC adapter");
4918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
4928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
4938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, riic_i2c_dt_ids);
494