summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/generic_i2c.c55
-rw-r--r--firmware/export/generic_i2c.h17
-rw-r--r--firmware/target/arm/as3525/fmradio-i2c-as3525.c24
-rw-r--r--firmware/target/mips/ingenic_jz47xx/i2c-jz4740.c1
4 files changed, 39 insertions, 58 deletions
diff --git a/firmware/drivers/generic_i2c.c b/firmware/drivers/generic_i2c.c
index dcbe46f654..206ded96fb 100644
--- a/firmware/drivers/generic_i2c.c
+++ b/firmware/drivers/generic_i2c.c
@@ -28,9 +28,9 @@
28#define MAX_I2C_INTERFACES 5 28#define MAX_I2C_INTERFACES 5
29 29
30static int i2c_num_ifs = 0; 30static int i2c_num_ifs = 0;
31static struct i2c_interface *i2c_if[MAX_I2C_INTERFACES]; 31static const struct i2c_interface *i2c_if[MAX_I2C_INTERFACES];
32 32
33static void i2c_start(struct i2c_interface *iface) 33static void i2c_start(const struct i2c_interface *iface)
34{ 34{
35 iface->sda_output(); 35 iface->sda_output();
36 36
@@ -41,7 +41,7 @@ static void i2c_start(struct i2c_interface *iface)
41 iface->scl_lo(); 41 iface->scl_lo();
42} 42}
43 43
44static void i2c_stop(struct i2c_interface *iface) 44static void i2c_stop(const struct i2c_interface *iface)
45{ 45{
46 iface->sda_output(); 46 iface->sda_output();
47 47
@@ -51,7 +51,7 @@ static void i2c_stop(struct i2c_interface *iface)
51 iface->sda_hi(); 51 iface->sda_hi();
52} 52}
53 53
54static void i2c_ack(struct i2c_interface *iface, bool ack) 54static void i2c_ack(const struct i2c_interface *iface, bool ack)
55{ 55{
56 iface->sda_output(); 56 iface->sda_output();
57 iface->scl_lo(); 57 iface->scl_lo();
@@ -66,7 +66,7 @@ static void i2c_ack(struct i2c_interface *iface, bool ack)
66 iface->scl_lo(); 66 iface->scl_lo();
67} 67}
68 68
69static int i2c_getack(struct i2c_interface *iface) 69static int i2c_getack(const struct i2c_interface *iface)
70{ 70{
71 int ret = 1; 71 int ret = 1;
72 72
@@ -85,7 +85,7 @@ static int i2c_getack(struct i2c_interface *iface)
85 return ret; 85 return ret;
86} 86}
87 87
88static unsigned char i2c_inb(struct i2c_interface *iface, bool ack) 88static unsigned char i2c_inb(const struct i2c_interface *iface, bool ack)
89{ 89{
90 int i; 90 int i;
91 unsigned char byte = 0; 91 unsigned char byte = 0;
@@ -107,7 +107,7 @@ static unsigned char i2c_inb(struct i2c_interface *iface, bool ack)
107 return byte; 107 return byte;
108} 108}
109 109
110static int i2c_outb(struct i2c_interface *iface, unsigned char byte) 110static int i2c_outb(const struct i2c_interface *iface, unsigned char byte)
111{ 111{
112 int i; 112 int i;
113 113
@@ -127,32 +127,19 @@ static int i2c_outb(struct i2c_interface *iface, unsigned char byte)
127 } 127 }
128 128
129 iface->sda_hi(); 129 iface->sda_hi();
130
131 return i2c_getack(iface);
132}
133
134static struct i2c_interface *find_if(int address)
135{
136 int i;
137 130
138 for(i = 0;i < i2c_num_ifs;i++) { 131 return i2c_getack(iface);
139 if(i2c_if[i]->address == address)
140 return i2c_if[i];
141 }
142 return NULL;
143} 132}
144 133
145int i2c_write_data(int bus_address, int address, 134int i2c_write_data(int bus_index, int bus_address, int address,
146 const unsigned char* buf, int count) 135 const unsigned char* buf, int count)
147{ 136{
148 int i; 137 int i;
149 int ret = 0; 138 int ret = 0;
150 struct i2c_interface *iface = find_if(bus_address); 139 const struct i2c_interface *iface = i2c_if[bus_index];;
151 if(!iface)
152 return -1;
153 140
154 i2c_start(iface); 141 i2c_start(iface);
155 if (!i2c_outb(iface, iface->address & 0xfe)) 142 if (!i2c_outb(iface, bus_address & 0xfe))
156 { 143 {
157 ret = -2; 144 ret = -2;
158 goto end; 145 goto end;
@@ -181,19 +168,17 @@ end:
181 return ret; 168 return ret;
182} 169}
183 170
184int i2c_read_data(int bus_address, int address, 171int i2c_read_data(int bus_index, int bus_address, int address,
185 unsigned char* buf, int count) 172 unsigned char* buf, int count)
186{ 173{
187 int i; 174 int i;
188 int ret = 0; 175 int ret = 0;
189 struct i2c_interface *iface = find_if(bus_address); 176 const struct i2c_interface *iface = i2c_if[bus_index];;
190 if(!iface)
191 return -1;
192 177
193 if (address != -1) 178 if (address != -1)
194 { 179 {
195 i2c_start(iface); 180 i2c_start(iface);
196 if (!i2c_outb(iface, iface->address & 0xfe)) 181 if (!i2c_outb(iface, bus_address & 0xfe))
197 { 182 {
198 ret = -2; 183 ret = -2;
199 goto end; 184 goto end;
@@ -206,7 +191,7 @@ int i2c_read_data(int bus_address, int address,
206 } 191 }
207 192
208 i2c_start(iface); 193 i2c_start(iface);
209 if (!i2c_outb(iface, iface->address | 1)) 194 if (!i2c_outb(iface, bus_address | 1))
210 { 195 {
211 ret = -4; 196 ret = -4;
212 goto end; 197 goto end;
@@ -222,14 +207,18 @@ end:
222 return ret; 207 return ret;
223} 208}
224 209
225int i2c_add_node(struct i2c_interface *iface) 210/* returns bus index which can be used as a handle, or <0 on error */
211int i2c_add_node(const struct i2c_interface *iface)
226{ 212{
213 int bus_index;
214
227 if (i2c_num_ifs == MAX_I2C_INTERFACES) 215 if (i2c_num_ifs == MAX_I2C_INTERFACES)
228 return -1; 216 return -1;
229 217
230 i2c_if[i2c_num_ifs++] = iface; 218 bus_index = i2c_num_ifs++;
219 i2c_if[bus_index] = iface;
231 220
232 iface->scl_output(); 221 iface->scl_output();
233 222
234 return 0; 223 return bus_index;
235} 224}
diff --git a/firmware/export/generic_i2c.h b/firmware/export/generic_i2c.h
index f38728589d..6679b78415 100644
--- a/firmware/export/generic_i2c.h
+++ b/firmware/export/generic_i2c.h
@@ -23,9 +23,6 @@
23 23
24struct i2c_interface 24struct i2c_interface
25{ 25{
26 unsigned char address; /* Address of the chip that this interface
27 describes */
28
29 void (*scl_hi)(void); /* Drive SCL high, might sleep on clk stretch */ 26 void (*scl_hi)(void); /* Drive SCL high, might sleep on clk stretch */
30 void (*scl_lo)(void); /* Drive SCL low */ 27 void (*scl_lo)(void); /* Drive SCL low */
31 void (*sda_hi)(void); /* Drive SDA high */ 28 void (*sda_hi)(void); /* Drive SDA high */
@@ -47,9 +44,11 @@ struct i2c_interface
47 void (*delay_thigh)(void); /* SCL high period (tHIGH) 4.0us/0.6us */ 44 void (*delay_thigh)(void); /* SCL high period (tHIGH) 4.0us/0.6us */
48}; 45};
49 46
50extern int i2c_add_node(struct i2c_interface *iface); 47int i2c_add_node(const struct i2c_interface *iface);
51extern int i2c_write_data(int bus_address, int address, 48int i2c_write_data(int bus_index, int bus_address, int address,
52 const unsigned char* buf, int count); 49 const unsigned char* buf, int count);
53extern int i2c_read_data(int bus_address, int address, 50int i2c_read_data(int bus_index, int bus_address, int address,
54 unsigned char* buf, int count); 51 unsigned char* buf, int count);
55#endif 52
53#endif /* _GEN_I2C_ */
54
diff --git a/firmware/target/arm/as3525/fmradio-i2c-as3525.c b/firmware/target/arm/as3525/fmradio-i2c-as3525.c
index 72775eda75..528e8c79a3 100644
--- a/firmware/target/arm/as3525/fmradio-i2c-as3525.c
+++ b/firmware/target/arm/as3525/fmradio-i2c-as3525.c
@@ -22,7 +22,7 @@
22/* 22/*
23 This is the fmradio_i2c interface, used by the radio driver 23 This is the fmradio_i2c interface, used by the radio driver
24 to communicate with the radio tuner chip. 24 to communicate with the radio tuner chip.
25 25
26 It is implemented using the generic i2c driver, which does "bit-banged" 26 It is implemented using the generic i2c driver, which does "bit-banged"
27 I2C with a couple of GPIO pins. 27 I2C with a couple of GPIO pins.
28 */ 28 */
@@ -53,6 +53,8 @@
53#error no FM I2C GPIOPIN defines 53#error no FM I2C GPIOPIN defines
54#endif 54#endif
55 55
56static int fm_i2c_bus;
57
56static void fm_scl_hi(void) 58static void fm_scl_hi(void)
57{ 59{
58 I2C_GPIO(I2C_SCL_PIN) = 1 << I2C_SCL_PIN; 60 I2C_GPIO(I2C_SCL_PIN) = 1 << I2C_SCL_PIN;
@@ -107,22 +109,14 @@ static int fm_scl(void)
107static void fm_delay(void) 109static void fm_delay(void)
108{ 110{
109 volatile int i; 111 volatile int i;
110 112
111 /* this loop is uncalibrated and could use more sophistication */ 113 /* this loop is uncalibrated and could use more sophistication */
112 for (i = 0; i < 100; i++) { 114 for (i = 0; i < 100; i++) {
113 } 115 }
114} 116}
115 117
116/* interface towards the generic i2c driver */ 118/* interface towards the generic i2c driver */
117static struct i2c_interface fm_i2c_interface = { 119static const struct i2c_interface fm_i2c_interface = {
118#if defined(SANSA_CLIP) || defined(SANSA_FUZE) || defined(SANSA_E200V2)
119 .address = 0x10 << 1,
120#elif defined(SANSA_M200V4)
121 .address = 0xC0,
122#elif
123#error no fm i2c address defined
124#endif
125
126 .scl_hi = fm_scl_hi, 120 .scl_hi = fm_scl_hi,
127 .scl_lo = fm_scl_lo, 121 .scl_lo = fm_scl_lo,
128 .sda_hi = fm_sda_hi, 122 .sda_hi = fm_sda_hi,
@@ -133,7 +127,7 @@ static struct i2c_interface fm_i2c_interface = {
133 .scl_output = fm_scl_output, 127 .scl_output = fm_scl_output,
134 .scl = fm_scl, 128 .scl = fm_scl,
135 .sda = fm_sda, 129 .sda = fm_sda,
136 130
137 .delay_hd_sta = fm_delay, 131 .delay_hd_sta = fm_delay,
138 .delay_hd_dat = fm_delay, 132 .delay_hd_dat = fm_delay,
139 .delay_su_dat = fm_delay, 133 .delay_su_dat = fm_delay,
@@ -145,17 +139,17 @@ static struct i2c_interface fm_i2c_interface = {
145/* initialise i2c for fmradio */ 139/* initialise i2c for fmradio */
146void fmradio_i2c_init(void) 140void fmradio_i2c_init(void)
147{ 141{
148 i2c_add_node(&fm_i2c_interface); 142 fm_i2c_bus = i2c_add_node(&fm_i2c_interface);
149} 143}
150 144
151int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count) 145int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count)
152{ 146{
153 return i2c_write_data(address, -1, buf, count); 147 return i2c_write_data(fm_i2c_bus, address, -1, buf, count);
154} 148}
155 149
156int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) 150int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
157{ 151{
158 return i2c_read_data(address, -1, buf, count); 152 return i2c_read_data(fm_i2c_bus, address, -1, buf, count);
159} 153}
160 154
161 155
diff --git a/firmware/target/mips/ingenic_jz47xx/i2c-jz4740.c b/firmware/target/mips/ingenic_jz47xx/i2c-jz4740.c
index 456542064c..b97448f4bb 100644
--- a/firmware/target/mips/ingenic_jz47xx/i2c-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/i2c-jz4740.c
@@ -46,7 +46,6 @@
46#include "system.h" 46#include "system.h"
47#include "jz4740.h" 47#include "jz4740.h"
48#include "logf.h" 48#include "logf.h"
49#include "generic_i2c.h"
50 49
51 50
52/* I2C protocol */ 51/* I2C protocol */