Annotation of sys/arch/arm/xscale/pxa2x0_i2c.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pxa2x0_i2c.c,v 1.2 2005/05/26 03:52:07 pascoe Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Christopher Pascoe <pascoe@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21:
22: #include <arm/xscale/pxa2x0reg.h>
23: #include <arm/xscale/pxa2x0var.h>
24: #include <arm/xscale/pxa2x0_i2c.h>
25: #include <arm/xscale/pxa2x0_gpio.h>
26:
27: #define I2C_RETRY_COUNT 10
28:
29: int
30: pxa2x0_i2c_attach_sub(struct pxa2x0_i2c_softc *sc)
31: {
32: if (bus_space_map(sc->sc_iot, PXA2X0_I2C_BASE,
33: PXA2X0_I2C_SIZE, 0, &sc->sc_ioh)) {
34: sc->sc_size = 0;
35: return EIO;
36: }
37: bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, sc->sc_size,
38: BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
39:
40: /*
41: * Configure the alternate functions. The _IN is arbitrary, as the
42: * direction is managed by the I2C unit when comms are in progress.
43: */
44: pxa2x0_gpio_set_function(117, GPIO_ALT_FN_1_IN); /* SCL */
45: pxa2x0_gpio_set_function(118, GPIO_ALT_FN_1_IN); /* SDA */
46:
47: pxa2x0_i2c_init(sc);
48:
49: return 0;
50: }
51:
52: int
53: pxa2x0_i2c_detach_sub(struct pxa2x0_i2c_softc *sc)
54: {
55: if (sc->sc_size) {
56: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
57: sc->sc_size = 0;
58: }
59: pxa2x0_clkman_config(CKEN_I2C, 0);
60:
61: return 0;
62: }
63:
64: void
65: pxa2x0_i2c_init(struct pxa2x0_i2c_softc *sc)
66: {
67: pxa2x0_i2c_open(sc);
68: pxa2x0_i2c_close(sc);
69: }
70:
71: void
72: pxa2x0_i2c_open(struct pxa2x0_i2c_softc *sc)
73: {
74: /* Enable the clock to the standard I2C unit. */
75: pxa2x0_clkman_config(CKEN_I2C, 1);
76: }
77:
78: void
79: pxa2x0_i2c_close(struct pxa2x0_i2c_softc *sc)
80: {
81: /* Reset and disable the standard I2C unit. */
82: bus_space_write_4(sc->sc_iot, sc->sc_ioh, I2C_ICR, ICR_UR);
83: bus_space_write_4(sc->sc_iot, sc->sc_ioh, I2C_ISAR, 0);
84: delay(1);
85: pxa2x0_clkman_config(CKEN_I2C, 0);
86: }
87:
88: int
89: pxa2x0_i2c_read(struct pxa2x0_i2c_softc *sc, u_char slave, u_char *valuep)
90: {
91: u_int32_t rv;
92: int timeout;
93: int tries = I2C_RETRY_COUNT;
94: bus_space_tag_t iot = sc->sc_iot;
95: bus_space_handle_t ioh = sc->sc_ioh;
96:
97: retry:
98: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
99: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
100: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE | ISR_IRF);
101: delay(1);
102: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
103:
104: /* Write slave device address. */
105: bus_space_write_4(iot, ioh, I2C_IDBR, (slave<<1) | 0x1);
106: rv = bus_space_read_4(iot, ioh, I2C_ICR);
107: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_START);
108: rv = bus_space_read_4(iot, ioh, I2C_ICR);
109: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
110: rv = bus_space_read_4(iot, ioh, I2C_ICR);
111: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
112:
113: timeout = 10000;
114: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
115: if (timeout-- == 0)
116: goto err;
117: delay(1);
118: }
119:
120: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
121:
122: rv = bus_space_read_4(iot, ioh, I2C_ICR);
123: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
124:
125: /* Read data value. */
126: rv = bus_space_read_4(iot, ioh, I2C_ICR);
127: bus_space_write_4(iot, ioh, I2C_ICR, rv |
128: (ICR_STOP | ICR_ACKNAK));
129: rv = bus_space_read_4(iot, ioh, I2C_ICR);
130: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
131:
132: timeout = 10000;
133: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_IRF) == 0) {
134: if (timeout-- == 0)
135: goto err;
136: delay(1);
137: }
138:
139: bus_space_write_4(iot, ioh, I2C_ISR, ISR_IRF);
140:
141: rv = bus_space_read_4(iot, ioh, I2C_IDBR);
142: *valuep = (u_char)rv;
143: rv = bus_space_read_4(iot, ioh, I2C_ICR);
144: bus_space_write_4(iot, ioh, I2C_ICR, rv &
145: ~(ICR_STOP | ICR_ACKNAK));
146:
147: return (0);
148: err:
149: if (tries-- >= 0)
150: goto retry;
151:
152: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
153: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
154: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE | ISR_IRF);
155: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
156:
157: return (-EIO);
158: }
159:
160: int
161: pxa2x0_i2c_write(struct pxa2x0_i2c_softc *sc, u_char slave, u_char value)
162: {
163: u_int32_t rv;
164: int timeout;
165: int tries = I2C_RETRY_COUNT;
166: bus_space_tag_t iot = sc->sc_iot;
167: bus_space_handle_t ioh = sc->sc_ioh;
168:
169: retry:
170: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
171: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
172: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
173: delay(1);
174: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
175:
176: /* Write slave device address. */
177: bus_space_write_4(iot, ioh, I2C_IDBR, (slave<<1));
178: rv = bus_space_read_4(iot, ioh, I2C_ICR);
179: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_START);
180: rv = bus_space_read_4(iot, ioh, I2C_ICR);
181: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
182: rv = bus_space_read_4(iot, ioh, I2C_ICR);
183: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
184:
185: timeout = 10000;
186: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
187: if (timeout-- == 0)
188: goto err;
189: delay(1);
190: }
191: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
192: goto err;
193:
194: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
195:
196: /* Write data. */
197: rv = bus_space_read_4(iot, ioh, I2C_ICR);
198: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
199: rv = bus_space_read_4(iot, ioh, I2C_ICR);
200: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_STOP);
201: bus_space_write_4(iot, ioh, I2C_IDBR, value);
202: rv = bus_space_read_4(iot, ioh, I2C_ICR);
203: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
204:
205: timeout = 10000;
206: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
207: if (timeout-- == 0)
208: goto err;
209: delay(1);
210: }
211: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
212: goto err;
213:
214: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
215:
216: rv = bus_space_read_4(iot, ioh, I2C_ICR);
217: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
218:
219: return (0);
220: err:
221: if (tries-- >= 0)
222: goto retry;
223:
224: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
225: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
226: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
227: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
228:
229: return (-EIO);
230: }
231:
232: int
233: pxa2x0_i2c_write_2(struct pxa2x0_i2c_softc *sc, u_char slave, u_short value)
234: {
235: u_int32_t rv;
236: int timeout;
237: int tries = I2C_RETRY_COUNT;
238: bus_space_tag_t iot = sc->sc_iot;
239: bus_space_handle_t ioh = sc->sc_ioh;
240:
241: retry:
242: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
243: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
244: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
245: delay(1);
246: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
247:
248: /* Write slave device address. */
249: bus_space_write_4(iot, ioh, I2C_IDBR, (slave<<1));
250: rv = bus_space_read_4(iot, ioh, I2C_ICR);
251: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_START);
252: rv = bus_space_read_4(iot, ioh, I2C_ICR);
253: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
254: rv = bus_space_read_4(iot, ioh, I2C_ICR);
255: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
256:
257: timeout = 10000;
258: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
259: if (timeout-- == 0)
260: goto err;
261: delay(1);
262: }
263: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
264: goto err;
265:
266: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
267:
268: /* Write upper 8 bits of data. */
269: bus_space_write_4(iot, ioh, I2C_IDBR, (value >> 8) & 0xff);
270: rv = bus_space_read_4(iot, ioh, I2C_ICR);
271: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
272: rv = bus_space_read_4(iot, ioh, I2C_ICR);
273: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
274: rv = bus_space_read_4(iot, ioh, I2C_ICR);
275: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
276:
277: timeout = 10000;
278: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
279: if (timeout-- == 0)
280: goto err;
281: delay(1);
282: }
283: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
284: goto err;
285:
286: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
287:
288: /* Write lower 8 bits of data. */
289: bus_space_write_4(iot, ioh, I2C_IDBR, value & 0xff);
290: rv = bus_space_read_4(iot, ioh, I2C_ICR);
291: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
292: rv = bus_space_read_4(iot, ioh, I2C_ICR);
293: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_STOP);
294: rv = bus_space_read_4(iot, ioh, I2C_ICR);
295: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
296:
297: timeout = 10000;
298: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
299: if (timeout-- == 0)
300: goto err;
301: delay(1);
302: }
303: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
304: goto err;
305:
306: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
307:
308: rv = bus_space_read_4(iot, ioh, I2C_ICR);
309: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
310:
311: return (0);
312: err:
313: if (tries-- >= 0)
314: goto retry;
315:
316: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
317: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
318: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
319: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
320:
321: return (-EIO);
322: }
CVSweb