source: umon/ports/csb740/cpu_i2c.c @ 273af8f

Last change on this file since 273af8f was b987a75, checked in by Jarielle Catbagan <jcatbagan93@…>, on 06/19/15 at 21:32:43

Removed execution mode file attribute from all ASCII text files

  • Property mode set to 100644
File size: 6.7 KB
Line 
1//==========================================================================
2//
3//      cpu_i2c.c
4//
5// Author(s):   Michael Kelly - Cogent Computer Systems, Inc.
6// Date:        03/26/2003
7// Description: Generic IIC Routines - requires I2C_SCL and I2C_SDA to
8//                              be defined in cpu_gpio.h
9//
10//==========================================================================
11
12#include "config.h"
13#include "cpuio.h"
14#include "genlib.h"
15#include "stddefs.h"
16#include "cli.h"
17#include "cpu_gpio.h"
18#include "cpu_gpio.h"
19#include "umongpio.h"
20
21//--------------------------------------------------------------------------
22// function prototypes
23//
24ulong i2c_init(void);
25ulong i2c_wr_device(uchar dev, uchar reg, uchar data);
26ulong i2c_rd_device(uchar dev, uchar reg, uchar *data);
27ulong i2c_wr_byte(uchar data);
28uchar i2c_rd_byte(void);
29void i2c_start(void);
30void i2c_stop(void);
31int i2c(int argc,char *argv[]);
32
33extern void udelay(int delay);
34
35//--------------------------------------------------------------------------
36// I2C Macros
37//
38#define I2C_SCL_CLR             GPIO_out(I2C_SCL)                               
39#define I2C_SCL_SET             GPIO_in(I2C_SCL)                                       
40
41#define I2C_SDA_CLR                             GPIO_out(I2C_SDA)               
42#define I2C_SDA_SET                             GPIO_in(I2C_SDA)               
43
44#define I2C_SCL_RD                              GPIO_tst(I2C_SCL)
45#define I2C_SDA_RD                              GPIO_tst(I2C_SDA)
46
47#define I2C_DELAY                               udelay(1000)
48
49//--------------------------------------------------------------------------
50// i2c_init()
51//
52// I2C is a shared bus.  We drive a low by setting the SCL/SDA GPIO as
53// an output.  We must preset a 0 in the GPIO output bit so the line will
54// go low whenever we make it an output.  For a high, we make the GPIO an
55// input, thus letting the external pullup to pull the line high.
56//
57ulong i2c_init()
58{
59    GPIO_out(I2C_SCL);
60    GPIO_clr(I2C_SCL);
61    GPIO_in(I2C_SCL);
62       
63    GPIO_out(I2C_SDA);
64    GPIO_clr(I2C_SDA);
65    GPIO_in(I2C_SDA);
66       
67    return 0;
68
69}
70
71//--------------------------------------------------------------------------
72// i2c_wr_device()
73//
74// This function writes an 8-bit value to the I2C device at the requested
75// register.
76//
77ulong i2c_wr_device(uchar dev, uchar reg, uchar data)
78{
79
80        // issue a start command
81        i2c_start();
82
83        // write the 7-bit device address with write = 0
84        if(i2c_wr_byte((dev << 1) & 0xfe)){
85                return -1;
86        }
87        // Write the 8-bit register address
88        if(i2c_wr_byte(reg)){
89                return -1;
90        }
91        // Write the 8-bit data value
92        if(i2c_wr_byte(data)){
93                return -1;
94        }
95
96        // issue a stop
97        i2c_stop();
98       
99        return 0;
100}
101
102//--------------------------------------------------------------------------
103// i2c_rd_device()
104//
105// This function reads an 8-bit value from the I2C device at the requested
106// register.
107//
108ulong i2c_rd_device(uchar dev, uchar reg, uchar *data)
109{
110
111        // issue a start command
112        i2c_start();
113
114        // write the 7-bit device address with write = 0
115        if(i2c_wr_byte((dev << 1) & 0xfe)){
116                return -1;
117        }
118        // Write the 8-bit register address
119        if(i2c_wr_byte(reg)){
120                return -1;
121        }
122        // repeat the start command
123        i2c_start();
124        // write the 7-bit device address again plus data direction (read = 1)
125        if(i2c_wr_byte((dev << 1) | 0x01)){
126                return -1;
127        }
128        *data = i2c_rd_byte();
129
130        // issue a stop
131        i2c_stop();
132
133        return 0;
134}
135
136//--------------------------------------------------------------------------
137// i2c_wr_byte()
138//
139// This function writes an 8-bit value to the I2C bus, MSB first.
140// Data is written by changing SDA during SCL low, then bringing
141// SCL high.  SCL is returned low to setup for the next transition.
142//
143ulong i2c_wr_byte(uchar data)
144{
145
146        int i;
147
148        for (i = 0; i < 8; i++){
149                if (data & 0x80) {
150                        // write a 1 bit
151                        I2C_SDA_SET;
152                        I2C_DELAY;
153                        I2C_SCL_SET;
154                        I2C_DELAY;
155                        I2C_SCL_CLR;
156                        I2C_DELAY;
157                }
158                else {
159                        // write a 0 bit
160                        I2C_SDA_CLR;
161                        I2C_DELAY;
162                        I2C_SCL_SET;
163                        I2C_DELAY;
164                        I2C_SCL_CLR;
165                        I2C_DELAY;
166                }
167                data = data << 1;
168        }
169        // Release SDA, bring SCL high, then read SDA.
170        // A low indicates an acknowledge.
171        I2C_SDA_SET;
172        I2C_DELAY;
173        I2C_SCL_SET;
174        I2C_DELAY;
175        if(I2C_SDA_RD){ // a high means no ack
176                // re-enable SDA for output
177                I2C_SCL_CLR;
178                I2C_DELAY;
179                return -1;
180        }
181
182        I2C_SCL_CLR;
183        I2C_DELAY;
184
185        return 0;
186}
187
188//--------------------------------------------------------------------------
189// i2c_rd_byte()
190//
191// This function reads an 8-bit data value from the I2C bus, MSB first.
192// Data is read from SDA after each low to high SCL transition.
193//
194uchar i2c_rd_byte()
195{
196
197        int i;
198        uchar volatile data;
199
200        data = 0;
201
202        for (i = 0; i < 8; i++){
203                data = data << 1;
204                data = data & 0xfe;
205                // clock the data out of the slave
206                I2C_SCL_SET;
207                I2C_DELAY;
208                // check it
209                if (I2C_SDA_RD){
210                        data = data | 0x01;
211                }
212                I2C_SCL_CLR;
213                I2C_DELAY;
214        }
215        // generate an extra SCL transition
216        // The slave generates no acknowledge for reads.
217        I2C_SCL_SET;
218        I2C_DELAY;
219        I2C_SCL_CLR;
220        I2C_DELAY;
221
222        return data;
223}
224
225
226//--------------------------------------------------------------------------
227// i2c_start()
228//
229// This function issues an I2C start command which is a high to low
230// transition on SDA while SCL is high.
231//
232void i2c_start()
233{
234
235        I2C_SDA_SET;
236        I2C_DELAY;
237        I2C_SCL_SET;
238        I2C_DELAY;
239        I2C_SDA_CLR;
240        I2C_DELAY;
241        I2C_SCL_CLR;
242        I2C_DELAY;
243        I2C_SDA_SET;
244        I2C_DELAY;
245}
246
247//--------------------------------------------------------------------------
248// i2c_stop()
249//
250// This function issues an I2C stop command which is a low to high
251// transition on SDA while SCL is high.
252//
253void i2c_stop()
254{
255
256        I2C_SDA_CLR;
257        I2C_DELAY;
258        I2C_SCL_SET;
259        I2C_DELAY;
260        I2C_SDA_SET;
261        I2C_DELAY;
262        I2C_SCL_CLR;
263        I2C_DELAY;
264}
265
266char *i2cHelp[] = {
267        " This command allows the user to read ",
268        " and write devices on the i2c bus. \n ",
269    " Usage:",
270    " i2c -[w] {device} {register} {val/count}",
271    " Options...",
272    " -w write val to device/register",
273        " no options, read from device/register up to count",
274        0
275};
276
277int i2c(int argc,char *argv[])
278{
279        int i, opt;
280        int write = 0;
281        uchar dev, reg, data, count;
282
283    while ((opt=getopt(argc,argv,"w")) != -1) {
284    if (opt == 'w') write = 1;
285        }
286
287        // make sure we have the right number of paramters
288        if (argc < (optind+3))
289                return(CMD_PARAM_ERROR);
290
291        dev = (uchar) strtoul(argv[optind],(char **)0,0);
292        reg = (uchar) strtoul(argv[optind+1],(char **)0,0);
293
294        // 3rd arg is the data value if it's a write, count if it's a read
295        data = (uchar) strtoul(argv[optind+2],(char **)0,0);
296        count = data;
297        // do it
298        if (write)
299        {
300                printf("Writing 0x%02x to Device 0x%02x @ Register 0x%02x.\n", data, dev, reg);
301        if(i2c_wr_device(dev, reg, data))
302        {
303                        printf("I2C Bus Failure - Check Paramters!\n");
304                return (CMD_FAILURE);
305                }
306        }
307        else
308        {
309                for (i = 0; i < count; i++)
310        {
311                        printf("Read Device 0x%02x, Register 0x%02x = ", dev, reg + i);
312                        if(i2c_rd_device(dev, reg + i, &data))
313                        {
314                                printf("I2C Bus Failure - Check Paramters!\n");
315                        return (CMD_FAILURE);
316                        }
317                        printf("0x%02x.\n", data);
318                }
319        }
320        return(CMD_SUCCESS);
321}
322
Note: See TracBrowser for help on using the repository browser.