1/* ------------------------------------------------------------------------- */
2/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x       */
3/* ------------------------------------------------------------------------- */
4/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
5 *                    <Peter dot Milne at D hyphen TACQ dot com>
6 *
7 * With acknowledgements to i2c-algo-ibm_ocp.c by
8 * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
9 *
10 * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
11 *
12 * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
13 *
14 * And which acknowledged Ky��sti M��lkki <kmalkki@cc.hut.fi>,
15 * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
16 *
17 * Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005:
18 *
19 * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs
20 * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference
21 * - Make it work with IXP46x chips
22 * - Cleanup function names, coding style, etc
23 *
24 * - writing to slave address causes latchup on iop331.
25 *	fix: driver refuses to address self.
26 *
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation, version 2.
30 */
31
32#include <linux/interrupt.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/delay.h>
36#include <linux/slab.h>
37#include <linux/init.h>
38#include <linux/errno.h>
39#include <linux/platform_device.h>
40#include <linux/i2c.h>
41
42#include <asm/io.h>
43
44#include "i2c-iop3xx.h"
45
46/* global unit counter */
47static int i2c_id;
48
49static inline unsigned char
50iic_cook_addr(struct i2c_msg *msg)
51{
52	unsigned char addr;
53
54	addr = (msg->addr << 1);
55
56	if (msg->flags & I2C_M_RD)
57		addr |= 1;
58
59	/*
60	 * Read or Write?
61	 */
62	if (msg->flags & I2C_M_REV_DIR_ADDR)
63		addr ^= 1;
64
65	return addr;
66}
67
68static void
69iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
70{
71	/* Follows devman 9.3 */
72	__raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
73	__raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
74	__raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
75}
76
77static void
78iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
79{
80	u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
81
82	/*
83	 * Every time unit enable is asserted, GPOD needs to be cleared
84	 * on IOP3XX to avoid data corruption on the bus.
85	 */
86#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
87	if (iop3xx_adap->id == 0) {
88		gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
89		gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
90	} else {
91		gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW);
92		gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW);
93	}
94#endif
95	/* NB SR bits not same position as CR IE bits :-( */
96	iop3xx_adap->SR_enabled =
97		IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
98		IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
99
100	cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
101		IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE;
102
103	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
104}
105
106static void
107iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
108{
109	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
110
111	cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
112		IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
113
114	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
115}
116
117/*
118 * NB: the handler has to clear the source of the interrupt!
119 * Then it passes the SR flags of interest to BH via adap data
120 */
121static irqreturn_t
122iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
123{
124	struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
125	u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
126
127	if ((sr &= iop3xx_adap->SR_enabled)) {
128		__raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET);
129		iop3xx_adap->SR_received |= sr;
130		wake_up_interruptible(&iop3xx_adap->waitq);
131	}
132	return IRQ_HANDLED;
133}
134
135/* check all error conditions, clear them , report most important */
136static int
137iop3xx_i2c_error(u32 sr)
138{
139	int rc = 0;
140
141	if ((sr & IOP3XX_ISR_BERRD)) {
142		if ( !rc ) rc = -I2C_ERR_BERR;
143	}
144	if ((sr & IOP3XX_ISR_ALD)) {
145		if ( !rc ) rc = -I2C_ERR_ALD;
146	}
147	return rc;
148}
149
150static inline u32
151iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
152{
153	unsigned long flags;
154	u32 sr;
155
156	spin_lock_irqsave(&iop3xx_adap->lock, flags);
157	sr = iop3xx_adap->SR_received;
158	iop3xx_adap->SR_received = 0;
159	spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
160
161	return sr;
162}
163
164/*
165 * sleep until interrupted, then recover and analyse the SR
166 * saved by handler
167 */
168typedef int (* compare_func)(unsigned test, unsigned mask);
169/* returns 1 on correct comparison */
170
171static int
172iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
173			  unsigned flags, unsigned* status,
174			  compare_func compare)
175{
176	unsigned sr = 0;
177	int interrupted;
178	int done;
179	int rc = 0;
180
181	do {
182		interrupted = wait_event_interruptible_timeout (
183			iop3xx_adap->waitq,
184			(done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
185			1 * HZ;
186			);
187		if ((rc = iop3xx_i2c_error(sr)) < 0) {
188			*status = sr;
189			return rc;
190		} else if (!interrupted) {
191			*status = sr;
192			return -ETIMEDOUT;
193		}
194	} while(!done);
195
196	*status = sr;
197
198	return 0;
199}
200
201/*
202 * Concrete compare_funcs
203 */
204static int
205all_bits_clear(unsigned test, unsigned mask)
206{
207	return (test & mask) == 0;
208}
209
210static int
211any_bits_set(unsigned test, unsigned mask)
212{
213	return (test & mask) != 0;
214}
215
216static int
217iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
218{
219	return iop3xx_i2c_wait_event(
220		iop3xx_adap,
221	        IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
222		status, any_bits_set);
223}
224
225static int
226iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
227{
228	return iop3xx_i2c_wait_event(
229		iop3xx_adap,
230		IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
231		status,	any_bits_set);
232}
233
234static int
235iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
236{
237	return iop3xx_i2c_wait_event(
238		iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
239}
240
241static int
242iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
243				struct i2c_msg* msg)
244{
245	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
246	int status;
247	int rc;
248
249	/* avoid writing to my slave address (hangs on 80331),
250	 * forbidden in Intel developer manual
251	 */
252	if (msg->addr == MYSAR) {
253		return -EBUSY;
254	}
255
256	__raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
257
258	cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
259	cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
260
261	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
262	rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
263
264	return rc;
265}
266
267static int
268iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
269				int stop)
270{
271	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
272	int status;
273	int rc = 0;
274
275	__raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET);
276	cr &= ~IOP3XX_ICR_MSTART;
277	if (stop) {
278		cr |= IOP3XX_ICR_MSTOP;
279	} else {
280		cr &= ~IOP3XX_ICR_MSTOP;
281	}
282	cr |= IOP3XX_ICR_TBYTE;
283	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
284	rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
285
286	return rc;
287}
288
289static int
290iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
291				int stop)
292{
293	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
294	int status;
295	int rc = 0;
296
297	cr &= ~IOP3XX_ICR_MSTART;
298
299	if (stop) {
300		cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK;
301	} else {
302		cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
303	}
304	cr |= IOP3XX_ICR_TBYTE;
305	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
306
307	rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status);
308
309	*byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET);
310
311	return rc;
312}
313
314static int
315iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
316{
317	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
318	int ii;
319	int rc = 0;
320
321	for (ii = 0; rc == 0 && ii != count; ++ii)
322		rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
323	return rc;
324}
325
326static int
327iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
328{
329	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
330	int ii;
331	int rc = 0;
332
333	for (ii = 0; rc == 0 && ii != count; ++ii)
334		rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
335
336	return rc;
337}
338
339/*
340 * Description:  This function implements combined transactions.  Combined
341 * transactions consist of combinations of reading and writing blocks of data.
342 * FROM THE SAME ADDRESS
343 * Each transfer (i.e. a read or a write) is separated by a repeated start
344 * condition.
345 */
346static int
347iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
348{
349	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
350	int rc;
351
352	rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg);
353	if (rc < 0) {
354		return rc;
355	}
356
357	if ((pmsg->flags&I2C_M_RD)) {
358		return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
359	} else {
360		return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
361	}
362}
363
364/*
365 * master_xfer() - main read/write entry
366 */
367static int
368iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
369				int num)
370{
371	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
372	int im = 0;
373	int ret = 0;
374	int status;
375
376	iop3xx_i2c_wait_idle(iop3xx_adap, &status);
377	iop3xx_i2c_reset(iop3xx_adap);
378	iop3xx_i2c_enable(iop3xx_adap);
379
380	for (im = 0; ret == 0 && im != num; im++) {
381		ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]);
382	}
383
384	iop3xx_i2c_transaction_cleanup(iop3xx_adap);
385
386	if(ret)
387		return ret;
388
389	return im;
390}
391
392static int
393iop3xx_i2c_algo_control(struct i2c_adapter *adapter, unsigned int cmd,
394			unsigned long arg)
395{
396	return 0;
397}
398
399static u32
400iop3xx_i2c_func(struct i2c_adapter *adap)
401{
402	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
403}
404
405static const struct i2c_algorithm iop3xx_i2c_algo = {
406	.master_xfer	= iop3xx_i2c_master_xfer,
407	.algo_control	= iop3xx_i2c_algo_control,
408	.functionality	= iop3xx_i2c_func,
409};
410
411static int
412iop3xx_i2c_remove(struct platform_device *pdev)
413{
414	struct i2c_adapter *padapter = platform_get_drvdata(pdev);
415	struct i2c_algo_iop3xx_data *adapter_data =
416		(struct i2c_algo_iop3xx_data *)padapter->algo_data;
417	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
418	unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
419
420	/*
421	 * Disable the actual HW unit
422	 */
423	cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
424		IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE);
425	__raw_writel(cr, adapter_data->ioaddr + CR_OFFSET);
426
427	iounmap((void __iomem*)adapter_data->ioaddr);
428	release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
429	kfree(adapter_data);
430	kfree(padapter);
431
432	platform_set_drvdata(pdev, NULL);
433
434	return 0;
435}
436
437static int
438iop3xx_i2c_probe(struct platform_device *pdev)
439{
440	struct resource *res;
441	int ret, irq;
442	struct i2c_adapter *new_adapter;
443	struct i2c_algo_iop3xx_data *adapter_data;
444
445	new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
446	if (!new_adapter) {
447		ret = -ENOMEM;
448		goto out;
449	}
450
451	adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
452	if (!adapter_data) {
453		ret = -ENOMEM;
454		goto free_adapter;
455	}
456
457	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
458	if (!res) {
459		ret = -ENODEV;
460		goto free_both;
461	}
462
463	if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) {
464		ret = -EBUSY;
465		goto free_both;
466	}
467
468	/* set the adapter enumeration # */
469	adapter_data->id = i2c_id++;
470
471	adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE);
472	if (!adapter_data->ioaddr) {
473		ret = -ENOMEM;
474		goto release_region;
475	}
476
477	irq = platform_get_irq(pdev, 0);
478	if (irq < 0) {
479		ret = -ENXIO;
480		goto unmap;
481	}
482	ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
483				pdev->name, adapter_data);
484
485	if (ret) {
486		ret = -EIO;
487		goto unmap;
488	}
489
490	memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
491	new_adapter->id = I2C_HW_IOP3XX;
492	new_adapter->owner = THIS_MODULE;
493	new_adapter->dev.parent = &pdev->dev;
494
495	/*
496	 * Default values...should these come in from board code?
497	 */
498	new_adapter->timeout = 100;
499	new_adapter->retries = 3;
500	new_adapter->algo = &iop3xx_i2c_algo;
501
502	init_waitqueue_head(&adapter_data->waitq);
503	spin_lock_init(&adapter_data->lock);
504
505	iop3xx_i2c_reset(adapter_data);
506	iop3xx_i2c_enable(adapter_data);
507
508	platform_set_drvdata(pdev, new_adapter);
509	new_adapter->algo_data = adapter_data;
510
511	i2c_add_adapter(new_adapter);
512
513	return 0;
514
515unmap:
516	iounmap((void __iomem*)adapter_data->ioaddr);
517
518release_region:
519	release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
520
521free_both:
522	kfree(adapter_data);
523
524free_adapter:
525	kfree(new_adapter);
526
527out:
528	return ret;
529}
530
531
532static struct platform_driver iop3xx_i2c_driver = {
533	.probe		= iop3xx_i2c_probe,
534	.remove		= iop3xx_i2c_remove,
535	.driver		= {
536		.owner	= THIS_MODULE,
537		.name	= "IOP3xx-I2C",
538	},
539};
540
541static int __init
542i2c_iop3xx_init (void)
543{
544	return platform_driver_register(&iop3xx_i2c_driver);
545}
546
547static void __exit
548i2c_iop3xx_exit (void)
549{
550	platform_driver_unregister(&iop3xx_i2c_driver);
551	return;
552}
553
554module_init (i2c_iop3xx_init);
555module_exit (i2c_iop3xx_exit);
556
557MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
558MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
559MODULE_LICENSE("GPL");
560