blob: b84fbe4438ae949383d145e8800e4d135799a7d9 [file] [log] [blame]
Rob Purchase47ea0302008-01-14 22:04:48 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Rob Purchase
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Rob Purchase47ea0302008-01-14 22:04:48 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22
23#include "system.h"
24#include "i2c.h"
25#include "i2c-target.h"
26
27/* arbitrary delay loop */
Rob Purchaseddfd7872008-04-12 16:18:28 +000028#define DELAY do { int _x; for(_x=0;_x<40;_x++);} while (0)
Rob Purchase47ea0302008-01-14 22:04:48 +000029
30static struct mutex i2c_mtx;
31
32void i2c_init(void)
33{
34 /* nothing to do */
35}
36
37void i2c_start(void)
38{
39 SDA_OUTPUT;
40
41 SCL_HI;
42 SDA_HI;
43 DELAY;
44
45 SDA_LO;
46 DELAY;
47 SCL_LO;
48 DELAY;
49}
50
51void i2c_stop(void)
52{
53 SDA_OUTPUT;
54
55 SDA_LO;
56 DELAY;
57
58 SCL_HI;
59 DELAY;
60 SDA_HI;
61 DELAY;
62}
63
64void i2c_outb(unsigned char byte)
65{
66 int bit;
67
68 SDA_OUTPUT;
69
70 for (bit = 0; bit < 8; bit++)
71 {
72 if ((byte<<bit) & 0x80)
73 SDA_HI;
74 else
75 SDA_LO;
76
77 DELAY;
78
79 SCL_HI;
80 DELAY;
81 SCL_LO;
82 DELAY;
83 }
84}
85
86unsigned char i2c_inb(int ack)
87{
88 int i;
89 unsigned char byte = 0;
90
91 SDA_INPUT;
92
93 /* clock in each bit, MSB first */
94 for ( i=0x80; i; i>>=1 )
95 {
96 SCL_HI;
97 DELAY;
98
99 if ( SDA ) byte |= i;
100
101 SCL_LO;
102 DELAY;
103 }
104
105 i2c_ack(ack);
106 return byte;
107}
108
109void i2c_ack(int bit)
110{
111 SDA_OUTPUT;
112
113 if (bit)
114 SDA_HI;
115 else
116 SDA_LO;
117
118 SCL_HI;
119 DELAY;
120 SCL_LO;
121 DELAY;
122}
123
124int i2c_getack(void)
125{
126 bool ack_bit;
127
128 SDA_INPUT;
129
130 SCL_HI;
131 DELAY;
132
133 ack_bit = SDA;
134 DELAY;
135
136 SCL_LO;
137 DELAY;
138
139 return ack_bit;
140}
141
142/* device = 8 bit slave address */
Bertrik Sikkene5319e02008-04-28 14:33:03 +0000143int i2c_write(int device, const unsigned char* buf, int count )
Rob Purchase47ea0302008-01-14 22:04:48 +0000144{
145 int i = 0;
146 mutex_lock(&i2c_mtx);
147
148 i2c_start();
149 i2c_outb(device & 0xfe);
150
151 while (!i2c_getack() && i < count)
152 {
153 i2c_outb(buf[i++]);
154 }
155
156 i2c_stop();
157 mutex_unlock(&i2c_mtx);
158 return 0;
159}
160
161
162/* device = 8 bit slave address */
163int i2c_readmem(int device, int address, unsigned char* buf, int count )
164{
165 int i = 0;
166 mutex_lock(&i2c_mtx);
167
168 i2c_start();
169 i2c_outb(device & 0xfe);
170 if (i2c_getack()) goto exit;
171
172 i2c_outb(address);
173 if (i2c_getack()) goto exit;
174
175 i2c_start();
176 i2c_outb(device | 1);
177 if (i2c_getack()) goto exit;
178
179 while (i < count)
180 {
181 buf[i] = i2c_inb(i == (count-1));
182 i++;
183 }
184
185exit:
186 i2c_stop();
187 mutex_unlock(&i2c_mtx);
188 return 0;
189}