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