18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * I2C driver for the Renesas EMEV2 SoC
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Wolfram Sang <wsa@sang-engineering.com>
68c2ecf20Sopenharmony_ci * Copyright 2013 Codethink Ltd.
78c2ecf20Sopenharmony_ci * Copyright 2010-2015 Renesas Electronics Corporation
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/clk.h>
118c2ecf20Sopenharmony_ci#include <linux/completion.h>
128c2ecf20Sopenharmony_ci#include <linux/device.h>
138c2ecf20Sopenharmony_ci#include <linux/i2c.h>
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
168c2ecf20Sopenharmony_ci#include <linux/io.h>
178c2ecf20Sopenharmony_ci#include <linux/kernel.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/of_device.h>
208c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
218c2ecf20Sopenharmony_ci#include <linux/sched.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* I2C Registers */
248c2ecf20Sopenharmony_ci#define I2C_OFS_IICACT0		0x00	/* start */
258c2ecf20Sopenharmony_ci#define I2C_OFS_IIC0		0x04	/* shift */
268c2ecf20Sopenharmony_ci#define I2C_OFS_IICC0		0x08	/* control */
278c2ecf20Sopenharmony_ci#define I2C_OFS_SVA0		0x0c	/* slave address */
288c2ecf20Sopenharmony_ci#define I2C_OFS_IICCL0		0x10	/* clock select */
298c2ecf20Sopenharmony_ci#define I2C_OFS_IICX0		0x14	/* extension */
308c2ecf20Sopenharmony_ci#define I2C_OFS_IICS0		0x18	/* status */
318c2ecf20Sopenharmony_ci#define I2C_OFS_IICSE0		0x1c	/* status For emulation */
328c2ecf20Sopenharmony_ci#define I2C_OFS_IICF0		0x20	/* IIC flag */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* I2C IICACT0 Masks */
358c2ecf20Sopenharmony_ci#define I2C_BIT_IICE0		0x0001
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* I2C IICC0 Masks */
388c2ecf20Sopenharmony_ci#define I2C_BIT_LREL0		0x0040
398c2ecf20Sopenharmony_ci#define I2C_BIT_WREL0		0x0020
408c2ecf20Sopenharmony_ci#define I2C_BIT_SPIE0		0x0010
418c2ecf20Sopenharmony_ci#define I2C_BIT_WTIM0		0x0008
428c2ecf20Sopenharmony_ci#define I2C_BIT_ACKE0		0x0004
438c2ecf20Sopenharmony_ci#define I2C_BIT_STT0		0x0002
448c2ecf20Sopenharmony_ci#define I2C_BIT_SPT0		0x0001
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* I2C IICCL0 Masks */
478c2ecf20Sopenharmony_ci#define I2C_BIT_SMC0		0x0008
488c2ecf20Sopenharmony_ci#define I2C_BIT_DFC0		0x0004
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/* I2C IICSE0 Masks */
518c2ecf20Sopenharmony_ci#define I2C_BIT_MSTS0		0x0080
528c2ecf20Sopenharmony_ci#define I2C_BIT_ALD0		0x0040
538c2ecf20Sopenharmony_ci#define I2C_BIT_EXC0		0x0020
548c2ecf20Sopenharmony_ci#define I2C_BIT_COI0		0x0010
558c2ecf20Sopenharmony_ci#define I2C_BIT_TRC0		0x0008
568c2ecf20Sopenharmony_ci#define I2C_BIT_ACKD0		0x0004
578c2ecf20Sopenharmony_ci#define I2C_BIT_STD0		0x0002
588c2ecf20Sopenharmony_ci#define I2C_BIT_SPD0		0x0001
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/* I2C IICF0 Masks */
618c2ecf20Sopenharmony_ci#define I2C_BIT_STCF		0x0080
628c2ecf20Sopenharmony_ci#define I2C_BIT_IICBSY		0x0040
638c2ecf20Sopenharmony_ci#define I2C_BIT_STCEN		0x0002
648c2ecf20Sopenharmony_ci#define I2C_BIT_IICRSV		0x0001
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistruct em_i2c_device {
678c2ecf20Sopenharmony_ci	void __iomem *base;
688c2ecf20Sopenharmony_ci	struct i2c_adapter adap;
698c2ecf20Sopenharmony_ci	struct completion msg_done;
708c2ecf20Sopenharmony_ci	struct clk *sclk;
718c2ecf20Sopenharmony_ci	struct i2c_client *slave;
728c2ecf20Sopenharmony_ci	int irq;
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	writeb((readb(priv->base + reg) & ~clear) | set, priv->base + reg);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic int em_i2c_wait_for_event(struct em_i2c_device *priv)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	unsigned long time_left;
838c2ecf20Sopenharmony_ci	int status;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	reinit_completion(&priv->msg_done);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	time_left = wait_for_completion_timeout(&priv->msg_done, priv->adap.timeout);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	if (!time_left)
908c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	status = readb(priv->base + I2C_OFS_IICSE0);
938c2ecf20Sopenharmony_ci	return status & I2C_BIT_ALD0 ? -EAGAIN : status;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic void em_i2c_stop(struct em_i2c_device *priv)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	/* Send Stop condition */
998c2ecf20Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_SPT0 | I2C_BIT_SPIE0, I2C_OFS_IICC0);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	/* Wait for stop condition */
1028c2ecf20Sopenharmony_ci	em_i2c_wait_for_event(priv);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic void em_i2c_reset(struct i2c_adapter *adap)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(adap);
1088c2ecf20Sopenharmony_ci	int retr;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	/* If I2C active */
1118c2ecf20Sopenharmony_ci	if (readb(priv->base + I2C_OFS_IICACT0) & I2C_BIT_IICE0) {
1128c2ecf20Sopenharmony_ci		/* Disable I2C operation */
1138c2ecf20Sopenharmony_ci		writeb(0, priv->base + I2C_OFS_IICACT0);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci		retr = 1000;
1168c2ecf20Sopenharmony_ci		while (readb(priv->base + I2C_OFS_IICACT0) == 1 && retr)
1178c2ecf20Sopenharmony_ci			retr--;
1188c2ecf20Sopenharmony_ci		WARN_ON(retr == 0);
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	/* Transfer mode set */
1228c2ecf20Sopenharmony_ci	writeb(I2C_BIT_DFC0, priv->base + I2C_OFS_IICCL0);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	/* Can Issue start without detecting a stop, Reservation disabled. */
1258c2ecf20Sopenharmony_ci	writeb(I2C_BIT_STCEN | I2C_BIT_IICRSV, priv->base + I2C_OFS_IICF0);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	/* I2C enable, 9 bit interrupt mode */
1288c2ecf20Sopenharmony_ci	writeb(I2C_BIT_WTIM0, priv->base + I2C_OFS_IICC0);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* Enable I2C operation */
1318c2ecf20Sopenharmony_ci	writeb(I2C_BIT_IICE0, priv->base + I2C_OFS_IICACT0);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	retr = 1000;
1348c2ecf20Sopenharmony_ci	while (readb(priv->base + I2C_OFS_IICACT0) == 0 && retr)
1358c2ecf20Sopenharmony_ci		retr--;
1368c2ecf20Sopenharmony_ci	WARN_ON(retr == 0);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic int __em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
1408c2ecf20Sopenharmony_ci				int stop)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(adap);
1438c2ecf20Sopenharmony_ci	int count, status, read = !!(msg->flags & I2C_M_RD);
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	/* Send start condition */
1468c2ecf20Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_ACKE0 | I2C_BIT_WTIM0, I2C_OFS_IICC0);
1478c2ecf20Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_STT0, I2C_OFS_IICC0);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/* Send slave address and R/W type */
1508c2ecf20Sopenharmony_ci	writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/* Wait for transaction */
1538c2ecf20Sopenharmony_ci	status = em_i2c_wait_for_event(priv);
1548c2ecf20Sopenharmony_ci	if (status < 0)
1558c2ecf20Sopenharmony_ci		goto out_reset;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* Received NACK (result of setting slave address and R/W) */
1588c2ecf20Sopenharmony_ci	if (!(status & I2C_BIT_ACKD0)) {
1598c2ecf20Sopenharmony_ci		em_i2c_stop(priv);
1608c2ecf20Sopenharmony_ci		goto out;
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	/* Extra setup for read transactions */
1648c2ecf20Sopenharmony_ci	if (read) {
1658c2ecf20Sopenharmony_ci		/* 8 bit interrupt mode */
1668c2ecf20Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0, I2C_OFS_IICC0);
1678c2ecf20Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0, I2C_OFS_IICC0);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci		/* Wait for transaction */
1708c2ecf20Sopenharmony_ci		status = em_i2c_wait_for_event(priv);
1718c2ecf20Sopenharmony_ci		if (status < 0)
1728c2ecf20Sopenharmony_ci			goto out_reset;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	/* Send / receive data */
1768c2ecf20Sopenharmony_ci	for (count = 0; count < msg->len; count++) {
1778c2ecf20Sopenharmony_ci		if (read) { /* Read transaction */
1788c2ecf20Sopenharmony_ci			msg->buf[count] = readb(priv->base + I2C_OFS_IIC0);
1798c2ecf20Sopenharmony_ci			em_clear_set_bit(priv, 0, I2C_BIT_WREL0, I2C_OFS_IICC0);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci		} else { /* Write transaction */
1828c2ecf20Sopenharmony_ci			/* Received NACK */
1838c2ecf20Sopenharmony_ci			if (!(status & I2C_BIT_ACKD0)) {
1848c2ecf20Sopenharmony_ci				em_i2c_stop(priv);
1858c2ecf20Sopenharmony_ci				goto out;
1868c2ecf20Sopenharmony_ci			}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci			/* Write data */
1898c2ecf20Sopenharmony_ci			writeb(msg->buf[count], priv->base + I2C_OFS_IIC0);
1908c2ecf20Sopenharmony_ci		}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci		/* Wait for R/W transaction */
1938c2ecf20Sopenharmony_ci		status = em_i2c_wait_for_event(priv);
1948c2ecf20Sopenharmony_ci		if (status < 0)
1958c2ecf20Sopenharmony_ci			goto out_reset;
1968c2ecf20Sopenharmony_ci	}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	if (stop)
1998c2ecf20Sopenharmony_ci		em_i2c_stop(priv);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	return count;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ciout_reset:
2048c2ecf20Sopenharmony_ci	em_i2c_reset(adap);
2058c2ecf20Sopenharmony_ciout:
2068c2ecf20Sopenharmony_ci	return status < 0 ? status : -ENXIO;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
2108c2ecf20Sopenharmony_ci	int num)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(adap);
2138c2ecf20Sopenharmony_ci	int ret, i;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (readb(priv->base + I2C_OFS_IICF0) & I2C_BIT_IICBSY)
2168c2ecf20Sopenharmony_ci		return -EAGAIN;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
2198c2ecf20Sopenharmony_ci		ret = __em_i2c_xfer(adap, &msgs[i], (i == (num - 1)));
2208c2ecf20Sopenharmony_ci		if (ret < 0)
2218c2ecf20Sopenharmony_ci			return ret;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* I2C transfer completed */
2258c2ecf20Sopenharmony_ci	return num;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic bool em_i2c_slave_irq(struct em_i2c_device *priv)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	u8 status, value;
2318c2ecf20Sopenharmony_ci	enum i2c_slave_event event;
2328c2ecf20Sopenharmony_ci	int ret;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	if (!priv->slave)
2358c2ecf20Sopenharmony_ci		return false;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	status = readb(priv->base + I2C_OFS_IICSE0);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	/* Extension code, do not participate */
2408c2ecf20Sopenharmony_ci	if (status & I2C_BIT_EXC0) {
2418c2ecf20Sopenharmony_ci		em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
2428c2ecf20Sopenharmony_ci		return true;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	/* Stop detected, we don't know if it's for slave or master */
2468c2ecf20Sopenharmony_ci	if (status & I2C_BIT_SPD0) {
2478c2ecf20Sopenharmony_ci		/* Notify slave device */
2488c2ecf20Sopenharmony_ci		i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
2498c2ecf20Sopenharmony_ci		/* Pretend we did not handle the interrupt */
2508c2ecf20Sopenharmony_ci		return false;
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	/* Only handle interrupts addressed to us */
2548c2ecf20Sopenharmony_ci	if (!(status & I2C_BIT_COI0))
2558c2ecf20Sopenharmony_ci		return false;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* Enable stop interrupts */
2588c2ecf20Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	/* Transmission or Reception */
2618c2ecf20Sopenharmony_ci	if (status & I2C_BIT_TRC0) {
2628c2ecf20Sopenharmony_ci		if (status & I2C_BIT_ACKD0) {
2638c2ecf20Sopenharmony_ci			/* 9 bit interrupt mode */
2648c2ecf20Sopenharmony_ci			em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci			/* Send data */
2678c2ecf20Sopenharmony_ci			event = status & I2C_BIT_STD0 ?
2688c2ecf20Sopenharmony_ci				I2C_SLAVE_READ_REQUESTED :
2698c2ecf20Sopenharmony_ci				I2C_SLAVE_READ_PROCESSED;
2708c2ecf20Sopenharmony_ci			i2c_slave_event(priv->slave, event, &value);
2718c2ecf20Sopenharmony_ci			writeb(value, priv->base + I2C_OFS_IIC0);
2728c2ecf20Sopenharmony_ci		} else {
2738c2ecf20Sopenharmony_ci			/* NACK, stop transmitting */
2748c2ecf20Sopenharmony_ci			em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
2758c2ecf20Sopenharmony_ci		}
2768c2ecf20Sopenharmony_ci	} else {
2778c2ecf20Sopenharmony_ci		/* 8 bit interrupt mode */
2788c2ecf20Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0,
2798c2ecf20Sopenharmony_ci				I2C_OFS_IICC0);
2808c2ecf20Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0,
2818c2ecf20Sopenharmony_ci				I2C_OFS_IICC0);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci		if (status & I2C_BIT_STD0) {
2848c2ecf20Sopenharmony_ci			i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED,
2858c2ecf20Sopenharmony_ci					&value);
2868c2ecf20Sopenharmony_ci		} else {
2878c2ecf20Sopenharmony_ci			/* Recv data */
2888c2ecf20Sopenharmony_ci			value = readb(priv->base + I2C_OFS_IIC0);
2898c2ecf20Sopenharmony_ci			ret = i2c_slave_event(priv->slave,
2908c2ecf20Sopenharmony_ci					I2C_SLAVE_WRITE_RECEIVED, &value);
2918c2ecf20Sopenharmony_ci			if (ret < 0)
2928c2ecf20Sopenharmony_ci				em_clear_set_bit(priv, I2C_BIT_ACKE0, 0,
2938c2ecf20Sopenharmony_ci						I2C_OFS_IICC0);
2948c2ecf20Sopenharmony_ci		}
2958c2ecf20Sopenharmony_ci	}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	return true;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = dev_id;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (em_i2c_slave_irq(priv))
3058c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	complete(&priv->msg_done);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic u32 em_i2c_func(struct i2c_adapter *adap)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic int em_i2c_reg_slave(struct i2c_client *slave)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (priv->slave)
3228c2ecf20Sopenharmony_ci		return -EBUSY;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	if (slave->flags & I2C_CLIENT_TEN)
3258c2ecf20Sopenharmony_ci		return -EAFNOSUPPORT;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	priv->slave = slave;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	/* Set slave address */
3308c2ecf20Sopenharmony_ci	writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	return 0;
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cistatic int em_i2c_unreg_slave(struct i2c_client *slave)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	WARN_ON(!priv->slave);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	writeb(0, priv->base + I2C_OFS_SVA0);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	/*
3448c2ecf20Sopenharmony_ci	 * Wait for interrupt to finish. New slave irqs cannot happen because we
3458c2ecf20Sopenharmony_ci	 * cleared the slave address and, thus, only extension codes will be
3468c2ecf20Sopenharmony_ci	 * detected which do not use the slave ptr.
3478c2ecf20Sopenharmony_ci	 */
3488c2ecf20Sopenharmony_ci	synchronize_irq(priv->irq);
3498c2ecf20Sopenharmony_ci	priv->slave = NULL;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return 0;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic const struct i2c_algorithm em_i2c_algo = {
3558c2ecf20Sopenharmony_ci	.master_xfer = em_i2c_xfer,
3568c2ecf20Sopenharmony_ci	.functionality = em_i2c_func,
3578c2ecf20Sopenharmony_ci	.reg_slave      = em_i2c_reg_slave,
3588c2ecf20Sopenharmony_ci	.unreg_slave    = em_i2c_unreg_slave,
3598c2ecf20Sopenharmony_ci};
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic int em_i2c_probe(struct platform_device *pdev)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct em_i2c_device *priv;
3648c2ecf20Sopenharmony_ci	int ret;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
3678c2ecf20Sopenharmony_ci	if (!priv)
3688c2ecf20Sopenharmony_ci		return -ENOMEM;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	priv->base = devm_platform_ioremap_resource(pdev, 0);
3718c2ecf20Sopenharmony_ci	if (IS_ERR(priv->base))
3728c2ecf20Sopenharmony_ci		return PTR_ERR(priv->base);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	strlcpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name));
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	priv->sclk = devm_clk_get(&pdev->dev, "sclk");
3778c2ecf20Sopenharmony_ci	if (IS_ERR(priv->sclk))
3788c2ecf20Sopenharmony_ci		return PTR_ERR(priv->sclk);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(priv->sclk);
3818c2ecf20Sopenharmony_ci	if (ret)
3828c2ecf20Sopenharmony_ci		return ret;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	priv->adap.timeout = msecs_to_jiffies(100);
3858c2ecf20Sopenharmony_ci	priv->adap.retries = 5;
3868c2ecf20Sopenharmony_ci	priv->adap.dev.parent = &pdev->dev;
3878c2ecf20Sopenharmony_ci	priv->adap.algo = &em_i2c_algo;
3888c2ecf20Sopenharmony_ci	priv->adap.owner = THIS_MODULE;
3898c2ecf20Sopenharmony_ci	priv->adap.dev.of_node = pdev->dev.of_node;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	init_completion(&priv->msg_done);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, priv);
3948c2ecf20Sopenharmony_ci	i2c_set_adapdata(&priv->adap, priv);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	em_i2c_reset(&priv->adap);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	ret = platform_get_irq(pdev, 0);
3998c2ecf20Sopenharmony_ci	if (ret < 0)
4008c2ecf20Sopenharmony_ci		goto err_clk;
4018c2ecf20Sopenharmony_ci	priv->irq = ret;
4028c2ecf20Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
4038c2ecf20Sopenharmony_ci				"em_i2c", priv);
4048c2ecf20Sopenharmony_ci	if (ret)
4058c2ecf20Sopenharmony_ci		goto err_clk;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	ret = i2c_add_adapter(&priv->adap);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	if (ret)
4108c2ecf20Sopenharmony_ci		goto err_clk;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr,
4138c2ecf20Sopenharmony_ci		 priv->irq);
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	return 0;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_cierr_clk:
4188c2ecf20Sopenharmony_ci	clk_disable_unprepare(priv->sclk);
4198c2ecf20Sopenharmony_ci	return ret;
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cistatic int em_i2c_remove(struct platform_device *dev)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	struct em_i2c_device *priv = platform_get_drvdata(dev);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	i2c_del_adapter(&priv->adap);
4278c2ecf20Sopenharmony_ci	clk_disable_unprepare(priv->sclk);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	return 0;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic const struct of_device_id em_i2c_ids[] = {
4338c2ecf20Sopenharmony_ci	{ .compatible = "renesas,iic-emev2", },
4348c2ecf20Sopenharmony_ci	{ }
4358c2ecf20Sopenharmony_ci};
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic struct platform_driver em_i2c_driver = {
4388c2ecf20Sopenharmony_ci	.probe = em_i2c_probe,
4398c2ecf20Sopenharmony_ci	.remove = em_i2c_remove,
4408c2ecf20Sopenharmony_ci	.driver = {
4418c2ecf20Sopenharmony_ci		.name = "em-i2c",
4428c2ecf20Sopenharmony_ci		.of_match_table = em_i2c_ids,
4438c2ecf20Sopenharmony_ci	}
4448c2ecf20Sopenharmony_ci};
4458c2ecf20Sopenharmony_cimodule_platform_driver(em_i2c_driver);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("EMEV2 I2C bus driver");
4488c2ecf20Sopenharmony_ciMODULE_AUTHOR("Ian Molton");
4498c2ecf20Sopenharmony_ciMODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
4508c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
4518c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, em_i2c_ids);
452