Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
420 giacomo 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>
6
 
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.
10
 
11
 
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.
16
 
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
/* ------------------------------------------------------------------------- */
21
/*
22
   With acknowledgements to i2c-algo-ibm_ocp.c by
23
   Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
24
 
25
   And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
26
 
27
     Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
28
 
29
   And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
30
   Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
31
 
32
  ---------------------------------------------------------------------------*/
33
 
34
 
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>
44
 
45
 
46
#include <asm/arch-iop3xx/iop321.h>
47
#include <asm/arch-iop3xx/iop321-irqs.h>
48
#include "i2c-iop3xx.h"
49
 
50
 
51
/* ----- global defines ----------------------------------------------- */
52
#define PASSERT(x) do { if (!(x) ) \
53
                printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
54
        } while (0)
55
 
56
 
57
/* ----- global variables --------------------------------------------- */
58
 
59
 
60
static inline unsigned char iic_cook_addr(struct i2c_msg *msg)
61
{
62
        unsigned char addr;
63
 
64
        addr = (msg->addr << 1);
65
 
66
        if (msg->flags & I2C_M_RD)
67
                addr |= 1;
68
 
69
        /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
70
        if (msg->flags & I2C_M_REV_DIR_ADDR)
71
                addr ^= 1;
72
 
73
        return addr;  
74
}
75
 
76
 
77
static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
78
{
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;
83
}
84
 
85
static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
86
{
87
        *iop3xx_adap->biu->SAR = MYSAR;
88
}
89
 
90
static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
91
{
92
        u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
93
 
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;
98
 
99
        cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
100
                IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
101
 
102
        *iop3xx_adap->biu->CR = cr;
103
}
104
 
105
static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
106
{
107
        unsigned cr = *iop3xx_adap->biu->CR;
108
 
109
        cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
110
                IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
111
        *iop3xx_adap->biu->CR = cr;
112
}
113
 
114
static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
115
{
116
        unsigned cr = *iop3xx_adap->biu->CR;
117
 
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;
122
}
123
 
124
/*
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
127
 */
128
static void iop3xx_i2c_handler(int this_irq,
129
                                void *dev_id,
130
                                struct pt_regs *regs)
131
{
132
        struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
133
 
134
        u32 sr = *iop3xx_adap->biu->SR;
135
 
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);
140
        }
141
}
142
 
143
/* check all error conditions, clear them , report most important */
144
static int iop3xx_adap_error(u32 sr)
145
{
146
        int rc = 0;
147
 
148
        if ((sr&IOP321_ISR_BERRD)) {
149
                if ( !rc ) rc = -I2C_ERR_BERR;
150
        }
151
        if ((sr&IOP321_ISR_ALD)) {
152
                if ( !rc ) rc = -I2C_ERR_ALD;          
153
        }
154
        return rc;     
155
}
156
 
157
static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
158
{
159
        unsigned long flags;
160
        u32 sr;
161
 
162
        spin_lock_irqsave(&iop3xx_adap->lock, flags);
163
        sr = iop3xx_adap->biu->SR_received;
164
        iop3xx_adap->biu->SR_received = 0;
165
        spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
166
 
167
        return sr;
168
}
169
 
170
/*
171
 * sleep until interrupted, then recover and analyse the SR
172
 * saved by handler
173
 */
174
typedef int (* compare_func)(unsigned test, unsigned mask);
175
/* returns 1 on correct comparison */
176
 
177
static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
178
                                  unsigned flags, unsigned* status,
179
                                  compare_func compare)
180
{
181
        unsigned sr = 0;
182
        int interrupted;
183
        int done;
184
        int rc;
185
 
186
        do {
187
                interrupted = wait_event_interruptible_timeout (
188
                        iop3xx_adap->waitq,
189
                        (done = compare( sr = get_srstat(iop3xx_adap),flags )),
190
                        iop3xx_adap->timeout
191
                        );
192
                if ((rc = iop3xx_adap_error(sr)) < 0) {
193
                        *status = sr;
194
                        return rc;
195
                }else if (!interrupted) {
196
                        *status = sr;
197
                        return rc = -ETIMEDOUT;
198
                }
199
        } while(!done);
200
 
201
        *status = sr;
202
 
203
        return rc = 0;
204
}
205
 
206
/*
207
 * Concrete compare_funcs
208
 */
209
static int all_bits_clear(unsigned test, unsigned mask)
210
{
211
        return (test & mask) == 0;
212
}
213
static int any_bits_set(unsigned test, unsigned mask)
214
{
215
        return (test & mask) != 0;
216
}
217
 
218
static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
219
{
220
        return iop3xx_adap_wait_event(
221
                iop3xx_adap,
222
                IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
223
                status, any_bits_set);
224
}
225
 
226
static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
227
{
228
        return iop3xx_adap_wait_event(
229
                iop3xx_adap,
230
                IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
231
                status, any_bits_set);
232
}
233
 
234
static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
235
{
236
        return iop3xx_adap_wait_event(
237
                iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
238
}
239
 
240
/*
241
 * Description: This performs the IOP3xx initialization sequence
242
 * Valid for IOP321. Maybe valid for IOP310?.
243
 */
244
static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap)
245
{
246
        *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ?
247
                          IOP321_GPOD_I2C0:
248
                          IOP321_GPOD_I2C1);
249
 
250
        iop3xx_adap_reset(iop3xx_adap);
251
        iop3xx_adap_set_slave_addr(iop3xx_adap);
252
        iop3xx_adap_enable(iop3xx_adap);
253
 
254
        return 0;
255
}
256
 
257
static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
258
                                              struct i2c_msg* msg)
259
{
260
        unsigned cr = *iop3xx_adap->biu->CR;
261
        int status;
262
        int rc;
263
 
264
        *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
265
 
266
        cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
267
        cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
268
 
269
        *iop3xx_adap->biu->CR = cr;
270
        rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
271
        /* this assert fires every time, contrary to IOP manual
272
        PASSERT((status&IOP321_ISR_UNITBUSY)!=0);
273
        */
274
        PASSERT((status&IOP321_ISR_RXREAD)==0);
275
 
276
        return rc;
277
}
278
 
279
static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
280
{
281
        unsigned cr = *iop3xx_adap->biu->CR;
282
        int status;
283
        int rc;
284
 
285
        *iop3xx_adap->biu->DBR = byte;
286
        cr &= ~IOP321_ICR_MSTART;
287
        if (stop) {
288
                cr |= IOP321_ICR_MSTOP;
289
        } else {
290
                cr &= ~IOP321_ICR_MSTOP;
291
        }
292
        *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
293
        rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
294
 
295
        return rc;
296
}
297
 
298
static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
299
                                 char* byte, int stop)
300
{
301
        unsigned cr = *iop3xx_adap->biu->CR;
302
        int status;
303
        int rc;
304
 
305
        cr &= ~IOP321_ICR_MSTART;
306
 
307
        if (stop) {
308
                cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
309
        } else {
310
                cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
311
        }
312
        *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
313
 
314
        rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
315
 
316
        *byte = *iop3xx_adap->biu->DBR;
317
 
318
        return rc;
319
}
320
 
321
static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap,
322
                                 const char *buf, int count)
323
{
324
        struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
325
        int ii;
326
        int rc = 0;
327
 
328
        for (ii = 0; rc == 0 && ii != count; ++ii) {
329
                rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);
330
        }
331
        return rc;
332
}
333
 
334
static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap,
335
                                char *buf, int count)
336
{
337
        struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
338
        int ii;
339
        int rc = 0;
340
 
341
        for (ii = 0; rc == 0 && ii != count; ++ii) {
342
                rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
343
        }
344
        return rc;
345
}
346
 
347
/*
348
 * Description:  This function implements combined transactions.  Combined
349
 * transactions consist of combinations of reading and writing blocks of data.
350
 * FROM THE SAME ADDRESS
351
 * Each transfer (i.e. a read or a write) is separated by a repeated start
352
 * condition.
353
 */
354
static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
355
{
356
        struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
357
        int rc;
358
 
359
        rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
360
        if (rc < 0) {
361
                return rc;
362
        }
363
 
364
        if ((pmsg->flags&I2C_M_RD)) {
365
                return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
366
        } else {
367
                return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
368
        }
369
}
370
 
371
/*
372
 * master_xfer() - main read/write entry
373
 */
374
static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
375
{
376
        struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
377
        int im = 0;
378
        int ret = 0;
379
        int status;
380
 
381
        iop3xx_adap_wait_idle(iop3xx_adap, &status);
382
        iop3xx_adap_reset(iop3xx_adap);
383
        iop3xx_adap_enable(iop3xx_adap);
384
 
385
        for (im = 0; ret == 0 && im != num; ++im) {
386
                ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
387
        }
388
 
389
        iop3xx_adap_transaction_cleanup(iop3xx_adap);
390
 
391
        return ret;  
392
}
393
 
394
static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
395
                        unsigned long arg)
396
{
397
        return 0;
398
}
399
 
400
static u32 iic_func(struct i2c_adapter *adap)
401
{
402
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
403
}
404
 
405
 
406
/* -----exported algorithm data: -------------------------------------  */
407
 
408
static struct i2c_algorithm iic_algo = {
409
        .name           = "IOP3xx I2C algorithm",
410
        .id             = I2C_ALGO_OCP_IOP3XX,
411
        .master_xfer    = iop3xx_master_xfer,
412
        .algo_control   = algo_control,
413
        .functionality  = iic_func,
414
};
415
 
416
/*
417
 * registering functions to load algorithms at runtime
418
 */
419
static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
420
{
421
        struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
422
 
423
        if (!request_region( REGION_START(iop3xx_adap),
424
                              REGION_LENGTH(iop3xx_adap),
425
                              iic_adap->name)) {
426
                return -ENODEV;
427
        }
428
 
429
        init_waitqueue_head(&iop3xx_adap->waitq);
430
        spin_lock_init(&iop3xx_adap->lock);
431
 
432
        if (request_irq(
433
                     iop3xx_adap->biu->irq,
434
                     iop3xx_i2c_handler,
435
                     /* SA_SAMPLE_RANDOM */ 0,
436
                     iic_adap->name,
437
                     iop3xx_adap)) {
438
                return -ENODEV;
439
        }                        
440
 
441
        /* register new iic_adapter to i2c module... */
442
        iic_adap->id |= iic_algo.id;
443
        iic_adap->algo = &iic_algo;
444
 
445
        iic_adap->timeout = 100;        /* default values, should */
446
        iic_adap->retries = 3;          /* be replaced by defines */
447
 
448
        iop3xx_adap_init(iic_adap->algo_data);
449
        i2c_add_adapter(iic_adap);
450
        return 0;
451
}
452
 
453
static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
454
{
455
        struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
456
 
457
        iop3xx_adap_final_cleanup(iop3xx_adap);
458
        free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
459
 
460
        release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
461
 
462
        return i2c_del_adapter(iic_adap);
463
}
464
 
465
#ifdef CONFIG_ARCH_IOP321
466
 
467
static struct iop3xx_biu biu0 = {
468
        .CR     = IOP321_ICR0,
469
        .SR     = IOP321_ISR0,
470
        .SAR    = IOP321_ISAR0,
471
        .DBR    = IOP321_IDBR0,
472
        .BMR    = IOP321_IBMR0,
473
        .irq    = IRQ_IOP321_I2C_0,
474
};
475
 
476
static struct iop3xx_biu biu1 = {
477
        .CR     = IOP321_ICR1,
478
        .SR     = IOP321_ISR1,
479
        .SAR    = IOP321_ISAR1,
480
        .DBR    = IOP321_IDBR1,
481
        .BMR    = IOP321_IBMR1,
482
        .irq    = IRQ_IOP321_I2C_1,
483
};
484
 
485
#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
486
#else
487
#error Please define the BIU struct iop3xx_biu for your processor arch
488
#endif
489
 
490
static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
491
        .channel                = 0,
492
        .biu                    = &biu0,
493
        .timeout                = 1*HZ,
494
};
495
static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
496
        .channel                = 1,
497
        .biu                    = &biu1,
498
        .timeout                = 1*HZ,
499
};
500
 
501
static struct i2c_adapter iop3xx_ops0 = {
502
        .owner                  = THIS_MODULE,
503
        .name                   = ADAPTER_NAME_ROOT "0",
504
        .id                     = I2C_HW_IOP321,
505
        .algo_data              = &algo_iop3xx_data0,
506
};
507
static struct i2c_adapter iop3xx_ops1 = {
508
        .owner                  = THIS_MODULE,
509
        .name                   = ADAPTER_NAME_ROOT "1",
510
        .id                     = I2C_HW_IOP321,
511
        .algo_data              = &algo_iop3xx_data1,
512
};
513
 
514
static int __init i2c_iop3xx_init (void)
515
{
516
        return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
517
                i2c_iop3xx_add_bus(&iop3xx_ops1);
518
}
519
 
520
static void __exit i2c_iop3xx_exit (void)
521
{
522
        i2c_iop3xx_del_bus(&iop3xx_ops0);
523
        i2c_iop3xx_del_bus(&iop3xx_ops1);
524
}
525
 
526
module_init (i2c_iop3xx_init);
527
module_exit (i2c_iop3xx_exit);
528
 
529
MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
530
MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
531
MODULE_LICENSE("GPL");
532
 
533
MODULE_PARM(i2c_debug,"i");
534
 
535
MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
536