OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [i2c/] [scx200_acb.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*  linux/drivers/i2c/scx200_acb.c
2
 
3
    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
4
 
5
    National Semiconductor SCx200 ACCESS.bus support
6
 
7
    Based on i2c-keywest.c which is:
8
        Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
9
        Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
10
 
11
    This program is free software; you can redistribute it and/or
12
    modify it under the terms of the GNU General Public License as
13
    published by the Free Software Foundation; either version 2 of the
14
    License, or (at your option) any later version.
15
 
16
    This program is distributed in the hope that it will be useful,
17
    but WITHOUT ANY WARRANTY; without even the implied warranty of
18
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
    General Public License for more details.
20
 
21
    You should have received a copy of the GNU General Public License
22
    along with this program; if not, write to the Free Software
23
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
 
25
*/
26
 
27
#include <linux/config.h>
28
#include <linux/module.h>
29
#include <linux/errno.h>
30
#include <linux/kernel.h>
31
#include <linux/sched.h>
32
#include <linux/init.h>
33
#include <linux/i2c.h>
34
#include <linux/smp_lock.h>
35
#include <linux/pci.h>
36
#include <asm/io.h>
37
 
38
#include <linux/scx200.h>
39
 
40
#define NAME "scx200_acb"
41
 
42
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
43
MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
44
MODULE_LICENSE("GPL");
45
 
46
#define MAX_DEVICES 4
47
static int base[MAX_DEVICES] = { 0x840 };
48
MODULE_PARM(base, "1-4i");
49
MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
50
 
51
#define DEBUG 0
52
 
53
#if DEBUG
54
#define DBG(x...) printk(KERN_DEBUG NAME ": " x)
55
#else
56
#define DBG(x...)
57
#endif
58
 
59
/* The hardware supports interrupt driven mode too, but I haven't
60
   implemented that. */
61
#define POLLED_MODE 1
62
#define POLL_TIMEOUT (HZ)
63
 
64
enum scx200_acb_state {
65
        state_idle,
66
        state_address,
67
        state_command,
68
        state_repeat_start,
69
        state_quick,
70
        state_read,
71
        state_write,
72
};
73
 
74
static const char *scx200_acb_state_name[] = {
75
        "idle",
76
        "address",
77
        "command",
78
        "repeat_start",
79
        "quick",
80
        "read",
81
        "write",
82
};
83
 
84
/* Physical interface */
85
struct scx200_acb_iface
86
{
87
        struct scx200_acb_iface *next;
88
        struct i2c_adapter adapter;
89
        unsigned base;
90
        struct semaphore sem;
91
 
92
        /* State machine data */
93
        enum scx200_acb_state state;
94
        int result;
95
        u8 address_byte;
96
        u8 command;
97
        u8 *ptr;
98
        char needs_reset;
99
        unsigned len;
100
};
101
 
102
/* Register Definitions */
103
#define ACBSDA          (iface->base + 0)
104
#define ACBST           (iface->base + 1)
105
#define    ACBST_SDAST          0x40 /* SDA Status */
106
#define    ACBST_BER            0x20 
107
#define    ACBST_NEGACK         0x10 /* Negative Acknowledge */
108
#define    ACBST_STASTR         0x08 /* Stall After Start */
109
#define    ACBST_MASTER         0x02
110
#define ACBCST          (iface->base + 2)
111
#define    ACBCST_BB            0x02
112
#define ACBCTL1         (iface->base + 3)
113
#define    ACBCTL1_STASTRE      0x80
114
#define    ACBCTL1_NMINTE       0x40
115
#define    ACBCTL1_ACK          0x10
116
#define    ACBCTL1_STOP         0x02
117
#define    ACBCTL1_START        0x01
118
#define ACBADDR         (iface->base + 4)
119
#define ACBCTL2         (iface->base + 5)
120
#define    ACBCTL2_ENABLE       0x01
121
 
122
/************************************************************************/
123
 
124
static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
125
{
126
        const char *errmsg;
127
 
128
        DBG("state %s, status = 0x%02x\n",
129
            scx200_acb_state_name[iface->state], status);
130
 
131
        if (status & ACBST_BER) {
132
                errmsg = "bus error";
133
                goto error;
134
        }
135
        if (!(status & ACBST_MASTER)) {
136
                errmsg = "not master";
137
                goto error;
138
        }
139
        if (status & ACBST_NEGACK)
140
                goto negack;
141
 
142
        switch (iface->state) {
143
        case state_idle:
144
                printk(KERN_WARNING NAME ": %s, interrupt in idle state\n",
145
                       iface->adapter.name);
146
                break;
147
 
148
        case state_address:
149
                /* Do a pointer write first */
150
                outb(iface->address_byte & ~1, ACBSDA);
151
 
152
                iface->state = state_command;
153
                break;
154
 
155
        case state_command:
156
                outb(iface->command, ACBSDA);
157
 
158
                if (iface->address_byte & 1)
159
                        iface->state = state_repeat_start;
160
                else
161
                        iface->state = state_write;
162
                break;
163
 
164
        case state_repeat_start:
165
                outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
166
                /* fallthrough */
167
 
168
        case state_quick:
169
                if (iface->address_byte & 1) {
170
                        if (iface->len == 1)
171
                                outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
172
                        else
173
                                outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
174
                        outb(iface->address_byte, ACBSDA);
175
 
176
                        iface->state = state_read;
177
                } else {
178
                        outb(iface->address_byte, ACBSDA);
179
 
180
                        iface->state = state_write;
181
                }
182
                break;
183
 
184
        case state_read:
185
                /* Set ACK if receiving the last byte */
186
                if (iface->len == 1)
187
                        outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
188
                else
189
                        outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
190
 
191
                *iface->ptr++ = inb(ACBSDA);
192
                --iface->len;
193
 
194
                if (iface->len == 0) {
195
                        iface->result = 0;
196
                        iface->state = state_idle;
197
                        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
198
                }
199
 
200
                break;
201
 
202
        case state_write:
203
                if (iface->len == 0) {
204
                        iface->result = 0;
205
                        iface->state = state_idle;
206
                        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
207
                        break;
208
                }
209
 
210
                outb(*iface->ptr++, ACBSDA);
211
                --iface->len;
212
 
213
                break;
214
        }
215
 
216
        return;
217
 
218
 negack:
219
        DBG("negative acknowledge in state %s\n",
220
            scx200_acb_state_name[iface->state]);
221
 
222
        iface->state = state_idle;
223
        iface->result = -ENXIO;
224
 
225
        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
226
        outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
227
        return;
228
 
229
 error:
230
        printk(KERN_ERR NAME ": %s, %s in state %s\n", iface->adapter.name,
231
               errmsg, scx200_acb_state_name[iface->state]);
232
 
233
        iface->state = state_idle;
234
        iface->result = -EIO;
235
        iface->needs_reset = 1;
236
}
237
 
238
static void scx200_acb_timeout(struct scx200_acb_iface *iface)
239
{
240
        printk(KERN_ERR NAME ": %s, timeout in state %s\n",
241
               iface->adapter.name, scx200_acb_state_name[iface->state]);
242
 
243
        iface->state = state_idle;
244
        iface->result = -EIO;
245
        iface->needs_reset = 1;
246
}
247
 
248
#ifdef POLLED_MODE
249
static void scx200_acb_poll(struct scx200_acb_iface *iface)
250
{
251
        u8 status = 0;
252
        unsigned long timeout;
253
 
254
        timeout = jiffies + POLL_TIMEOUT;
255
        while (time_before(jiffies, timeout)) {
256
                status = inb(ACBST);
257
                if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
258
                        scx200_acb_machine(iface, status);
259
                        return;
260
                }
261
                yield();
262
        }
263
 
264
        scx200_acb_timeout(iface);
265
}
266
#endif /* POLLED_MODE */
267
 
268
static void scx200_acb_reset(struct scx200_acb_iface *iface)
269
{
270
        /* Disable the ACCESS.bus device and Configure the SCL
271
           frequency: 16 clock cycles */
272
        outb(0x70, ACBCTL2);
273
        /* Polling mode */
274
        outb(0, ACBCTL1);
275
        /* Disable slave address */
276
        outb(0, ACBADDR);
277
        /* Enable the ACCESS.bus device */
278
        outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2);
279
        /* Free STALL after START */
280
        outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1);
281
        /* Send a STOP */
282
        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
283
        /* Clear BER, NEGACK and STASTR bits */
284
        outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST);
285
        /* Clear BB bit */
286
        outb(inb(ACBCST) | ACBCST_BB, ACBCST);
287
}
288
 
289
static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
290
                                u16 address, unsigned short flags,
291
                                char rw, u8 command, int size,
292
                                union i2c_smbus_data *data)
293
{
294
        struct scx200_acb_iface *iface = adapter->data;
295
        int len;
296
        u8 *buffer;
297
        u16 cur_word;
298
        int rc;
299
 
300
        switch (size) {
301
        case I2C_SMBUS_QUICK:
302
                len = 0;
303
                buffer = NULL;
304
                break;
305
        case I2C_SMBUS_BYTE:
306
                if (rw == I2C_SMBUS_READ) {
307
                        len = 1;
308
                        buffer = &data->byte;
309
                } else {
310
                        len = 1;
311
                        buffer = &command;
312
                }
313
                break;
314
        case I2C_SMBUS_BYTE_DATA:
315
                len = 1;
316
                buffer = &data->byte;
317
                break;
318
        case I2C_SMBUS_WORD_DATA:
319
                len = 2;
320
                cur_word = cpu_to_le16(data->word);
321
                buffer = (u8 *)&cur_word;
322
                break;
323
        case I2C_SMBUS_BLOCK_DATA:
324
                len = data->block[0];
325
                buffer = &data->block[1];
326
                break;
327
        default:
328
                return -EINVAL;
329
        }
330
 
331
        DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
332
            size, address, command, len, rw == I2C_SMBUS_READ);
333
 
334
        if (!len && rw == I2C_SMBUS_READ) {
335
                printk(KERN_WARNING NAME ": %s, zero length read\n",
336
                       adapter->name);
337
                return -EINVAL;
338
        }
339
 
340
        if (len && !buffer) {
341
                printk(KERN_WARNING NAME ": %s, nonzero length but no buffer\n", adapter->name);
342
                return -EFAULT;
343
        }
344
 
345
        down(&iface->sem);
346
 
347
        iface->address_byte = address<<1;
348
        if (rw == I2C_SMBUS_READ)
349
                iface->address_byte |= 1;
350
        iface->command = command;
351
        iface->ptr = buffer;
352
        iface->len = len;
353
        iface->result = -EINVAL;
354
        iface->needs_reset = 0;
355
 
356
        outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
357
 
358
        if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)
359
                iface->state = state_quick;
360
        else
361
                iface->state = state_address;
362
 
363
#ifdef POLLED_MODE
364
        while (iface->state != state_idle)
365
                scx200_acb_poll(iface);
366
#else /* POLLED_MODE */
367
#error Interrupt driven mode not implemented
368
#endif /* POLLED_MODE */        
369
 
370
        if (iface->needs_reset)
371
                scx200_acb_reset(iface);
372
 
373
        rc = iface->result;
374
 
375
        up(&iface->sem);
376
 
377
        if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ)
378
                data->word = le16_to_cpu(cur_word);
379
 
380
#if DEBUG
381
        printk(KERN_DEBUG NAME ": transfer done, result: %d", rc);
382
        if (buffer) {
383
                int i;
384
                printk(" data:");
385
                for (i = 0; i < len; ++i)
386
                        printk(" %02x", buffer[i]);
387
        }
388
        printk("\n");
389
#endif
390
 
391
        return rc;
392
}
393
 
394
static u32 scx200_acb_func(struct i2c_adapter *adapter)
395
{
396
        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
397
               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
398
               I2C_FUNC_SMBUS_BLOCK_DATA;
399
}
400
 
401
static int scx200_acb_reg(struct i2c_client *client)
402
{
403
        return 0;
404
}
405
 
406
static int scx200_acb_unreg(struct i2c_client *client)
407
{
408
        return 0;
409
}
410
 
411
static void scx200_acb_inc_use(struct i2c_adapter *adapter)
412
{
413
        MOD_INC_USE_COUNT;
414
}
415
 
416
static void scx200_acb_dec_use(struct i2c_adapter *adapter)
417
{
418
        MOD_DEC_USE_COUNT;
419
}
420
 
421
/* For now, we only handle combined mode (smbus) */
422
static struct i2c_algorithm scx200_acb_algorithm = {
423
        name:           "NatSemi SCx200 ACCESS.bus",
424
        id:             I2C_ALGO_SMBUS,
425
        smbus_xfer:     scx200_acb_smbus_xfer,
426
        functionality:  scx200_acb_func,
427
};
428
 
429
struct scx200_acb_iface *scx200_acb_list;
430
 
431
int scx200_acb_probe(struct scx200_acb_iface *iface)
432
{
433
        u8 val;
434
 
435
        /* Disable the ACCESS.bus device and Configure the SCL
436
           frequency: 16 clock cycles */
437
        outb(0x70, ACBCTL2);
438
 
439
        if (inb(ACBCTL2) != 0x70) {
440
                DBG("ACBCTL2 readback failed\n");
441
                return -ENXIO;
442
        }
443
 
444
        outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1);
445
 
446
        val = inb(ACBCTL1);
447
        if (val) {
448
                DBG("disabled, but ACBCTL1=0x%02x\n", val);
449
                return -ENXIO;
450
        }
451
 
452
        outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2);
453
 
454
        outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1);
455
 
456
        val = inb(ACBCTL1);
457
        if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
458
                DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val);
459
                return -ENXIO;
460
        }
461
 
462
        return 0;
463
}
464
 
465
static int  __init scx200_acb_create(int base, int index)
466
{
467
        struct scx200_acb_iface *iface;
468
        struct i2c_adapter *adapter;
469
        int rc = 0;
470
        char description[64];
471
 
472
        iface = kmalloc(sizeof(*iface), GFP_KERNEL);
473
        if (!iface) {
474
                printk(KERN_ERR NAME ": can't allocate memory\n");
475
                rc = -ENOMEM;
476
                goto errout;
477
        }
478
 
479
        memset(iface, 0, sizeof(*iface));
480
        adapter = &iface->adapter;
481
        adapter->data = iface;
482
        sprintf(adapter->name, "SCx200 ACB%d", index);
483
        adapter->id = I2C_ALGO_SMBUS;
484
        adapter->algo = &scx200_acb_algorithm;
485
        adapter->inc_use = scx200_acb_inc_use;
486
        adapter->dec_use = scx200_acb_dec_use;
487
        adapter->client_register = scx200_acb_reg;
488
        adapter->client_unregister = scx200_acb_unreg;
489
 
490
        init_MUTEX(&iface->sem);
491
 
492
        sprintf(description, "NatSemi SCx200 ACCESS.bus [%s]", adapter->name);
493
        if (request_region(base, 8, description) == 0) {
494
                printk(KERN_ERR NAME ": %s, can't allocate io 0x%x-0x%x\n",
495
                       adapter->name, base, base + 8-1);
496
                rc = -EBUSY;
497
                goto errout;
498
        }
499
        iface->base = base;
500
 
501
        rc = scx200_acb_probe(iface);
502
        if (rc) {
503
                printk(KERN_WARNING NAME ": %s, probe failed\n", adapter->name);
504
                goto errout;
505
        }
506
 
507
        scx200_acb_reset(iface);
508
 
509
        if (i2c_add_adapter(adapter) < 0) {
510
                printk(KERN_ERR NAME ": %s, failed to register\n", adapter->name);
511
                rc = -ENODEV;
512
                goto errout;
513
        }
514
 
515
        lock_kernel();
516
        iface->next = scx200_acb_list;
517
        scx200_acb_list = iface;
518
        unlock_kernel();
519
 
520
        return 0;
521
 
522
 errout:
523
        if (iface) {
524
                if (iface->base)
525
                        release_region(iface->base, 8);
526
                kfree(iface);
527
        }
528
        return rc;
529
}
530
 
531
static int __init scx200_acb_init(void)
532
{
533
        int i;
534
        int rc;
535
 
536
        printk(KERN_DEBUG NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
537
 
538
        /* Verify that this really is a SCx200 processor */
539
        if (pci_find_device(PCI_VENDOR_ID_NS,
540
                            PCI_DEVICE_ID_NS_SCx200_BRIDGE,
541
                            NULL) == NULL)
542
                return -ENODEV;
543
 
544
        rc = -ENXIO;
545
        for (i = 0; i < MAX_DEVICES; ++i) {
546
                if (base[i] > 0)
547
                        rc = scx200_acb_create(base[i], i);
548
        }
549
        if (scx200_acb_list)
550
                return 0;
551
        return rc;
552
}
553
 
554
static void __exit scx200_acb_cleanup(void)
555
{
556
        struct scx200_acb_iface *iface;
557
        lock_kernel();
558
        while ((iface = scx200_acb_list) != NULL) {
559
                scx200_acb_list = iface->next;
560
                unlock_kernel();
561
 
562
                i2c_del_adapter(&iface->adapter);
563
                release_region(iface->base, 8);
564
                kfree(iface);
565
                lock_kernel();
566
        }
567
        unlock_kernel();
568
}
569
 
570
module_init(scx200_acb_init);
571
module_exit(scx200_acb_cleanup);
572
 
573
/*
574
    Local variables:
575
        compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules"
576
        c-basic-offset: 8
577
    End:
578
*/
579
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.