diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/coldfire/i2c-coldfire.c | 34 |
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 @@ | |||
30 | static int i2c_start(volatile unsigned char *iface); | 30 | static int i2c_start(volatile unsigned char *iface); |
31 | static int i2c_wait_for_slave(volatile unsigned char *iface); | 31 | static int i2c_wait_for_slave(volatile unsigned char *iface); |
32 | static int i2c_outb(volatile unsigned char *iface, unsigned char byte); | 32 | static int i2c_outb(volatile unsigned char *iface, unsigned char byte); |
33 | inline void i2c_stop(volatile unsigned char *iface); | 33 | static 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. */ | ||
80 | static 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. */ | ||
238 | inline void i2c_stop(volatile unsigned char *iface) | ||
239 | { | ||
240 | iface[O_MBCR] &= ~MSTA; | ||
241 | } | ||