Annotation of sys/arch/macppc/dev/kiic.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: kiic.c,v 1.2 2007/05/20 23:38:52 thib Exp $ */
2: /* $NetBSD: kiic.c,v 1.1 2003/12/27 02:19:34 grant Exp $ */
3:
4: /*-
5: * Copyright (c) 2001 Tsubai Masanari. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: #include <sys/param.h>
31: #include <sys/device.h>
32: #include <sys/systm.h>
33:
34: #include <dev/ofw/openfirm.h>
35: #include <uvm/uvm_extern.h>
36: #include <machine/autoconf.h>
37:
38: #include <macppc/dev/kiicvar.h>
39: #include <macppc/dev/maci2cvar.h>
40:
41: int kiic_match(struct device *, void *, void *);
42: void kiic_attach(struct device *, struct device *, void *);
43: void kiic_attach_bus(struct kiic_softc *, struct kiic_bus *, int);
44: inline u_int kiic_readreg(struct kiic_softc *, int);
45: inline void kiic_writereg(struct kiic_softc *, int, u_int);
46: u_int kiic_getmode(struct kiic_softc *);
47: void kiic_setmode(struct kiic_softc *, u_int, u_int);
48: u_int kiic_getspeed(struct kiic_softc *);
49: void kiic_setspeed(struct kiic_softc *, u_int);
50: int kiic_intr(struct kiic_softc *);
51: int kiic_poll(struct kiic_softc *, int);
52: int kiic_start(struct kiic_softc *, int, int, void *, int);
53: int kiic_read(struct kiic_softc *, int, int, void *, int);
54: int kiic_write(struct kiic_softc *, int, int, const void *, int);
55:
56: /* I2C glue */
57: int kiic_i2c_acquire_bus(void *, int);
58: void kiic_i2c_release_bus(void *, int);
59: int kiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
60: void *, size_t, int);
61:
62: struct cfattach kiic_ca = {
63: sizeof(struct kiic_softc), kiic_match, kiic_attach
64: };
65: struct cfattach kiic_memc_ca = {
66: sizeof(struct kiic_softc), kiic_match, kiic_attach
67: };
68:
69: struct cfdriver kiic_cd = {
70: NULL, "kiic", DV_DULL
71: };
72:
73: int
74: kiic_match(struct device *parent, void *match, void *aux)
75: {
76: struct confargs *ca = aux;
77:
78: if (strcmp(ca->ca_name, "i2c") == 0 &&
79: ca->ca_nreg >= 4)
80: return (1);
81:
82: return (0);
83: }
84:
85: void
86: kiic_attach(struct device *parent, struct device *self, void *aux)
87: {
88: struct kiic_softc *sc = (struct kiic_softc *)self;
89: struct confargs *ca = aux;
90: int node = ca->ca_node;
91: int rate, count = 0;
92: char name[32];
93:
94: ca->ca_reg[0] += ca->ca_baseaddr;
95:
96: if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
97: printf(": cannot get i2c-rate\n");
98: return;
99: }
100: if (OF_getprop(node, "AAPL,address", &sc->sc_paddr, 4) != 4) {
101: printf(": unable to find i2c address\n");
102: return;
103: }
104: if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
105: printf(": unable to find i2c address step\n");
106: return;
107: }
108: sc->sc_reg = mapiodev(sc->sc_paddr, (DATA+1)*sc->sc_regstep);
109:
110: printf("\n");
111:
112: kiic_writereg(sc, STATUS, 0);
113: kiic_writereg(sc, ISR, 0);
114: kiic_writereg(sc, IER, 0);
115:
116: kiic_setmode(sc, I2C_STDSUBMODE, 0);
117: kiic_setspeed(sc, I2C_100kHz); /* XXX rate */
118:
119: rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname);
120: kiic_writereg(sc, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
121:
122: for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
123: if (OF_getprop(node, "name", &name, sizeof name) > 0) {
124: if (strcmp(name, "i2c-bus") == 0) {
125: kiic_attach_bus(sc, &sc->sc_bus[count], node);
126: if (++count >= KIIC_MAX_BUSSES)
127: break;
128: }
129: }
130: }
131:
132: /*
133: * If we didn't find any i2c-bus nodes, there is only a single
134: * i2c bus.
135: */
136:
137: if (count == 0)
138: kiic_attach_bus(sc, &sc->sc_bus[0], ca->ca_node);
139: }
140:
141: void
142: kiic_attach_bus(struct kiic_softc *sc, struct kiic_bus *bus, int node)
143: {
144: struct i2cbus_attach_args iba;
145: u_int32_t reg;
146:
147: if (OF_getprop(node, "reg", ®, sizeof reg) != sizeof reg)
148: return;
149:
150: bus->sc = sc;
151: bus->i2c_tag.ic_cookie = bus;
152: bus->i2c_tag.ic_acquire_bus = kiic_i2c_acquire_bus;
153: bus->i2c_tag.ic_release_bus = kiic_i2c_release_bus;
154: bus->i2c_tag.ic_exec = kiic_i2c_exec;
155: bus->reg = reg;
156:
157: bzero(&iba, sizeof iba);
158: iba.iba_name = "iic";
159: iba.iba_tag = &bus->i2c_tag;
160: iba.iba_bus_scan = maciic_scan;
161: iba.iba_bus_scan_arg = &node;
162: config_found(&sc->sc_dev, &iba, NULL);
163: }
164:
165: u_int
166: kiic_readreg(struct kiic_softc *sc, int reg)
167: {
168: u_char *addr = sc->sc_reg + sc->sc_regstep * reg;
169:
170: return (*addr);
171: }
172:
173: void
174: kiic_writereg(struct kiic_softc *sc, int reg, u_int val)
175: {
176: u_char *addr = sc->sc_reg + sc->sc_regstep * reg;
177:
178: *addr = val;
179: asm volatile ("eieio");
180: delay(10);
181: }
182:
183: u_int
184: kiic_getmode(struct kiic_softc *sc)
185: {
186: return kiic_readreg(sc, MODE) & I2C_MODE;
187: }
188:
189: void
190: kiic_setmode(struct kiic_softc *sc, u_int mode, u_int bus)
191: {
192: u_int x;
193:
194: KASSERT((mode & ~I2C_MODE) == 0);
195: x = kiic_readreg(sc, MODE);
196: x &= ~(I2C_MODE);
197: if (bus)
198: x |= I2C_BUS1;
199: else
200: x &= ~I2C_BUS1;
201: x |= mode;
202: kiic_writereg(sc, MODE, x);
203: }
204:
205: u_int
206: kiic_getspeed(struct kiic_softc *sc)
207: {
208: return kiic_readreg(sc, MODE) & I2C_SPEED;
209: }
210:
211: void
212: kiic_setspeed(struct kiic_softc *sc, u_int speed)
213: {
214: u_int x;
215:
216: KASSERT((speed & ~I2C_SPEED) == 0);
217: x = kiic_readreg(sc, MODE);
218: x &= ~I2C_SPEED;
219: x |= speed;
220: kiic_writereg(sc, MODE, x);
221: }
222:
223: int
224: kiic_intr(struct kiic_softc *sc)
225: {
226: u_int isr, x;
227:
228: isr = kiic_readreg(sc, ISR);
229: if (isr & I2C_INT_ADDR) {
230: #if 0
231: if ((kiic_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
232: /* No slave responded. */
233: sc->sc_flags |= I2C_ERROR;
234: goto out;
235: }
236: #endif
237:
238: if (sc->sc_flags & I2C_READING) {
239: if (sc->sc_resid > 1) {
240: x = kiic_readreg(sc, CONTROL);
241: x |= I2C_CT_AAK;
242: kiic_writereg(sc, CONTROL, x);
243: }
244: } else {
245: kiic_writereg(sc, DATA, *sc->sc_data++);
246: sc->sc_resid--;
247: }
248: }
249:
250: if (isr & I2C_INT_DATA) {
251: if (sc->sc_flags & I2C_READING) {
252: *sc->sc_data++ = kiic_readreg(sc, DATA);
253: sc->sc_resid--;
254:
255: if (sc->sc_resid == 0) { /* Completed */
256: kiic_writereg(sc, CONTROL, 0);
257: goto out;
258: }
259: } else {
260: #if 0
261: if ((kiic_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
262: /* No slave responded. */
263: sc->sc_flags |= I2C_ERROR;
264: goto out;
265: }
266: #endif
267:
268: if (sc->sc_resid == 0) {
269: x = kiic_readreg(sc, CONTROL) | I2C_CT_STOP;
270: kiic_writereg(sc, CONTROL, x);
271: } else {
272: kiic_writereg(sc, DATA, *sc->sc_data++);
273: sc->sc_resid--;
274: }
275: }
276: }
277:
278: out:
279: if (isr & I2C_INT_STOP) {
280: kiic_writereg(sc, CONTROL, 0);
281: sc->sc_flags &= ~I2C_BUSY;
282: }
283:
284: kiic_writereg(sc, ISR, isr);
285:
286: return (1);
287: }
288:
289: int
290: kiic_poll(struct kiic_softc *sc, int timo)
291: {
292: while (sc->sc_flags & I2C_BUSY) {
293: if (kiic_readreg(sc, ISR))
294: kiic_intr(sc);
295: timo -= 100;
296: if (timo < 0) {
297: printf("i2c_poll: timeout\n");
298: return (-1);
299: }
300: delay(100);
301: }
302: return (0);
303: }
304:
305: int
306: kiic_start(struct kiic_softc *sc, int addr, int subaddr, void *data, int len)
307: {
308: int rw = (sc->sc_flags & I2C_READING) ? 1 : 0;
309: int timo, x;
310:
311: KASSERT((addr & 1) == 0);
312:
313: sc->sc_data = data;
314: sc->sc_resid = len;
315: sc->sc_flags |= I2C_BUSY;
316:
317: timo = 1000 + len * 200;
318:
319: /* XXX TAS3001 sometimes takes 50ms to finish writing registers. */
320: /* if (addr == 0x68) */
321: timo += 100000;
322:
323: kiic_writereg(sc, ADDR, addr | rw);
324: kiic_writereg(sc, SUBADDR, subaddr);
325:
326: x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR;
327: kiic_writereg(sc, CONTROL, x);
328:
329: if (kiic_poll(sc, timo))
330: return (-1);
331: if (sc->sc_flags & I2C_ERROR) {
332: printf("I2C_ERROR\n");
333: return (-1);
334: }
335: return (0);
336: }
337:
338: int
339: kiic_read(struct kiic_softc *sc, int addr, int subaddr, void *data, int len)
340: {
341: sc->sc_flags = I2C_READING;
342: return kiic_start(sc, addr, subaddr, data, len);
343: }
344:
345: int
346: kiic_write(struct kiic_softc *sc, int addr, int subaddr, const void *data, int len)
347: {
348: sc->sc_flags = 0;
349: return kiic_start(sc, addr, subaddr, (void *)data, len);
350: }
351:
352: int
353: kiic_i2c_acquire_bus(void *cookie, int flags)
354: {
355: struct kiic_bus *bus = cookie;
356:
357: return (rw_enter(&bus->sc->sc_buslock, RW_WRITE));
358: }
359:
360: void
361: kiic_i2c_release_bus(void *cookie, int flags)
362: {
363: struct kiic_bus *bus = cookie;
364:
365: (void) rw_exit(&bus->sc->sc_buslock);
366: }
367:
368: int
369: kiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
370: const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
371: {
372: struct kiic_bus *bus = cookie;
373: u_int mode = I2C_STDSUBMODE;
374: u_int8_t cmd = 0;
375:
376: if (!I2C_OP_STOP_P(op) || cmdlen > 1)
377: return (EINVAL);
378:
379: if (cmdlen == 0)
380: mode = I2C_STDMODE;
381: else if (I2C_OP_READ_P(op))
382: mode = I2C_COMBMODE;
383:
384: if (cmdlen > 0)
385: cmd = *(u_int8_t *)cmdbuf;
386:
387: kiic_setmode(bus->sc, mode, bus->reg || addr & 0x80);
388: addr &= 0x7f;
389:
390: if (I2C_OP_READ_P(op)) {
391: if (kiic_read(bus->sc, (addr << 1), cmd, buf, len) != 0)
392: return (EIO);
393: } else {
394: if (kiic_write(bus->sc, (addr << 1), cmd, buf, len) != 0)
395: return (EIO);
396: }
397: return (0);
398: }
CVSweb