Annotation of src/sys/dev/i2c/i2c.c, Revision 1.14.6.1
1.14.6.1! jmcneill 1: /* $NetBSD: i2c.c,v 1.15 2007/09/01 22:19:25 riz Exp $ */
1.1 thorpej 2:
3: /*
4: * Copyright (c) 2003 Wasabi Systems, Inc.
5: * All rights reserved.
6: *
7: * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed for the NetBSD Project by
20: * Wasabi Systems, Inc.
21: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
23: * written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35: * POSSIBILITY OF SUCH DAMAGE.
36: */
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/device.h>
41: #include <sys/event.h>
42: #include <sys/conf.h>
1.11 jmcneill 43: #include <sys/malloc.h>
44: #include <sys/kthread.h>
45: #include <sys/proc.h>
46: #include <sys/kernel.h>
1.1 thorpej 47:
48: #include <dev/i2c/i2cvar.h>
49:
50: #include "locators.h"
51:
52: struct iic_softc {
53: struct device sc_dev;
54: i2c_tag_t sc_tag;
1.6 jmcneill 55: int sc_type;
1.1 thorpej 56: };
57:
1.11 jmcneill 58: static void iic_smbus_intr_thread(void *);
59:
1.1 thorpej 60: int
1.10 christos 61: iicbus_print(void *aux, const char *pnp)
1.1 thorpej 62: {
63:
64: if (pnp != NULL)
1.8 drochner 65: aprint_normal("iic at %s", pnp);
1.1 thorpej 66:
67: return (UNCONF);
68: }
69:
70: static int
1.10 christos 71: iic_print(void *aux, const char *pnp)
1.1 thorpej 72: {
73: struct i2c_attach_args *ia = aux;
74:
1.6 jmcneill 75: if (ia->ia_addr != (i2c_addr_t)-1)
76: aprint_normal(" addr 0x%x", ia->ia_addr);
1.1 thorpej 77:
78: return (UNCONF);
79: }
80:
81: static int
1.3 drochner 82: iic_search(struct device *parent, struct cfdata *cf,
1.10 christos 83: const int *ldesc, void *aux)
1.1 thorpej 84: {
85: struct iic_softc *sc = (void *) parent;
86: struct i2c_attach_args ia;
87:
88: ia.ia_tag = sc->sc_tag;
89: ia.ia_addr = cf->cf_loc[IICCF_ADDR];
90: ia.ia_size = cf->cf_loc[IICCF_SIZE];
1.6 jmcneill 91: ia.ia_type = sc->sc_type;
1.1 thorpej 92:
93: if (config_match(parent, cf, &ia) > 0)
94: config_attach(parent, cf, &ia, iic_print);
95:
96: return (0);
97: }
98:
99: static int
1.10 christos 100: iic_match(struct device *parent, struct cfdata *cf,
101: void *aux)
1.1 thorpej 102: {
103:
1.8 drochner 104: return (1);
1.1 thorpej 105: }
106:
107: static void
1.10 christos 108: iic_attach(struct device *parent, struct device *self, void *aux)
1.1 thorpej 109: {
1.7 thorpej 110: struct iic_softc *sc = device_private(self);
1.1 thorpej 111: struct i2cbus_attach_args *iba = aux;
1.14.6.1! jmcneill 112: i2c_addr_t addr;
1.14 ad 113: i2c_tag_t ic;
114: int rv;
1.14.6.1! jmcneill 115: int found = 0;
! 116: uint8_t cmd = 0, val;
1.1 thorpej 117:
118: aprint_naive(": I2C bus\n");
119: aprint_normal(": I2C bus\n");
120:
121: sc->sc_tag = iba->iba_tag;
1.6 jmcneill 122: sc->sc_type = iba->iba_type;
1.14 ad 123: ic = sc->sc_tag;
124: ic->ic_devname = self->dv_xname;
1.11 jmcneill 125:
1.13 jmcneill 126: LIST_INIT(&(sc->sc_tag->ic_list));
127: LIST_INIT(&(sc->sc_tag->ic_proc_list));
1.14 ad 128:
129: rv = kthread_create(PRI_NONE, 0, NULL, iic_smbus_intr_thread,
130: ic, &ic->ic_intr_thread, "%s", ic->ic_devname);
131: if (rv)
132: printf("%s: unable to create intr thread\n", ic->ic_devname);
1.1 thorpej 133:
1.14.6.1! jmcneill 134: if (sc->sc_type == I2C_TYPE_SMBUS) {
! 135: for (addr = 0x0; addr < 0x80; addr++) {
! 136: iic_acquire_bus(ic, 0);
! 137: if (iic_exec(ic, I2C_OP_READ_WITH_STOP, addr,
! 138: &cmd, 1, &val, 1, 0) == 0) {
! 139: if (found == 0)
! 140: aprint_normal("%s: devices at",
! 141: ic->ic_devname);
! 142: found++;
! 143: aprint_normal(" 0x%02x", addr);
! 144: }
! 145: iic_release_bus(ic, 0);
! 146: }
! 147: if (found == 0)
! 148: aprint_normal("%s: no devices found", ic->ic_devname);
! 149: aprint_normal("\n");
! 150: }
! 151:
1.1 thorpej 152: /*
1.2 wiz 153: * Attach all i2c devices described in the kernel
1.1 thorpej 154: * configuration file.
155: */
1.3 drochner 156: config_search_ia(iic_search, self, "iic", NULL);
1.1 thorpej 157: }
158:
1.11 jmcneill 159: static void
1.14 ad 160: iic_smbus_intr_thread(void *aux)
1.11 jmcneill 161: {
162: i2c_tag_t ic;
163: struct ic_intr_list *il;
164: int rv;
165:
166: ic = (i2c_tag_t)aux;
167: ic->ic_running = 1;
168: ic->ic_pending = 0;
169:
170: while (ic->ic_running) {
171: if (ic->ic_pending == 0)
172: rv = tsleep(ic, PZERO, "iicintr", hz);
173: if (ic->ic_pending > 0) {
174: LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
175: (*il->il_intr)(il->il_intrarg);
176: }
177: ic->ic_pending--;
178: }
179: }
180:
181: kthread_exit(0);
182: }
183:
184: void *
185: iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
186: {
187: struct ic_intr_list *il;
188:
189: il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
190: if (il == NULL)
191: return NULL;
192:
193: il->il_intr = intr;
194: il->il_intrarg = intrarg;
195:
196: LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
197:
198: return il;
199: }
200:
201: void
202: iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
203: {
204: struct ic_intr_list *il;
205:
206: il = (struct ic_intr_list *)hdl;
207:
208: LIST_REMOVE(il, il_next);
209: free(il, M_DEVBUF);
210:
211: return;
212: }
213:
214: void *
215: iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
216: {
217: struct ic_intr_list *il;
218:
219: il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
220: if (il == NULL)
221: return NULL;
222:
223: il->il_intr = intr;
224: il->il_intrarg = intrarg;
225:
226: LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
227:
228: return il;
229: }
230:
231: void
232: iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
233: {
234: struct ic_intr_list *il;
235:
236: il = (struct ic_intr_list *)hdl;
237:
238: LIST_REMOVE(il, il_next);
239: free(il, M_DEVBUF);
240:
241: return;
242: }
243:
244: int
245: iic_smbus_intr(i2c_tag_t ic)
246: {
247: struct ic_intr_list *il;
248:
249: LIST_FOREACH(il, &(ic->ic_list), il_next) {
250: (*il->il_intr)(il->il_intrarg);
251: }
252:
253: ic->ic_pending++;
254: wakeup(ic);
255:
256: return 1;
257: }
258:
1.1 thorpej 259: CFATTACH_DECL(iic, sizeof(struct iic_softc),
260: iic_match, iic_attach, NULL, NULL);
CVSweb <webmaster@jp.NetBSD.org>