1 /* ------------------------------------------------------------------------- */
2 /* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */
3 /* ------------------------------------------------------------------------- */
4 /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
5 * <Peter dot Milne at D hyphen TACQ dot com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, version 2.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* ------------------------------------------------------------------------- */
22 With acknowledgements to i2c-algo-ibm_ocp.c by
23 Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
25 And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
27 Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
29 And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
30 Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
32 ---------------------------------------------------------------------------*/
34 #include <linux/config.h>
35 #include <linux/interrupt.h>
36 #include <linux/kernel.h>
37 #include <linux/module.h>
38 #include <linux/delay.h>
39 #include <linux/slab.h>
40 #include <linux/init.h>
41 #include <linux/errno.h>
42 #include <linux/sched.h>
43 #include <linux/i2c.h>
46 #include <asm/arch-iop3xx/iop321.h>
47 #include <asm/arch-iop3xx/iop321-irqs.h>
48 #include "i2c-iop3xx.h"
51 /* ----- global defines ----------------------------------------------- */
52 #define PASSERT(x) do { if (!(x) ) \
53 printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
57 /* ----- global variables --------------------------------------------- */
60 static inline unsigned char iic_cook_addr(struct i2c_msg *msg)
64 addr = (msg->addr << 1);
66 if (msg->flags & I2C_M_RD)
69 /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
70 if (msg->flags & I2C_M_REV_DIR_ADDR)
77 static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
79 /* Follows devman 9.3 */
80 *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
81 *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
82 *iop3xx_adap->biu->CR = 0;
85 static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
87 *iop3xx_adap->biu->SAR = MYSAR;
90 static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
92 u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
94 /* NB SR bits not same position as CR IE bits :-( */
95 iop3xx_adap->biu->SR_enabled =
96 IOP321_ISR_ALD | IOP321_ISR_BERRD |
97 IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
99 cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
100 IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
102 *iop3xx_adap->biu->CR = cr;
105 static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
107 unsigned cr = *iop3xx_adap->biu->CR;
109 cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
110 IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
111 *iop3xx_adap->biu->CR = cr;
114 static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
116 unsigned cr = *iop3xx_adap->biu->CR;
118 cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
119 IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
120 iop3xx_adap->biu->SR_enabled = 0;
121 *iop3xx_adap->biu->CR = cr;
125 * NB: the handler has to clear the source of the interrupt!
126 * Then it passes the SR flags of interest to BH via adap data
128 static irqreturn_t iop3xx_i2c_handler(int this_irq,
130 struct pt_regs *regs)
132 struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
134 u32 sr = *iop3xx_adap->biu->SR;
136 if ((sr &= iop3xx_adap->biu->SR_enabled)) {
137 *iop3xx_adap->biu->SR = sr;
138 iop3xx_adap->biu->SR_received |= sr;
139 wake_up_interruptible(&iop3xx_adap->waitq);
144 /* check all error conditions, clear them , report most important */
145 static int iop3xx_adap_error(u32 sr)
149 if ((sr&IOP321_ISR_BERRD)) {
150 if ( !rc ) rc = -I2C_ERR_BERR;
152 if ((sr&IOP321_ISR_ALD)) {
153 if ( !rc ) rc = -I2C_ERR_ALD;
158 static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
163 spin_lock_irqsave(&iop3xx_adap->lock, flags);
164 sr = iop3xx_adap->biu->SR_received;
165 iop3xx_adap->biu->SR_received = 0;
166 spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
172 * sleep until interrupted, then recover and analyse the SR
175 typedef int (* compare_func)(unsigned test, unsigned mask);
176 /* returns 1 on correct comparison */
178 static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
179 unsigned flags, unsigned* status,
180 compare_func compare)
188 interrupted = wait_event_interruptible_timeout (
190 (done = compare( sr = get_srstat(iop3xx_adap),flags )),
193 if ((rc = iop3xx_adap_error(sr)) < 0) {
196 }else if (!interrupted) {
208 * Concrete compare_funcs
210 static int all_bits_clear(unsigned test, unsigned mask)
212 return (test & mask) == 0;
214 static int any_bits_set(unsigned test, unsigned mask)
216 return (test & mask) != 0;
219 static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
221 return iop3xx_adap_wait_event(
223 IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
224 status, any_bits_set);
227 static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
229 return iop3xx_adap_wait_event(
231 IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
232 status, any_bits_set);
235 static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
237 return iop3xx_adap_wait_event(
238 iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
242 * Description: This performs the IOP3xx initialization sequence
243 * Valid for IOP321. Maybe valid for IOP310?.
245 static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap)
247 *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ?
251 iop3xx_adap_reset(iop3xx_adap);
252 iop3xx_adap_set_slave_addr(iop3xx_adap);
253 iop3xx_adap_enable(iop3xx_adap);
258 static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
261 unsigned cr = *iop3xx_adap->biu->CR;
265 *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
267 cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
268 cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
270 *iop3xx_adap->biu->CR = cr;
271 rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
272 /* this assert fires every time, contrary to IOP manual
273 PASSERT((status&IOP321_ISR_UNITBUSY)!=0);
275 PASSERT((status&IOP321_ISR_RXREAD)==0);
280 static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
282 unsigned cr = *iop3xx_adap->biu->CR;
286 *iop3xx_adap->biu->DBR = byte;
287 cr &= ~IOP321_ICR_MSTART;
289 cr |= IOP321_ICR_MSTOP;
291 cr &= ~IOP321_ICR_MSTOP;
293 *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
294 rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
299 static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
300 char* byte, int stop)
302 unsigned cr = *iop3xx_adap->biu->CR;
306 cr &= ~IOP321_ICR_MSTART;
309 cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
311 cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
313 *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
315 rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
317 *byte = *iop3xx_adap->biu->DBR;
322 static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap,
323 const char *buf, int count)
325 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
329 for (ii = 0; rc == 0 && ii != count; ++ii) {
330 rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);
335 static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap,
336 char *buf, int count)
338 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
342 for (ii = 0; rc == 0 && ii != count; ++ii) {
343 rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
349 * Description: This function implements combined transactions. Combined
350 * transactions consist of combinations of reading and writing blocks of data.
351 * FROM THE SAME ADDRESS
352 * Each transfer (i.e. a read or a write) is separated by a repeated start
355 static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
357 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
360 rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
365 if ((pmsg->flags&I2C_M_RD)) {
366 return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
368 return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
373 * master_xfer() - main read/write entry
375 static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
377 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
382 iop3xx_adap_wait_idle(iop3xx_adap, &status);
383 iop3xx_adap_reset(iop3xx_adap);
384 iop3xx_adap_enable(iop3xx_adap);
386 for (im = 0; ret == 0 && im != num; im++) {
387 ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
390 iop3xx_adap_transaction_cleanup(iop3xx_adap);
398 static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
404 static u32 iic_func(struct i2c_adapter *adap)
406 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
410 /* -----exported algorithm data: ------------------------------------- */
412 static struct i2c_algorithm iic_algo = {
413 .name = "IOP3xx I2C algorithm",
414 .id = I2C_ALGO_OCP_IOP3XX,
415 .master_xfer = iop3xx_master_xfer,
416 .algo_control = algo_control,
417 .functionality = iic_func,
421 * registering functions to load algorithms at runtime
423 static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
425 struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
427 if (!request_region( REGION_START(iop3xx_adap),
428 REGION_LENGTH(iop3xx_adap),
433 init_waitqueue_head(&iop3xx_adap->waitq);
434 spin_lock_init(&iop3xx_adap->lock);
437 iop3xx_adap->biu->irq,
439 /* SA_SAMPLE_RANDOM */ 0,
445 /* register new iic_adapter to i2c module... */
446 iic_adap->id |= iic_algo.id;
447 iic_adap->algo = &iic_algo;
449 iic_adap->timeout = 100; /* default values, should */
450 iic_adap->retries = 3; /* be replaced by defines */
452 iop3xx_adap_init(iic_adap->algo_data);
453 i2c_add_adapter(iic_adap);
457 static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
459 struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
461 iop3xx_adap_final_cleanup(iop3xx_adap);
462 free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
464 release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
466 return i2c_del_adapter(iic_adap);
469 #ifdef CONFIG_ARCH_IOP321
471 static struct iop3xx_biu biu0 = {
477 .irq = IRQ_IOP321_I2C_0,
480 static struct iop3xx_biu biu1 = {
486 .irq = IRQ_IOP321_I2C_1,
489 #define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
491 #error Please define the BIU struct iop3xx_biu for your processor arch
494 static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
499 static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
505 static struct i2c_adapter iop3xx_ops0 = {
506 .owner = THIS_MODULE,
507 .name = ADAPTER_NAME_ROOT "0",
509 .algo_data = &algo_iop3xx_data0,
511 static struct i2c_adapter iop3xx_ops1 = {
512 .owner = THIS_MODULE,
513 .name = ADAPTER_NAME_ROOT "1",
515 .algo_data = &algo_iop3xx_data1,
518 static int __init i2c_iop3xx_init (void)
520 return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
521 i2c_iop3xx_add_bus(&iop3xx_ops1);
524 static void __exit i2c_iop3xx_exit (void)
526 i2c_iop3xx_del_bus(&iop3xx_ops0);
527 i2c_iop3xx_del_bus(&iop3xx_ops1);
530 module_init (i2c_iop3xx_init);
531 module_exit (i2c_iop3xx_exit);
533 MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
534 MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
535 MODULE_LICENSE("GPL");