162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * I2C driver for the Renesas EMEV2 SoC
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2015 Wolfram Sang <wsa@sang-engineering.com>
662306a36Sopenharmony_ci * Copyright 2013 Codethink Ltd.
762306a36Sopenharmony_ci * Copyright 2010-2015 Renesas Electronics Corporation
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/clk.h>
1162306a36Sopenharmony_ci#include <linux/completion.h>
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/i2c.h>
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/kernel.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/of.h>
2062306a36Sopenharmony_ci#include <linux/platform_device.h>
2162306a36Sopenharmony_ci#include <linux/sched.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* I2C Registers */
2462306a36Sopenharmony_ci#define I2C_OFS_IICACT0		0x00	/* start */
2562306a36Sopenharmony_ci#define I2C_OFS_IIC0		0x04	/* shift */
2662306a36Sopenharmony_ci#define I2C_OFS_IICC0		0x08	/* control */
2762306a36Sopenharmony_ci#define I2C_OFS_SVA0		0x0c	/* slave address */
2862306a36Sopenharmony_ci#define I2C_OFS_IICCL0		0x10	/* clock select */
2962306a36Sopenharmony_ci#define I2C_OFS_IICX0		0x14	/* extension */
3062306a36Sopenharmony_ci#define I2C_OFS_IICS0		0x18	/* status */
3162306a36Sopenharmony_ci#define I2C_OFS_IICSE0		0x1c	/* status For emulation */
3262306a36Sopenharmony_ci#define I2C_OFS_IICF0		0x20	/* IIC flag */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* I2C IICACT0 Masks */
3562306a36Sopenharmony_ci#define I2C_BIT_IICE0		0x0001
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/* I2C IICC0 Masks */
3862306a36Sopenharmony_ci#define I2C_BIT_LREL0		0x0040
3962306a36Sopenharmony_ci#define I2C_BIT_WREL0		0x0020
4062306a36Sopenharmony_ci#define I2C_BIT_SPIE0		0x0010
4162306a36Sopenharmony_ci#define I2C_BIT_WTIM0		0x0008
4262306a36Sopenharmony_ci#define I2C_BIT_ACKE0		0x0004
4362306a36Sopenharmony_ci#define I2C_BIT_STT0		0x0002
4462306a36Sopenharmony_ci#define I2C_BIT_SPT0		0x0001
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/* I2C IICCL0 Masks */
4762306a36Sopenharmony_ci#define I2C_BIT_SMC0		0x0008
4862306a36Sopenharmony_ci#define I2C_BIT_DFC0		0x0004
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/* I2C IICSE0 Masks */
5162306a36Sopenharmony_ci#define I2C_BIT_MSTS0		0x0080
5262306a36Sopenharmony_ci#define I2C_BIT_ALD0		0x0040
5362306a36Sopenharmony_ci#define I2C_BIT_EXC0		0x0020
5462306a36Sopenharmony_ci#define I2C_BIT_COI0		0x0010
5562306a36Sopenharmony_ci#define I2C_BIT_TRC0		0x0008
5662306a36Sopenharmony_ci#define I2C_BIT_ACKD0		0x0004
5762306a36Sopenharmony_ci#define I2C_BIT_STD0		0x0002
5862306a36Sopenharmony_ci#define I2C_BIT_SPD0		0x0001
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/* I2C IICF0 Masks */
6162306a36Sopenharmony_ci#define I2C_BIT_STCF		0x0080
6262306a36Sopenharmony_ci#define I2C_BIT_IICBSY		0x0040
6362306a36Sopenharmony_ci#define I2C_BIT_STCEN		0x0002
6462306a36Sopenharmony_ci#define I2C_BIT_IICRSV		0x0001
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct em_i2c_device {
6762306a36Sopenharmony_ci	void __iomem *base;
6862306a36Sopenharmony_ci	struct i2c_adapter adap;
6962306a36Sopenharmony_ci	struct completion msg_done;
7062306a36Sopenharmony_ci	struct clk *sclk;
7162306a36Sopenharmony_ci	struct i2c_client *slave;
7262306a36Sopenharmony_ci	int irq;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	writeb((readb(priv->base + reg) & ~clear) | set, priv->base + reg);
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic int em_i2c_wait_for_event(struct em_i2c_device *priv)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	unsigned long time_left;
8362306a36Sopenharmony_ci	int status;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	reinit_completion(&priv->msg_done);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	time_left = wait_for_completion_timeout(&priv->msg_done, priv->adap.timeout);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	if (!time_left)
9062306a36Sopenharmony_ci		return -ETIMEDOUT;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	status = readb(priv->base + I2C_OFS_IICSE0);
9362306a36Sopenharmony_ci	return status & I2C_BIT_ALD0 ? -EAGAIN : status;
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic void em_i2c_stop(struct em_i2c_device *priv)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	/* Send Stop condition */
9962306a36Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_SPT0 | I2C_BIT_SPIE0, I2C_OFS_IICC0);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	/* Wait for stop condition */
10262306a36Sopenharmony_ci	em_i2c_wait_for_event(priv);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic void em_i2c_reset(struct i2c_adapter *adap)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(adap);
10862306a36Sopenharmony_ci	int retr;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/* If I2C active */
11162306a36Sopenharmony_ci	if (readb(priv->base + I2C_OFS_IICACT0) & I2C_BIT_IICE0) {
11262306a36Sopenharmony_ci		/* Disable I2C operation */
11362306a36Sopenharmony_ci		writeb(0, priv->base + I2C_OFS_IICACT0);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci		retr = 1000;
11662306a36Sopenharmony_ci		while (readb(priv->base + I2C_OFS_IICACT0) == 1 && retr)
11762306a36Sopenharmony_ci			retr--;
11862306a36Sopenharmony_ci		WARN_ON(retr == 0);
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* Transfer mode set */
12262306a36Sopenharmony_ci	writeb(I2C_BIT_DFC0, priv->base + I2C_OFS_IICCL0);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	/* Can Issue start without detecting a stop, Reservation disabled. */
12562306a36Sopenharmony_ci	writeb(I2C_BIT_STCEN | I2C_BIT_IICRSV, priv->base + I2C_OFS_IICF0);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/* I2C enable, 9 bit interrupt mode */
12862306a36Sopenharmony_ci	writeb(I2C_BIT_WTIM0, priv->base + I2C_OFS_IICC0);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* Enable I2C operation */
13162306a36Sopenharmony_ci	writeb(I2C_BIT_IICE0, priv->base + I2C_OFS_IICACT0);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	retr = 1000;
13462306a36Sopenharmony_ci	while (readb(priv->base + I2C_OFS_IICACT0) == 0 && retr)
13562306a36Sopenharmony_ci		retr--;
13662306a36Sopenharmony_ci	WARN_ON(retr == 0);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic int __em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
14062306a36Sopenharmony_ci				int stop)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(adap);
14362306a36Sopenharmony_ci	int count, status, read = !!(msg->flags & I2C_M_RD);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	/* Send start condition */
14662306a36Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_ACKE0 | I2C_BIT_WTIM0, I2C_OFS_IICC0);
14762306a36Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_STT0, I2C_OFS_IICC0);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* Send slave address and R/W type */
15062306a36Sopenharmony_ci	writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/* Wait for transaction */
15362306a36Sopenharmony_ci	status = em_i2c_wait_for_event(priv);
15462306a36Sopenharmony_ci	if (status < 0)
15562306a36Sopenharmony_ci		goto out_reset;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* Received NACK (result of setting slave address and R/W) */
15862306a36Sopenharmony_ci	if (!(status & I2C_BIT_ACKD0)) {
15962306a36Sopenharmony_ci		em_i2c_stop(priv);
16062306a36Sopenharmony_ci		goto out;
16162306a36Sopenharmony_ci	}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/* Extra setup for read transactions */
16462306a36Sopenharmony_ci	if (read) {
16562306a36Sopenharmony_ci		/* 8 bit interrupt mode */
16662306a36Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0, I2C_OFS_IICC0);
16762306a36Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0, I2C_OFS_IICC0);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci		/* Wait for transaction */
17062306a36Sopenharmony_ci		status = em_i2c_wait_for_event(priv);
17162306a36Sopenharmony_ci		if (status < 0)
17262306a36Sopenharmony_ci			goto out_reset;
17362306a36Sopenharmony_ci	}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	/* Send / receive data */
17662306a36Sopenharmony_ci	for (count = 0; count < msg->len; count++) {
17762306a36Sopenharmony_ci		if (read) { /* Read transaction */
17862306a36Sopenharmony_ci			msg->buf[count] = readb(priv->base + I2C_OFS_IIC0);
17962306a36Sopenharmony_ci			em_clear_set_bit(priv, 0, I2C_BIT_WREL0, I2C_OFS_IICC0);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		} else { /* Write transaction */
18262306a36Sopenharmony_ci			/* Received NACK */
18362306a36Sopenharmony_ci			if (!(status & I2C_BIT_ACKD0)) {
18462306a36Sopenharmony_ci				em_i2c_stop(priv);
18562306a36Sopenharmony_ci				goto out;
18662306a36Sopenharmony_ci			}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci			/* Write data */
18962306a36Sopenharmony_ci			writeb(msg->buf[count], priv->base + I2C_OFS_IIC0);
19062306a36Sopenharmony_ci		}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci		/* Wait for R/W transaction */
19362306a36Sopenharmony_ci		status = em_i2c_wait_for_event(priv);
19462306a36Sopenharmony_ci		if (status < 0)
19562306a36Sopenharmony_ci			goto out_reset;
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	if (stop)
19962306a36Sopenharmony_ci		em_i2c_stop(priv);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return count;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ciout_reset:
20462306a36Sopenharmony_ci	em_i2c_reset(adap);
20562306a36Sopenharmony_ciout:
20662306a36Sopenharmony_ci	return status < 0 ? status : -ENXIO;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
21062306a36Sopenharmony_ci	int num)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(adap);
21362306a36Sopenharmony_ci	int ret, i;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (readb(priv->base + I2C_OFS_IICF0) & I2C_BIT_IICBSY)
21662306a36Sopenharmony_ci		return -EAGAIN;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
21962306a36Sopenharmony_ci		ret = __em_i2c_xfer(adap, &msgs[i], (i == (num - 1)));
22062306a36Sopenharmony_ci		if (ret < 0)
22162306a36Sopenharmony_ci			return ret;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/* I2C transfer completed */
22562306a36Sopenharmony_ci	return num;
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic bool em_i2c_slave_irq(struct em_i2c_device *priv)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	u8 status, value;
23162306a36Sopenharmony_ci	enum i2c_slave_event event;
23262306a36Sopenharmony_ci	int ret;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	if (!priv->slave)
23562306a36Sopenharmony_ci		return false;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	status = readb(priv->base + I2C_OFS_IICSE0);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	/* Extension code, do not participate */
24062306a36Sopenharmony_ci	if (status & I2C_BIT_EXC0) {
24162306a36Sopenharmony_ci		em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
24262306a36Sopenharmony_ci		return true;
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	/* Stop detected, we don't know if it's for slave or master */
24662306a36Sopenharmony_ci	if (status & I2C_BIT_SPD0) {
24762306a36Sopenharmony_ci		/* Notify slave device */
24862306a36Sopenharmony_ci		i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
24962306a36Sopenharmony_ci		/* Pretend we did not handle the interrupt */
25062306a36Sopenharmony_ci		return false;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Only handle interrupts addressed to us */
25462306a36Sopenharmony_ci	if (!(status & I2C_BIT_COI0))
25562306a36Sopenharmony_ci		return false;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	/* Enable stop interrupts */
25862306a36Sopenharmony_ci	em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	/* Transmission or Reception */
26162306a36Sopenharmony_ci	if (status & I2C_BIT_TRC0) {
26262306a36Sopenharmony_ci		if (status & I2C_BIT_ACKD0) {
26362306a36Sopenharmony_ci			/* 9 bit interrupt mode */
26462306a36Sopenharmony_ci			em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci			/* Send data */
26762306a36Sopenharmony_ci			event = status & I2C_BIT_STD0 ?
26862306a36Sopenharmony_ci				I2C_SLAVE_READ_REQUESTED :
26962306a36Sopenharmony_ci				I2C_SLAVE_READ_PROCESSED;
27062306a36Sopenharmony_ci			i2c_slave_event(priv->slave, event, &value);
27162306a36Sopenharmony_ci			writeb(value, priv->base + I2C_OFS_IIC0);
27262306a36Sopenharmony_ci		} else {
27362306a36Sopenharmony_ci			/* NACK, stop transmitting */
27462306a36Sopenharmony_ci			em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
27562306a36Sopenharmony_ci		}
27662306a36Sopenharmony_ci	} else {
27762306a36Sopenharmony_ci		/* 8 bit interrupt mode */
27862306a36Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0,
27962306a36Sopenharmony_ci				I2C_OFS_IICC0);
28062306a36Sopenharmony_ci		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0,
28162306a36Sopenharmony_ci				I2C_OFS_IICC0);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci		if (status & I2C_BIT_STD0) {
28462306a36Sopenharmony_ci			i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED,
28562306a36Sopenharmony_ci					&value);
28662306a36Sopenharmony_ci		} else {
28762306a36Sopenharmony_ci			/* Recv data */
28862306a36Sopenharmony_ci			value = readb(priv->base + I2C_OFS_IIC0);
28962306a36Sopenharmony_ci			ret = i2c_slave_event(priv->slave,
29062306a36Sopenharmony_ci					I2C_SLAVE_WRITE_RECEIVED, &value);
29162306a36Sopenharmony_ci			if (ret < 0)
29262306a36Sopenharmony_ci				em_clear_set_bit(priv, I2C_BIT_ACKE0, 0,
29362306a36Sopenharmony_ci						I2C_OFS_IICC0);
29462306a36Sopenharmony_ci		}
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	return true;
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	struct em_i2c_device *priv = dev_id;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	if (em_i2c_slave_irq(priv))
30562306a36Sopenharmony_ci		return IRQ_HANDLED;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	complete(&priv->msg_done);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	return IRQ_HANDLED;
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic u32 em_i2c_func(struct i2c_adapter *adap)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic int em_i2c_reg_slave(struct i2c_client *slave)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	if (priv->slave)
32262306a36Sopenharmony_ci		return -EBUSY;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	if (slave->flags & I2C_CLIENT_TEN)
32562306a36Sopenharmony_ci		return -EAFNOSUPPORT;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	priv->slave = slave;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	/* Set slave address */
33062306a36Sopenharmony_ci	writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	return 0;
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistatic int em_i2c_unreg_slave(struct i2c_client *slave)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	WARN_ON(!priv->slave);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	writeb(0, priv->base + I2C_OFS_SVA0);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	/*
34462306a36Sopenharmony_ci	 * Wait for interrupt to finish. New slave irqs cannot happen because we
34562306a36Sopenharmony_ci	 * cleared the slave address and, thus, only extension codes will be
34662306a36Sopenharmony_ci	 * detected which do not use the slave ptr.
34762306a36Sopenharmony_ci	 */
34862306a36Sopenharmony_ci	synchronize_irq(priv->irq);
34962306a36Sopenharmony_ci	priv->slave = NULL;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	return 0;
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic const struct i2c_algorithm em_i2c_algo = {
35562306a36Sopenharmony_ci	.master_xfer = em_i2c_xfer,
35662306a36Sopenharmony_ci	.functionality = em_i2c_func,
35762306a36Sopenharmony_ci	.reg_slave      = em_i2c_reg_slave,
35862306a36Sopenharmony_ci	.unreg_slave    = em_i2c_unreg_slave,
35962306a36Sopenharmony_ci};
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_cistatic int em_i2c_probe(struct platform_device *pdev)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	struct em_i2c_device *priv;
36462306a36Sopenharmony_ci	int ret;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
36762306a36Sopenharmony_ci	if (!priv)
36862306a36Sopenharmony_ci		return -ENOMEM;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	priv->base = devm_platform_ioremap_resource(pdev, 0);
37162306a36Sopenharmony_ci	if (IS_ERR(priv->base))
37262306a36Sopenharmony_ci		return PTR_ERR(priv->base);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	strscpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name));
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	priv->sclk = devm_clk_get(&pdev->dev, "sclk");
37762306a36Sopenharmony_ci	if (IS_ERR(priv->sclk))
37862306a36Sopenharmony_ci		return PTR_ERR(priv->sclk);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	ret = clk_prepare_enable(priv->sclk);
38162306a36Sopenharmony_ci	if (ret)
38262306a36Sopenharmony_ci		return ret;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	priv->adap.timeout = msecs_to_jiffies(100);
38562306a36Sopenharmony_ci	priv->adap.retries = 5;
38662306a36Sopenharmony_ci	priv->adap.dev.parent = &pdev->dev;
38762306a36Sopenharmony_ci	priv->adap.algo = &em_i2c_algo;
38862306a36Sopenharmony_ci	priv->adap.owner = THIS_MODULE;
38962306a36Sopenharmony_ci	priv->adap.dev.of_node = pdev->dev.of_node;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	init_completion(&priv->msg_done);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	platform_set_drvdata(pdev, priv);
39462306a36Sopenharmony_ci	i2c_set_adapdata(&priv->adap, priv);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	em_i2c_reset(&priv->adap);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	ret = platform_get_irq(pdev, 0);
39962306a36Sopenharmony_ci	if (ret < 0)
40062306a36Sopenharmony_ci		goto err_clk;
40162306a36Sopenharmony_ci	priv->irq = ret;
40262306a36Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
40362306a36Sopenharmony_ci				"em_i2c", priv);
40462306a36Sopenharmony_ci	if (ret)
40562306a36Sopenharmony_ci		goto err_clk;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	ret = i2c_add_adapter(&priv->adap);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	if (ret)
41062306a36Sopenharmony_ci		goto err_clk;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr,
41362306a36Sopenharmony_ci		 priv->irq);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	return 0;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cierr_clk:
41862306a36Sopenharmony_ci	clk_disable_unprepare(priv->sclk);
41962306a36Sopenharmony_ci	return ret;
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic void em_i2c_remove(struct platform_device *dev)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	struct em_i2c_device *priv = platform_get_drvdata(dev);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	i2c_del_adapter(&priv->adap);
42762306a36Sopenharmony_ci	clk_disable_unprepare(priv->sclk);
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic const struct of_device_id em_i2c_ids[] = {
43162306a36Sopenharmony_ci	{ .compatible = "renesas,iic-emev2", },
43262306a36Sopenharmony_ci	{ }
43362306a36Sopenharmony_ci};
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic struct platform_driver em_i2c_driver = {
43662306a36Sopenharmony_ci	.probe = em_i2c_probe,
43762306a36Sopenharmony_ci	.remove_new = em_i2c_remove,
43862306a36Sopenharmony_ci	.driver = {
43962306a36Sopenharmony_ci		.name = "em-i2c",
44062306a36Sopenharmony_ci		.of_match_table = em_i2c_ids,
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci};
44362306a36Sopenharmony_cimodule_platform_driver(em_i2c_driver);
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ciMODULE_DESCRIPTION("EMEV2 I2C bus driver");
44662306a36Sopenharmony_ciMODULE_AUTHOR("Ian Molton");
44762306a36Sopenharmony_ciMODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
44862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
44962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, em_i2c_ids);
450