1/*
2 * I2C bus driver for Conexant Digicolor SoCs
3 *
4 * Author: Baruch Siach <baruch@tkos.co.il>
5 *
6 * Copyright (C) 2015 Paradox Innovation Ltd.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/clk.h>
14#include <linux/completion.h>
15#include <linux/delay.h>
16#include <linux/i2c.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/platform_device.h>
23
24#define DEFAULT_FREQ		100000
25#define TIMEOUT_MS		100
26
27#define II_CONTROL		0x0
28#define II_CONTROL_LOCAL_RESET	BIT(0)
29
30#define II_CLOCKTIME		0x1
31
32#define II_COMMAND		0x2
33#define II_CMD_START		1
34#define II_CMD_RESTART		2
35#define II_CMD_SEND_ACK		3
36#define II_CMD_GET_ACK		6
37#define II_CMD_GET_NOACK	7
38#define II_CMD_STOP		10
39#define II_COMMAND_GO		BIT(7)
40#define II_COMMAND_COMPLETION_STATUS(r)	(((r) >> 5) & 3)
41#define II_CMD_STATUS_NORMAL	0
42#define II_CMD_STATUS_ACK_GOOD	1
43#define II_CMD_STATUS_ACK_BAD	2
44#define II_CMD_STATUS_ABORT	3
45
46#define II_DATA			0x3
47#define II_INTFLAG_CLEAR	0x8
48#define II_INTENABLE		0xa
49
50struct dc_i2c {
51	struct i2c_adapter	adap;
52	struct device		*dev;
53	void __iomem		*regs;
54	struct clk		*clk;
55	unsigned int		frequency;
56
57	struct i2c_msg		*msg;
58	unsigned int		msgbuf_ptr;
59	int			last;
60	spinlock_t		lock;
61	struct completion	done;
62	int			state;
63	int			error;
64};
65
66enum {
67	STATE_IDLE,
68	STATE_START,
69	STATE_ADDR,
70	STATE_WRITE,
71	STATE_READ,
72	STATE_STOP,
73};
74
75static void dc_i2c_cmd(struct dc_i2c *i2c, u8 cmd)
76{
77	writeb_relaxed(cmd | II_COMMAND_GO, i2c->regs + II_COMMAND);
78}
79
80static u8 dc_i2c_addr_cmd(struct i2c_msg *msg)
81{
82	u8 addr = (msg->addr & 0x7f) << 1;
83
84	if (msg->flags & I2C_M_RD)
85		addr |= 1;
86
87	return addr;
88}
89
90static void dc_i2c_data(struct dc_i2c *i2c, u8 data)
91{
92	writeb_relaxed(data, i2c->regs + II_DATA);
93}
94
95static void dc_i2c_write_byte(struct dc_i2c *i2c, u8 byte)
96{
97	dc_i2c_data(i2c, byte);
98	dc_i2c_cmd(i2c, II_CMD_SEND_ACK);
99}
100
101static void dc_i2c_write_buf(struct dc_i2c *i2c)
102{
103	dc_i2c_write_byte(i2c, i2c->msg->buf[i2c->msgbuf_ptr++]);
104}
105
106static void dc_i2c_next_read(struct dc_i2c *i2c)
107{
108	bool last = (i2c->msgbuf_ptr + 1 == i2c->msg->len);
109
110	dc_i2c_cmd(i2c, last ? II_CMD_GET_NOACK : II_CMD_GET_ACK);
111}
112
113static void dc_i2c_stop(struct dc_i2c *i2c)
114{
115	i2c->state = STATE_STOP;
116	if (i2c->last)
117		dc_i2c_cmd(i2c, II_CMD_STOP);
118	else
119		complete(&i2c->done);
120}
121
122static u8 dc_i2c_read_byte(struct dc_i2c *i2c)
123{
124	return readb_relaxed(i2c->regs + II_DATA);
125}
126
127static void dc_i2c_read_buf(struct dc_i2c *i2c)
128{
129	i2c->msg->buf[i2c->msgbuf_ptr++] = dc_i2c_read_byte(i2c);
130	dc_i2c_next_read(i2c);
131}
132
133static void dc_i2c_set_irq(struct dc_i2c *i2c, int enable)
134{
135	if (enable)
136		writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
137	writeb_relaxed(!!enable, i2c->regs + II_INTENABLE);
138}
139
140static int dc_i2c_cmd_status(struct dc_i2c *i2c)
141{
142	u8 cmd = readb_relaxed(i2c->regs + II_COMMAND);
143
144	return II_COMMAND_COMPLETION_STATUS(cmd);
145}
146
147static void dc_i2c_start_msg(struct dc_i2c *i2c, int first)
148{
149	struct i2c_msg *msg = i2c->msg;
150
151	if (!(msg->flags & I2C_M_NOSTART)) {
152		i2c->state = STATE_START;
153		dc_i2c_cmd(i2c, first ? II_CMD_START : II_CMD_RESTART);
154	} else if (msg->flags & I2C_M_RD) {
155		i2c->state = STATE_READ;
156		dc_i2c_next_read(i2c);
157	} else {
158		i2c->state = STATE_WRITE;
159		dc_i2c_write_buf(i2c);
160	}
161}
162
163static irqreturn_t dc_i2c_irq(int irq, void *dev_id)
164{
165	struct dc_i2c *i2c = dev_id;
166	int cmd_status = dc_i2c_cmd_status(i2c);
167	unsigned long flags;
168	u8 addr_cmd;
169
170	writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
171
172	spin_lock_irqsave(&i2c->lock, flags);
173
174	if (cmd_status == II_CMD_STATUS_ACK_BAD
175	    || cmd_status == II_CMD_STATUS_ABORT) {
176		i2c->error = -EIO;
177		complete(&i2c->done);
178		goto out;
179	}
180
181	switch (i2c->state) {
182	case STATE_START:
183		addr_cmd = dc_i2c_addr_cmd(i2c->msg);
184		dc_i2c_write_byte(i2c, addr_cmd);
185		i2c->state = STATE_ADDR;
186		break;
187	case STATE_ADDR:
188		if (i2c->msg->flags & I2C_M_RD) {
189			dc_i2c_next_read(i2c);
190			i2c->state = STATE_READ;
191			break;
192		}
193		i2c->state = STATE_WRITE;
194		/* fall through */
195	case STATE_WRITE:
196		if (i2c->msgbuf_ptr < i2c->msg->len)
197			dc_i2c_write_buf(i2c);
198		else
199			dc_i2c_stop(i2c);
200		break;
201	case STATE_READ:
202		if (i2c->msgbuf_ptr < i2c->msg->len)
203			dc_i2c_read_buf(i2c);
204		else
205			dc_i2c_stop(i2c);
206		break;
207	case STATE_STOP:
208		i2c->state = STATE_IDLE;
209		complete(&i2c->done);
210		break;
211	}
212
213out:
214	spin_unlock_irqrestore(&i2c->lock, flags);
215	return IRQ_HANDLED;
216}
217
218static int dc_i2c_xfer_msg(struct dc_i2c *i2c, struct i2c_msg *msg, int first,
219			   int last)
220{
221	unsigned long timeout = msecs_to_jiffies(TIMEOUT_MS);
222	unsigned long flags;
223
224	spin_lock_irqsave(&i2c->lock, flags);
225	i2c->msg = msg;
226	i2c->msgbuf_ptr = 0;
227	i2c->last = last;
228	i2c->error = 0;
229
230	reinit_completion(&i2c->done);
231	dc_i2c_set_irq(i2c, 1);
232	dc_i2c_start_msg(i2c, first);
233	spin_unlock_irqrestore(&i2c->lock, flags);
234
235	timeout = wait_for_completion_timeout(&i2c->done, timeout);
236	dc_i2c_set_irq(i2c, 0);
237	if (timeout == 0) {
238		i2c->state = STATE_IDLE;
239		return -ETIMEDOUT;
240	}
241
242	if (i2c->error)
243		return i2c->error;
244
245	return 0;
246}
247
248static int dc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
249{
250	struct dc_i2c *i2c = adap->algo_data;
251	int i, ret;
252
253	for (i = 0; i < num; i++) {
254		ret = dc_i2c_xfer_msg(i2c, &msgs[i], i == 0, i == num - 1);
255		if (ret)
256			return ret;
257	}
258
259	return num;
260}
261
262static int dc_i2c_init_hw(struct dc_i2c *i2c)
263{
264	unsigned long clk_rate = clk_get_rate(i2c->clk);
265	unsigned int clocktime;
266
267	writeb_relaxed(II_CONTROL_LOCAL_RESET, i2c->regs + II_CONTROL);
268	udelay(100);
269	writeb_relaxed(0, i2c->regs + II_CONTROL);
270	udelay(100);
271
272	clocktime = DIV_ROUND_UP(clk_rate, 64 * i2c->frequency);
273	if (clocktime < 1 || clocktime > 0xff) {
274		dev_err(i2c->dev, "can't set bus speed of %u Hz\n",
275			i2c->frequency);
276		return -EINVAL;
277	}
278	writeb_relaxed(clocktime - 1, i2c->regs + II_CLOCKTIME);
279
280	return 0;
281}
282
283static u32 dc_i2c_func(struct i2c_adapter *adap)
284{
285	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART;
286}
287
288static const struct i2c_algorithm dc_i2c_algorithm = {
289	.master_xfer	= dc_i2c_xfer,
290	.functionality	= dc_i2c_func,
291};
292
293static int dc_i2c_probe(struct platform_device *pdev)
294{
295	struct device_node *np = pdev->dev.of_node;
296	struct dc_i2c *i2c;
297	struct resource *r;
298	int ret = 0, irq;
299
300	i2c = devm_kzalloc(&pdev->dev, sizeof(struct dc_i2c), GFP_KERNEL);
301	if (!i2c)
302		return -ENOMEM;
303
304	if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
305				 &i2c->frequency))
306		i2c->frequency = DEFAULT_FREQ;
307
308	i2c->dev = &pdev->dev;
309	platform_set_drvdata(pdev, i2c);
310
311	spin_lock_init(&i2c->lock);
312	init_completion(&i2c->done);
313
314	i2c->clk = devm_clk_get(&pdev->dev, NULL);
315	if (IS_ERR(i2c->clk))
316		return PTR_ERR(i2c->clk);
317
318	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
319	i2c->regs = devm_ioremap_resource(&pdev->dev, r);
320	if (IS_ERR(i2c->regs))
321		return PTR_ERR(i2c->regs);
322
323	irq = platform_get_irq(pdev, 0);
324	if (irq < 0)
325		return irq;
326
327	ret = devm_request_irq(&pdev->dev, irq, dc_i2c_irq, 0,
328			       dev_name(&pdev->dev), i2c);
329	if (ret < 0)
330		return ret;
331
332	strlcpy(i2c->adap.name, "Conexant Digicolor I2C adapter",
333		sizeof(i2c->adap.name));
334	i2c->adap.owner = THIS_MODULE;
335	i2c->adap.algo = &dc_i2c_algorithm;
336	i2c->adap.dev.parent = &pdev->dev;
337	i2c->adap.dev.of_node = np;
338	i2c->adap.algo_data = i2c;
339
340	ret = dc_i2c_init_hw(i2c);
341	if (ret)
342		return ret;
343
344	ret = clk_prepare_enable(i2c->clk);
345	if (ret < 0)
346		return ret;
347
348	ret = i2c_add_adapter(&i2c->adap);
349	if (ret < 0) {
350		clk_unprepare(i2c->clk);
351		return ret;
352	}
353
354	return 0;
355}
356
357static int dc_i2c_remove(struct platform_device *pdev)
358{
359	struct dc_i2c *i2c = platform_get_drvdata(pdev);
360
361	i2c_del_adapter(&i2c->adap);
362	clk_disable_unprepare(i2c->clk);
363
364	return 0;
365}
366
367static const struct of_device_id dc_i2c_match[] = {
368	{ .compatible = "cnxt,cx92755-i2c" },
369	{ },
370};
371
372static struct platform_driver dc_i2c_driver = {
373	.probe   = dc_i2c_probe,
374	.remove  = dc_i2c_remove,
375	.driver  = {
376		.name  = "digicolor-i2c",
377		.of_match_table = dc_i2c_match,
378	},
379};
380module_platform_driver(dc_i2c_driver);
381
382MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
383MODULE_DESCRIPTION("Conexant Digicolor I2C master driver");
384MODULE_LICENSE("GPL v2");
385