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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [i2c/] [i2c-algo-sgi.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
3
 *
4
 * This file is subject to the terms and conditions of the GNU General Public
5
 * License version 2 as published by the Free Software Foundation.
6
 *
7
 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
8
 */
9
 
10
#include <linux/kernel.h>
11
#include <linux/module.h>
12
#include <linux/init.h>
13
#include <linux/errno.h>
14
#include <linux/delay.h>
15
 
16
#include <linux/i2c.h>
17
#include <linux/i2c-algo-sgi.h>
18
 
19
 
20
#define SGI_I2C_FORCE_IDLE      (0 << 0)
21
#define SGI_I2C_NOT_IDLE        (1 << 0)
22
#define SGI_I2C_WRITE           (0 << 1)
23
#define SGI_I2C_READ            (1 << 1)
24
#define SGI_I2C_RELEASE_BUS     (0 << 2)
25
#define SGI_I2C_HOLD_BUS        (1 << 2)
26
#define SGI_I2C_XFER_DONE       (0 << 4)
27
#define SGI_I2C_XFER_BUSY       (1 << 4)
28
#define SGI_I2C_ACK             (0 << 5)
29
#define SGI_I2C_NACK            (1 << 5)
30
#define SGI_I2C_BUS_OK          (0 << 7)
31
#define SGI_I2C_BUS_ERR         (1 << 7)
32
 
33
#define get_control()           adap->getctrl(adap->data)
34
#define set_control(val)        adap->setctrl(adap->data, val)
35
#define read_data()             adap->rdata(adap->data)
36
#define write_data(val)         adap->wdata(adap->data, val)
37
 
38
 
39
static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
40
{
41
        int i;
42
 
43
        for (i = 0; i < adap->xfer_timeout; i++) {
44
                if ((get_control() & SGI_I2C_XFER_BUSY) == 0)
45
                        return 0;
46
                udelay(1);
47
        }
48
 
49
        return -ETIMEDOUT;
50
}
51
 
52
static int wait_ack(struct i2c_algo_sgi_data *adap)
53
{
54
        int i;
55
 
56
        if (wait_xfer_done(adap))
57
                return -ETIMEDOUT;
58
        for (i = 0; i < adap->ack_timeout; i++) {
59
                if ((get_control() & SGI_I2C_NACK) == 0)
60
                        return 0;
61
                udelay(1);
62
        }
63
 
64
        return -ETIMEDOUT;
65
}
66
 
67
static int force_idle(struct i2c_algo_sgi_data *adap)
68
{
69
        int i;
70
 
71
        set_control(SGI_I2C_FORCE_IDLE);
72
        for (i = 0; i < adap->xfer_timeout; i++) {
73
                if ((get_control() & SGI_I2C_NOT_IDLE) == 0)
74
                        goto out;
75
                udelay(1);
76
        }
77
        return -ETIMEDOUT;
78
out:
79
        if (get_control() & SGI_I2C_BUS_ERR)
80
                return -EIO;
81
        return 0;
82
}
83
 
84
static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
85
                      int rd)
86
{
87
        if (rd)
88
                set_control(SGI_I2C_NOT_IDLE);
89
        /* Check if bus is idle, eventually force it to do so */
90
        if (get_control() & SGI_I2C_NOT_IDLE)
91
                if (force_idle(adap))
92
                        return -EIO;
93
        /* Write out the i2c chip address and specify operation */
94
        set_control(SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
95
        if (rd)
96
                addr |= 1;
97
        write_data(addr);
98
        if (wait_ack(adap))
99
                return -EIO;
100
        return 0;
101
}
102
 
103
static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
104
                    unsigned int len)
105
{
106
        int i;
107
 
108
        set_control(SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
109
        for (i = 0; i < len; i++) {
110
                if (wait_xfer_done(adap))
111
                        return -EIO;
112
                buf[i] = read_data();
113
        }
114
        set_control(SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
115
 
116
        return 0;
117
 
118
}
119
 
120
static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
121
                     unsigned int len)
122
{
123
        int i;
124
 
125
        /* We are already in write state */
126
        for (i = 0; i < len; i++) {
127
                write_data(buf[i]);
128
                if (wait_ack(adap))
129
                        return -EIO;
130
        }
131
        return 0;
132
}
133
 
134
static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
135
                    int num)
136
{
137
        struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
138
        struct i2c_msg *p;
139
        int i, err = 0;
140
 
141
        for (i = 0; !err && i < num; i++) {
142
                p = &msgs[i];
143
                err = do_address(adap, p->addr, p->flags & I2C_M_RD);
144
                if (err || !p->len)
145
                        continue;
146
                if (p->flags & I2C_M_RD)
147
                        err = i2c_read(adap, p->buf, p->len);
148
                else
149
                        err = i2c_write(adap, p->buf, p->len);
150
        }
151
 
152
        return err;
153
}
154
 
155
static u32 sgi_func(struct i2c_adapter *adap)
156
{
157
        return I2C_FUNC_SMBUS_EMUL;
158
}
159
 
160
static struct i2c_algorithm sgi_algo = {
161
        .name           = "SGI algorithm",
162
        .id             = I2C_ALGO_SGI,
163
        .master_xfer    = sgi_xfer,
164
        .functionality  = sgi_func,
165
};
166
 
167
/*
168
 * registering functions to load algorithms at runtime
169
 */
170
int i2c_sgi_add_bus(struct i2c_adapter *adap)
171
{
172
        adap->id |= sgi_algo.id;
173
        adap->algo = &sgi_algo;
174
 
175
        return i2c_add_adapter(adap);
176
}
177
 
178
 
179
int i2c_sgi_del_bus(struct i2c_adapter *adap)
180
{
181
        return i2c_del_adapter(adap);
182
}
183
 
184
EXPORT_SYMBOL(i2c_sgi_add_bus);
185
EXPORT_SYMBOL(i2c_sgi_del_bus);
186
 
187
MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
188
MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
189
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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