summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2008-12-07 19:25:51 +0000
committerRafaël Carré <rafael.carre@gmail.com>2008-12-07 19:25:51 +0000
commit95d58d30588e13b016b4653b6b14020dcb61ff67 (patch)
treec8aa7fcd1a263c741e3f865deae56d22c4d23a34
parent43f238f6dc32e1e12fff872e0957f4f6c5d6144a (diff)
downloadrockbox-95d58d30588e13b016b4653b6b14020dcb61ff67.tar.gz
rockbox-95d58d30588e13b016b4653b6b14020dcb61ff67.zip
Generic I2C: fix various problems with this (now) unused driver
Explicit if SDA is input or output in static functions Do not use logf() but return codes Check for overflow when adding an interface Indent on 4 spaces Rewrite i2c_read_data() and i2c_write_data() using goto for error cases Make subaddress optional (not sent if == -1) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19360 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/generic_i2c.c149
-rw-r--r--firmware/export/generic_i2c.h2
2 files changed, 93 insertions, 58 deletions
diff --git a/firmware/drivers/generic_i2c.c b/firmware/drivers/generic_i2c.c
index 2e5f202307..0dcc957260 100644
--- a/firmware/drivers/generic_i2c.c
+++ b/firmware/drivers/generic_i2c.c
@@ -23,14 +23,17 @@
23#include <stdbool.h> 23#include <stdbool.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include "debug.h" 25#include "debug.h"
26#include "logf.h"
27#include "generic_i2c.h" 26#include "generic_i2c.h"
28 27
28#define MAX_I2C_INTERFACES 5
29
29int i2c_num_ifs = 0; 30int i2c_num_ifs = 0;
30struct i2c_interface *i2c_if[5]; 31struct i2c_interface *i2c_if[MAX_I2C_INTERFACES];
31 32
32static void i2c_start(struct i2c_interface *iface) 33static void i2c_start(struct i2c_interface *iface)
33{ 34{
35 iface->sda_output();
36
34 iface->sda_hi(); 37 iface->sda_hi();
35 iface->scl_hi(); 38 iface->scl_hi();
36 iface->sda_lo(); 39 iface->sda_lo();
@@ -40,6 +43,8 @@ static void i2c_start(struct i2c_interface *iface)
40 43
41static void i2c_stop(struct i2c_interface *iface) 44static void i2c_stop(struct i2c_interface *iface)
42{ 45{
46 iface->sda_output();
47
43 iface->sda_lo(); 48 iface->sda_lo();
44 iface->scl_hi(); 49 iface->scl_hi();
45 iface->delay_su_sto(); 50 iface->delay_su_sto();
@@ -48,6 +53,7 @@ static void i2c_stop(struct i2c_interface *iface)
48 53
49static void i2c_ack(struct i2c_interface *iface, bool ack) 54static void i2c_ack(struct i2c_interface *iface, bool ack)
50{ 55{
56 iface->sda_output();
51 iface->scl_lo(); 57 iface->scl_lo();
52 if ( ack ) 58 if ( ack )
53 iface->sda_lo(); 59 iface->sda_lo();
@@ -67,10 +73,10 @@ static int i2c_getack(struct i2c_interface *iface)
67 iface->sda_input(); 73 iface->sda_input();
68 iface->delay_su_dat(); 74 iface->delay_su_dat();
69 iface->scl_hi(); 75 iface->scl_hi();
70 76
71 if (iface->sda()) 77 if (iface->sda())
72 ret = 0; /* ack failed */ 78 ret = 0; /* ack failed */
73 79
74 iface->delay_thigh(); 80 iface->delay_thigh();
75 iface->scl_lo(); 81 iface->scl_lo();
76 iface->sda_hi(); 82 iface->sda_hi();
@@ -83,7 +89,9 @@ static unsigned char i2c_inb(struct i2c_interface *iface, bool ack)
83{ 89{
84 int i; 90 int i;
85 unsigned char byte = 0; 91 unsigned char byte = 0;
86 92
93 iface->sda_input();
94
87 /* clock in each bit, MSB first */ 95 /* clock in each bit, MSB first */
88 for ( i=0x80; i; i>>=1 ) { 96 for ( i=0x80; i; i>>=1 ) {
89 iface->sda_input(); 97 iface->sda_input();
@@ -95,27 +103,29 @@ static unsigned char i2c_inb(struct i2c_interface *iface, bool ack)
95 iface->delay_hd_dat(); 103 iface->delay_hd_dat();
96 iface->sda_output(); 104 iface->sda_output();
97 } 105 }
98 106
99 i2c_ack(iface, ack); 107 i2c_ack(iface, ack);
100 108
101 return byte; 109 return byte;
102} 110}
103 111
104static void i2c_outb(struct i2c_interface *iface, unsigned char byte) 112static void i2c_outb(struct i2c_interface *iface, unsigned char byte)
105{ 113{
106 int i; 114 int i;
107 115
108 /* clock out each bit, MSB first */ 116 iface->sda_output();
109 for (i=0x80; i; i>>=1) { 117
110 if (i & byte) 118 /* clock out each bit, MSB first */
111 iface->sda_hi(); 119 for (i=0x80; i; i>>=1) {
112 else 120 if (i & byte)
113 iface->sda_lo(); 121 iface->sda_hi();
114 iface->delay_su_dat(); 122 else
115 iface->scl_hi(); 123 iface->sda_lo();
116 iface->delay_thigh(); 124 iface->delay_su_dat();
117 iface->scl_lo(); 125 iface->scl_hi();
118 iface->delay_hd_dat(); 126 iface->delay_thigh();
127 iface->scl_lo();
128 iface->delay_hd_dat();
119 } 129 }
120 130
121 iface->sda_hi(); 131 iface->sda_hi();
@@ -140,27 +150,36 @@ int i2c_write_data(int bus_address, int address,
140 struct i2c_interface *iface = find_if(bus_address); 150 struct i2c_interface *iface = find_if(bus_address);
141 if(!iface) 151 if(!iface)
142 return -1; 152 return -1;
143 153
144 i2c_start(iface); 154 i2c_start(iface);
145 i2c_outb(iface, iface->address & 0xfe); 155 i2c_outb(iface, iface->address & 0xfe);
146 if (i2c_getack(iface)) { 156 if (!i2c_getack(iface))
157 {
158 ret = -2;
159 goto end;
160 }
161
162 if (address != -1)
163 {
147 i2c_outb(iface, address); 164 i2c_outb(iface, address);
148 if (i2c_getack(iface)) { 165 if (!i2c_getack(iface))
149 for(i = 0;i < count;i++) { 166 {
150 i2c_outb(iface, buf[i]); 167 ret = -3;
151 if (!i2c_getack(iface)) { 168 goto end;
152 ret = -3; 169 }
153 break; 170 }
154 } 171
155 } 172 for(i = 0;i < count;i++)
156 } else { 173 {
157 ret = -2; 174 i2c_outb(iface, buf[i]);
175 if (!i2c_getack(iface))
176 {
177 ret = -4;
178 break;
158 } 179 }
159 } else {
160 logf("i2c_write_data() - no ack\n");
161 ret = -1;
162 } 180 }
163 181
182end:
164 i2c_stop(iface); 183 i2c_stop(iface);
165 return ret; 184 return ret;
166} 185}
@@ -173,34 +192,50 @@ int i2c_read_data(int bus_address, int address,
173 struct i2c_interface *iface = find_if(bus_address); 192 struct i2c_interface *iface = find_if(bus_address);
174 if(!iface) 193 if(!iface)
175 return -1; 194 return -1;
176 195
177 i2c_start(iface); 196 if (address != -1)
178 i2c_outb(iface, iface->address & 0xfe); 197 {
179 if (i2c_getack(iface)) { 198 i2c_start(iface);
180 i2c_outb(iface, address); 199 i2c_outb(iface, iface->address & 0xfe);
181 if (i2c_getack(iface)) { 200 if (!i2c_getack(iface))
182 i2c_start(iface); 201 {
183 i2c_outb(iface, iface->address | 1);
184 if (i2c_getack(iface)) {
185 for(i = 0;i < count-1;i++)
186 buf[i] = i2c_inb(iface, true);
187
188 buf[i] = i2c_inb(iface, false);
189 } else {
190 ret = -3;
191 }
192 } else {
193 ret = -2; 202 ret = -2;
203 goto end;
204 }
205 i2c_outb(iface, address);
206 if (!i2c_getack(iface))
207 {
208 ret = -3;
209 goto end;
194 } 210 }
195 } else {
196 ret = -1;
197 } 211 }
198 212
213 i2c_start(iface);
214 i2c_outb(iface, iface->address | 1);
215 if (!i2c_getack(iface))
216 {
217 ret = -4;
218 goto end;
219 }
220
221 for(i = 0;i < count-1;i++)
222 buf[i] = i2c_inb(iface, true);
223
224 buf[i] = i2c_inb(iface, false);
225
226end:
199 i2c_stop(iface); 227 i2c_stop(iface);
200 return ret; 228 return ret;
201} 229}
202 230
203void i2c_add_node(struct i2c_interface *iface) 231int i2c_add_node(struct i2c_interface *iface)
204{ 232{
233 if (i2c_num_ifs == MAX_I2C_INTERFACES)
234 return -1;
235
205 i2c_if[i2c_num_ifs++] = iface; 236 i2c_if[i2c_num_ifs++] = iface;
237
238 iface->scl_output();
239
240 return 0;
206} 241}
diff --git a/firmware/export/generic_i2c.h b/firmware/export/generic_i2c.h
index 7b598039fa..f38728589d 100644
--- a/firmware/export/generic_i2c.h
+++ b/firmware/export/generic_i2c.h
@@ -47,7 +47,7 @@ struct i2c_interface
47 void (*delay_thigh)(void); /* SCL high period (tHIGH) 4.0us/0.6us */ 47 void (*delay_thigh)(void); /* SCL high period (tHIGH) 4.0us/0.6us */
48}; 48};
49 49
50extern void i2c_add_node(struct i2c_interface *iface); 50extern int i2c_add_node(struct i2c_interface *iface);
51extern int i2c_write_data(int bus_address, int address, 51extern int i2c_write_data(int bus_address, int address,
52 const unsigned char* buf, int count); 52 const unsigned char* buf, int count);
53extern int i2c_read_data(int bus_address, int address, 53extern int i2c_read_data(int bus_address, int address,