| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: motoi2c.c,v 1.9 2021/01/24 18:01:13 jmcneill Exp $ */ | | 1 | /* $NetBSD: motoi2c.c,v 1.10 2021/01/25 12:08:47 jmcneill Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2007, 2010 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2007, 2010 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Matt Thomas. | | 8 | * by Matt Thomas. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -20,27 +20,27 @@ | | | @@ -20,27 +20,27 @@ |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: motoi2c.c,v 1.9 2021/01/24 18:01:13 jmcneill Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: motoi2c.c,v 1.10 2021/01/25 12:08:47 jmcneill Exp $"); |
34 | | | 34 | |
35 | #if defined(__arm__) || defined(__aarch64__) | | 35 | #if defined(__arm__) || defined(__aarch64__) |
36 | #include "opt_fdt.h" | | 36 | #include "opt_fdt.h" |
37 | #endif | | 37 | #endif |
38 | | | 38 | |
39 | #include <sys/param.h> | | 39 | #include <sys/param.h> |
40 | #include <sys/device.h> | | 40 | #include <sys/device.h> |
41 | #include <sys/systm.h> | | 41 | #include <sys/systm.h> |
42 | #include <sys/mutex.h> | | 42 | #include <sys/mutex.h> |
43 | #include <sys/bus.h> | | 43 | #include <sys/bus.h> |
44 | #include <sys/intr.h> | | 44 | #include <sys/intr.h> |
45 | | | 45 | |
46 | #include <dev/i2c/i2cvar.h> | | 46 | #include <dev/i2c/i2cvar.h> |
| @@ -99,104 +99,126 @@ motoi2c_attach_common(device_t self, str | | | @@ -99,104 +99,126 @@ motoi2c_attach_common(device_t self, str |
99 | iic_tag_init(&sc->sc_i2c); | | 99 | iic_tag_init(&sc->sc_i2c); |
100 | sc->sc_i2c.ic_cookie = sc; | | 100 | sc->sc_i2c.ic_cookie = sc; |
101 | sc->sc_i2c.ic_acquire_bus = motoi2c_acquire_bus; | | 101 | sc->sc_i2c.ic_acquire_bus = motoi2c_acquire_bus; |
102 | sc->sc_i2c.ic_release_bus = motoi2c_release_bus; | | 102 | sc->sc_i2c.ic_release_bus = motoi2c_release_bus; |
103 | sc->sc_i2c.ic_exec = motoi2c_exec; | | 103 | sc->sc_i2c.ic_exec = motoi2c_exec; |
104 | if (sc->sc_iord == NULL) | | 104 | if (sc->sc_iord == NULL) |
105 | sc->sc_iord = motoi2c_iord1; | | 105 | sc->sc_iord = motoi2c_iord1; |
106 | if (sc->sc_iowr == NULL) | | 106 | if (sc->sc_iowr == NULL) |
107 | sc->sc_iowr = motoi2c_iowr1; | | 107 | sc->sc_iowr = motoi2c_iowr1; |
108 | memset(&iba, 0, sizeof(iba)); | | 108 | memset(&iba, 0, sizeof(iba)); |
109 | iba.iba_tag = &sc->sc_i2c; | | 109 | iba.iba_tag = &sc->sc_i2c; |
110 | iba.iba_child_devices = sc->sc_child_devices; | | 110 | iba.iba_child_devices = sc->sc_child_devices; |
111 | | | 111 | |
112 | I2C_WRITE(I2CCR, 0); /* reset before changing anything */ | | 112 | if ((sc->sc_flags & MOTOI2C_F_ENABLE_INV) != 0) { |
| | | 113 | sc->sc_enable_mask = 0; |
| | | 114 | sc->sc_disable_mask = CR_MEN; |
| | | 115 | } else { |
| | | 116 | sc->sc_enable_mask = CR_MEN; |
| | | 117 | sc->sc_disable_mask = 0; |
| | | 118 | } |
| | | 119 | |
| | | 120 | I2C_WRITE(I2CCR, sc->sc_disable_mask); /* reset before config */ |
113 | I2C_WRITE(I2CDFSRR, i2c->i2c_dfsrr); /* sampling units */ | | 121 | I2C_WRITE(I2CDFSRR, i2c->i2c_dfsrr); /* sampling units */ |
114 | I2C_WRITE(I2CFDR, i2c->i2c_fdr); /* divider 3072 (0x31) */ | | 122 | I2C_WRITE(I2CFDR, i2c->i2c_fdr); /* divider 3072 (0x31) */ |
115 | I2C_WRITE(I2CADR, i2c->i2c_adr); /* our slave address is 0x7f */ | | 123 | I2C_WRITE(I2CADR, i2c->i2c_adr); /* our slave address is 0x7f */ |
116 | I2C_WRITE(I2CSR, 0); /* clear status flags */ | | 124 | if ((sc->sc_flags & MOTOI2C_F_STATUS_W1C) != 0) { |
| | | 125 | I2C_WRITE(I2CSR, I2C_READ(I2CSR)); /* clear status flags */ |
| | | 126 | } else { |
| | | 127 | I2C_WRITE(I2CSR, 0); /* clear status flags */ |
| | | 128 | } |
117 | | | 129 | |
118 | #ifdef FDT | | 130 | #ifdef FDT |
119 | if (sc->sc_phandle != 0) { | | 131 | if (sc->sc_phandle != 0) { |
120 | fdtbus_register_i2c_controller(&sc->sc_i2c, sc->sc_phandle); | | 132 | fdtbus_register_i2c_controller(&sc->sc_i2c, sc->sc_phandle); |
121 | fdtbus_attach_i2cbus(self, sc->sc_phandle, &sc->sc_i2c, | | 133 | fdtbus_attach_i2cbus(self, sc->sc_phandle, &sc->sc_i2c, |
122 | iicbus_print); | | 134 | iicbus_print); |
123 | } else | | 135 | } else |
124 | #endif | | 136 | #endif |
125 | config_found_ia(self, "i2cbus", &iba, iicbus_print); | | 137 | config_found_ia(self, "i2cbus", &iba, iicbus_print); |
126 | } | | 138 | } |
127 | | | 139 | |
128 | static int | | 140 | static int |
129 | motoi2c_acquire_bus(void *v, int flags) | | 141 | motoi2c_acquire_bus(void *v, int flags) |
130 | { | | 142 | { |
131 | struct motoi2c_softc * const sc = v; | | 143 | struct motoi2c_softc * const sc = v; |
132 | | | 144 | |
133 | I2C_WRITE(I2CCR, CR_MEN); /* enable the I2C module */ | | 145 | I2C_WRITE(I2CCR, sc->sc_enable_mask); /* enable the I2C module */ |
134 | | | 146 | |
135 | return 0; | | 147 | return 0; |
136 | } | | 148 | } |
137 | | | 149 | |
138 | static void | | 150 | static void |
139 | motoi2c_release_bus(void *v, int flags) | | 151 | motoi2c_release_bus(void *v, int flags) |
140 | { | | 152 | { |
141 | struct motoi2c_softc * const sc = v; | | 153 | struct motoi2c_softc * const sc = v; |
142 | | | 154 | |
143 | I2C_WRITE(I2CCR, 0); /* reset before changing anything */ | | 155 | I2C_WRITE(I2CCR, sc->sc_disable_mask); /* disable the I2C module */ |
144 | } | | 156 | } |
145 | | | 157 | |
146 | static int | | 158 | static int |
147 | motoi2c_stop_wait(struct motoi2c_softc *sc) | | 159 | motoi2c_stop_wait(struct motoi2c_softc *sc) |
148 | { | | 160 | { |
149 | u_int timo; | | 161 | u_int timo; |
150 | int error = 0; | | 162 | int error = 0; |
151 | | | 163 | |
152 | timo = 1000; | | 164 | timo = 1000; |
153 | while ((I2C_READ(I2CSR) & SR_MBB) != 0 && --timo) | | 165 | while ((I2C_READ(I2CSR) & SR_MBB) != 0 && --timo) |
154 | DELAY(1); | | 166 | DELAY(1); |
155 | | | 167 | |
156 | if (timo == 0) { | | 168 | if (timo == 0) { |
157 | DPRINTF(("%s: timeout (sr=%#x)\n", __func__, I2C_READ(I2CSR))); | | 169 | DPRINTF(("%s: timeout (sr=%#x)\n", __func__, I2C_READ(I2CSR))); |
158 | error = ETIMEDOUT; | | 170 | error = ETIMEDOUT; |
159 | } | | 171 | } |
160 | | | 172 | |
161 | return error; | | 173 | return error; |
162 | } | | 174 | } |
163 | | | 175 | |
| | | 176 | static void |
| | | 177 | motoi2c_clear_status(struct motoi2c_softc *sc, uint8_t sr) |
| | | 178 | { |
| | | 179 | if ((sc->sc_flags & MOTOI2C_F_STATUS_W1C) != 0) { |
| | | 180 | I2C_WRITE(I2CSR, sr); |
| | | 181 | } else { |
| | | 182 | I2C_WRITE(I2CSR, 0); |
| | | 183 | } |
| | | 184 | } |
| | | 185 | |
164 | /* busy waiting for byte data transfer completion */ | | 186 | /* busy waiting for byte data transfer completion */ |
165 | static int | | 187 | static int |
166 | motoi2c_busy_wait(struct motoi2c_softc *sc, uint8_t cr) | | 188 | motoi2c_busy_wait(struct motoi2c_softc *sc, uint8_t cr) |
167 | { | | 189 | { |
168 | uint8_t sr; | | 190 | uint8_t sr; |
169 | u_int timo; | | 191 | u_int timo; |
170 | int error = 0; | | 192 | int error = 0; |
171 | | | 193 | |
172 | timo = 1000; | | 194 | timo = 1000; |
173 | while (((sr = I2C_READ(I2CSR)) & SR_MIF) == 0 && --timo) | | 195 | while (((sr = I2C_READ(I2CSR)) & SR_MIF) == 0 && --timo) |
174 | DELAY(10); | | 196 | DELAY(10); |
175 | | | 197 | |
176 | if (timo == 0) { | | 198 | if (timo == 0) { |
177 | DPRINTF(("%s: timeout (sr=%#x, cr=%#x)\n", | | 199 | DPRINTF(("%s: timeout (sr=%#x, cr=%#x)\n", |
178 | __func__, sr, I2C_READ(I2CCR))); | | 200 | __func__, sr, I2C_READ(I2CCR))); |
179 | error = ETIMEDOUT; | | 201 | error = ETIMEDOUT; |
180 | } | | 202 | } |
181 | /* | | 203 | /* |
182 | * RXAK is only valid when transmitting. | | 204 | * RXAK is only valid when transmitting. |
183 | */ | | 205 | */ |
184 | if ((cr & CR_MTX) && (sr & SR_RXAK)) { | | 206 | if ((cr & CR_MTX) && (sr & SR_RXAK)) { |
185 | DPRINTF(("%s: missing rx ack (%#x): spin=%u\n", | | 207 | DPRINTF(("%s: missing rx ack (%#x): spin=%u\n", |
186 | __func__, sr, 1000 - timo)); | | 208 | __func__, sr, 1000 - timo)); |
187 | error = EIO; | | 209 | error = EIO; |
188 | } | | 210 | } |
189 | I2C_WRITE(I2CSR, 0); | | 211 | motoi2c_clear_status(sc, sr); |
190 | return error; | | 212 | return error; |
191 | } | | 213 | } |
192 | | | 214 | |
193 | int | | 215 | int |
194 | motoi2c_intr(void *v) | | 216 | motoi2c_intr(void *v) |
195 | { | | 217 | { |
196 | struct motoi2c_softc * const sc = v; | | 218 | struct motoi2c_softc * const sc = v; |
197 | | | 219 | |
198 | panic("%s(%p)", __func__, sc); | | 220 | panic("%s(%p)", __func__, sc); |
199 | | | 221 | |
200 | return 0; | | 222 | return 0; |
201 | } | | 223 | } |
202 | | | 224 | |
| @@ -218,45 +240,45 @@ motoi2c_exec(void *v, i2c_op_t op, i2c_a | | | @@ -218,45 +240,45 @@ motoi2c_exec(void *v, i2c_op_t op, i2c_a |
218 | DPRINTF(("%s(%#x,%#x,%p,%zu,%p,%zu,%#x): sr=%#x cr=%#x\n", | | 240 | DPRINTF(("%s(%#x,%#x,%p,%zu,%p,%zu,%#x): sr=%#x cr=%#x\n", |
219 | __func__, op, addr, cmdbuf, cmdlen, databuf, datalen, flags, | | 241 | __func__, op, addr, cmdbuf, cmdlen, databuf, datalen, flags, |
220 | sr, cr)); | | 242 | sr, cr)); |
221 | #endif | | 243 | #endif |
222 | | | 244 | |
223 | if ((cr & CR_MSTA) == 0 && (sr & SR_MBB) != 0) { | | 245 | if ((cr & CR_MSTA) == 0 && (sr & SR_MBB) != 0) { |
224 | /* wait for bus becoming available */ | | 246 | /* wait for bus becoming available */ |
225 | error = motoi2c_stop_wait(sc); | | 247 | error = motoi2c_stop_wait(sc); |
226 | if (error) | | 248 | if (error) |
227 | return ETIMEDOUT; | | 249 | return ETIMEDOUT; |
228 | } | | 250 | } |
229 | | | 251 | |
230 | /* reset interrupt and arbitration-lost flags (all others are RO) */ | | 252 | /* reset interrupt and arbitration-lost flags (all others are RO) */ |
231 | I2C_WRITE(I2CSR, 0); | | 253 | motoi2c_clear_status(sc, sr); |
232 | sr = I2C_READ(I2CSR); | | 254 | sr = I2C_READ(I2CSR); |
233 | | | 255 | |
234 | /* | | 256 | /* |
235 | * Generate start condition | | 257 | * Generate start condition |
236 | */ | | 258 | */ |
237 | cr = CR_MEN | CR_MTX | CR_MSTA; | | 259 | cr = sc->sc_enable_mask | CR_MTX | CR_MSTA; |
238 | I2C_WRITE(I2CCR, cr); | | 260 | I2C_WRITE(I2CCR, cr); |
239 | | | 261 | |
240 | DPRINTF(("%s: started: sr=%#x cr=%#x/%#x\n", | | 262 | DPRINTF(("%s: started: sr=%#x cr=%#x/%#x\n", |
241 | __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR))); | | 263 | __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR))); |
242 | | | 264 | |
243 | sr = I2C_READ(I2CSR); | | 265 | sr = I2C_READ(I2CSR); |
244 | if (sr & SR_MAL) { | | 266 | if (sr & SR_MAL) { |
245 | DPRINTF(("%s: lost bus: sr=%#x cr=%#x/%#x\n", | | 267 | DPRINTF(("%s: lost bus: sr=%#x cr=%#x/%#x\n", |
246 | __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR))); | | 268 | __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR))); |
247 | I2C_WRITE(I2CCR, 0); | | 269 | I2C_WRITE(I2CCR, sc->sc_disable_mask); |
248 | DELAY(10); | | 270 | DELAY(10); |
249 | I2C_WRITE(I2CCR, CR_MEN | CR_MTX | CR_MSTA); | | 271 | I2C_WRITE(I2CCR, sc->sc_enable_mask | CR_MTX | CR_MSTA); |
250 | DELAY(10); | | 272 | DELAY(10); |
251 | sr = I2C_READ(I2CSR); | | 273 | sr = I2C_READ(I2CSR); |
252 | if (sr & SR_MAL) { | | 274 | if (sr & SR_MAL) { |
253 | error = EBUSY; | | 275 | error = EBUSY; |
254 | goto out; | | 276 | goto out; |
255 | } | | 277 | } |
256 | DPRINTF(("%s: reacquired bus: sr=%#x cr=%#x/%#x\n", | | 278 | DPRINTF(("%s: reacquired bus: sr=%#x cr=%#x/%#x\n", |
257 | __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR))); | | 279 | __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR))); |
258 | } | | 280 | } |
259 | | | 281 | |
260 | /* send target address and transfer direction */ | | 282 | /* send target address and transfer direction */ |
261 | uint8_t addr_byte = (addr << 1) | | 283 | uint8_t addr_byte = (addr << 1) |
262 | | (cmdlen == 0 && I2C_OP_READ_P(op) ? 1 : 0); | | 284 | | (cmdlen == 0 && I2C_OP_READ_P(op) ? 1 : 0); |
| @@ -319,34 +341,34 @@ motoi2c_exec(void *v, i2c_op_t op, i2c_a | | | @@ -319,34 +341,34 @@ motoi2c_exec(void *v, i2c_op_t op, i2c_a |
319 | * the transmit acknowledge bit (I2CCR[TXAK])) before | | 341 | * the transmit acknowledge bit (I2CCR[TXAK])) before |
320 | * reading the next-to-last byte of data. | | 342 | * reading the next-to-last byte of data. |
321 | */ | | 343 | */ |
322 | error = motoi2c_busy_wait(sc, cr); | | 344 | error = motoi2c_busy_wait(sc, cr); |
323 | if (error) { | | 345 | if (error) { |
324 | DPRINTF(("%s: error reading byte %zu: %d\n", | | 346 | DPRINTF(("%s: error reading byte %zu: %d\n", |
325 | __func__, i, error)); | | 347 | __func__, i, error)); |
326 | goto out; | | 348 | goto out; |
327 | } | | 349 | } |
328 | if (i == datalen - 2) { | | 350 | if (i == datalen - 2) { |
329 | cr |= CR_TXAK; | | 351 | cr |= CR_TXAK; |
330 | I2C_WRITE(I2CCR, cr); | | 352 | I2C_WRITE(I2CCR, cr); |
331 | } else if (i == datalen - 1 && I2C_OP_STOP_P(op)) { | | 353 | } else if (i == datalen - 1 && I2C_OP_STOP_P(op)) { |
332 | cr = CR_MEN | CR_TXAK; | | 354 | cr = sc->sc_enable_mask | CR_TXAK; |
333 | I2C_WRITE(I2CCR, cr); | | 355 | I2C_WRITE(I2CCR, cr); |
334 | } | | 356 | } |
335 | *dataptr++ = I2C_READ(I2CDR); | | 357 | *dataptr++ = I2C_READ(I2CDR); |
336 | } | | 358 | } |
337 | if (datalen == 0) { | | 359 | if (datalen == 0) { |
338 | if (I2C_OP_STOP_P(op)) { | | 360 | if (I2C_OP_STOP_P(op)) { |
339 | cr = CR_MEN | CR_TXAK; | | 361 | cr = sc->sc_enable_mask | CR_TXAK; |
340 | I2C_WRITE(I2CCR, cr); | | 362 | I2C_WRITE(I2CCR, cr); |
341 | } | | 363 | } |
342 | (void)I2C_READ(I2CDR); /* dummy read */ | | 364 | (void)I2C_READ(I2CDR); /* dummy read */ |
343 | error = motoi2c_busy_wait(sc, cr); | | 365 | error = motoi2c_busy_wait(sc, cr); |
344 | if (error) { | | 366 | if (error) { |
345 | DPRINTF(("%s: error reading dummy last byte:" | | 367 | DPRINTF(("%s: error reading dummy last byte:" |
346 | "%d\n", __func__, error)); | | 368 | "%d\n", __func__, error)); |
347 | goto out; | | 369 | goto out; |
348 | } | | 370 | } |
349 | } | | 371 | } |
350 | } else { | | 372 | } else { |
351 | const uint8_t *dataptr = databuf; | | 373 | const uint8_t *dataptr = databuf; |
352 | for (size_t i = 0; i < datalen; i++) { | | 374 | for (size_t i = 0; i < datalen; i++) { |
| @@ -356,25 +378,25 @@ motoi2c_exec(void *v, i2c_op_t op, i2c_a | | | @@ -356,25 +378,25 @@ motoi2c_exec(void *v, i2c_op_t op, i2c_a |
356 | DPRINTF(("%s: error sending data byte %zu:" | | 378 | DPRINTF(("%s: error sending data byte %zu:" |
357 | " %d\n", __func__, i, error)); | | 379 | " %d\n", __func__, i, error)); |
358 | goto out; | | 380 | goto out; |
359 | } | | 381 | } |
360 | } | | 382 | } |
361 | } | | 383 | } |
362 | | | 384 | |
363 | out: | | 385 | out: |
364 | /* | | 386 | /* |
365 | * If we encountered an error condition or caller wants a STOP, | | 387 | * If we encountered an error condition or caller wants a STOP, |
366 | * send a STOP. | | 388 | * send a STOP. |
367 | */ | | 389 | */ |
368 | if (error || (cr & CR_TXAK) || ((cr & CR_MSTA) && I2C_OP_STOP_P(op))) { | | 390 | if (error || (cr & CR_TXAK) || ((cr & CR_MSTA) && I2C_OP_STOP_P(op))) { |
369 | cr = CR_MEN; | | 391 | cr = sc->sc_enable_mask; |
370 | I2C_WRITE(I2CCR, cr); | | 392 | I2C_WRITE(I2CCR, cr); |
371 | motoi2c_stop_wait(sc); | | 393 | motoi2c_stop_wait(sc); |
372 | DPRINTF(("%s: stopping: cr=%#x/%#x\n", __func__, | | 394 | DPRINTF(("%s: stopping: cr=%#x/%#x\n", __func__, |
373 | cr, I2C_READ(I2CCR))); | | 395 | cr, I2C_READ(I2CCR))); |
374 | } | | 396 | } |
375 | | | 397 | |
376 | DPRINTF(("%s: exit sr=%#x cr=%#x: %d\n", __func__, | | 398 | DPRINTF(("%s: exit sr=%#x cr=%#x: %d\n", __func__, |
377 | I2C_READ(I2CSR), I2C_READ(I2CCR), error)); | | 399 | I2C_READ(I2CSR), I2C_READ(I2CCR), error)); |
378 | | | 400 | |
379 | return error; | | 401 | return error; |
380 | } | | 402 | } |