summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/i2c-coldfire.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/i2c-coldfire.c')
-rw-r--r--firmware/target/coldfire/i2c-coldfire.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/firmware/target/coldfire/i2c-coldfire.c b/firmware/target/coldfire/i2c-coldfire.c
index d743d046a7..06c196792f 100644
--- a/firmware/target/coldfire/i2c-coldfire.c
+++ b/firmware/target/coldfire/i2c-coldfire.c
@@ -30,7 +30,7 @@
30static int i2c_start(volatile unsigned char *iface); 30static int i2c_start(volatile unsigned char *iface);
31static int i2c_wait_for_slave(volatile unsigned char *iface); 31static int i2c_wait_for_slave(volatile unsigned char *iface);
32static int i2c_outb(volatile unsigned char *iface, unsigned char byte); 32static int i2c_outb(volatile unsigned char *iface, unsigned char byte);
33inline void i2c_stop(volatile unsigned char *iface); 33static inline void i2c_stop(volatile unsigned char *iface);
34 34
35 35
36/* --- Public functions - implementation --- */ 36/* --- Public functions - implementation --- */
@@ -76,6 +76,12 @@ void i2c_close(void)
76 MBCR2 = 0; 76 MBCR2 = 0;
77} 77}
78 78
79/* End I2C session on the given interface. */
80static inline void i2c_stop(volatile unsigned char *iface)
81{
82 iface[O_MBCR] &= ~MSTA;
83}
84
79/* 85/*
80 * Writes bytes to a I2C device. 86 * Writes bytes to a I2C device.
81 * 87 *
@@ -86,7 +92,7 @@ int i2c_write(volatile unsigned char *iface, unsigned char addr,
86{ 92{
87 int i, rc; 93 int i, rc;
88 94
89 if ( ! count) 95 if (count <= 0)
90 return 0; 96 return 0;
91 97
92 rc = i2c_start(iface); 98 rc = i2c_start(iface);
@@ -118,7 +124,7 @@ int i2c_read(volatile unsigned char *iface, unsigned char addr,
118{ 124{
119 int i, rc; 125 int i, rc;
120 126
121 if ( ! count) 127 if (count <= 0)
122 return 0; 128 return 0;
123 129
124 rc = i2c_start(iface); 130 rc = i2c_start(iface);
@@ -131,23 +137,25 @@ int i2c_read(volatile unsigned char *iface, unsigned char addr,
131 137
132 /* Switch to Rx mode */ 138 /* Switch to Rx mode */
133 iface[O_MBCR] &= ~MTX; 139 iface[O_MBCR] &= ~MTX;
134 iface[O_MBCR] &= ~TXAK; 140
141 /* Turn on ACK generation if reading multiple bytes */
142 if (count > 1)
143 iface[O_MBCR] &= ~TXAK;
135 144
136 /* Dummy read */ 145 /* Dummy read */
137 rc = (int) iface[O_MBDR]; 146 rc = (int) iface[O_MBDR];
138 147
139 for (i = 0; i < count; i++) 148 for (i = count; i > 0; i--)
140 { 149 {
141 rc = i2c_wait_for_slave(iface); 150 rc = i2c_wait_for_slave(iface);
142 if (rc < 0) 151 if (rc < 0)
143 return rc; 152 return rc;
144 153
145 if (i == count-2) 154 if (i == 2)
146 /* Don't ACK the next-to-last byte */ 155 /* Don't ACK the last byte to be read from the slave */
147 iface[O_MBCR] |= TXAK; 156 iface[O_MBCR] |= TXAK;
148 157 else if (i == 1)
149 if (i == count-1) 158 /* Generate STOP before reading last byte received */
150 /* Generate STOP before reading last byte */
151 i2c_stop(iface); 159 i2c_stop(iface);
152 160
153 *buf++ = iface[O_MBDR]; 161 *buf++ = iface[O_MBDR];
@@ -233,9 +241,3 @@ int i2c_outb(volatile unsigned char *iface, unsigned char byte)
233 241
234 return 0; 242 return 0;
235} 243}
236
237/* End I2C session on the given interface. */
238inline void i2c_stop(volatile unsigned char *iface)
239{
240 iface[O_MBCR] &= ~MSTA;
241}