Thu Jun 7 13:30:49 2018 UTC ()
Changes / enhancements to i2c indirect device auto-configuration:

— iic_search() chooses a “probe strategy” based on the
  "i2c-indirect-probe-strategy” property on the “iic” instance.
  Valid values are "smbus-quick-write”, "smbus-receive-byte”, and
  “none”.  If no value is specified, the default is "smbus-quick-write”.

— If the "i2c-indirect-device-whitelist” exists on the “iic” instance,
  iic_search() will first check the driver name in the cfdata_t against
  this list, and only allow the match/probe to move forward if the
  cfdata_t driver name is in the list.  This is primarily to accommodate
  the Intel integrated memory controller neutered-i2c-thing.

— If the cfdata_t specifies a wildcard address, each address of the i2c
  bus will be consulted.  If the cfdata_t contains a nailed-down address,
  then we limit the bus scan to that specific address.

— We explicitly skip reserved / special i2c addresses, such as the
  General-Call address, etc.

— We introduce the notion of a “match quality” for i2c drivers.  From
  lowest-quality to highest-quality: matched by plausible address only,
  matched by plausible address and poking at the bus to see if the
  device looks reasonable, matched by direct-config “compatible” string,
  matched by direct-config “driver name” string.

— If the “match quality” is merely “plausible address only”, then
  iic_search() will use the probe strategy selected above to see if
  a device responds to that address.


(thorpej)
diff -r1.60 -r1.61 src/sys/dev/i2c/i2c.c
diff -r1.12 -r1.13 src/sys/dev/i2c/i2cvar.h

cvs diff -r1.60 -r1.61 src/sys/dev/i2c/i2c.c (switch to unified diff)

--- src/sys/dev/i2c/i2c.c 2018/06/07 05:56:18 1.60
+++ src/sys/dev/i2c/i2c.c 2018/06/07 13:30:49 1.61
@@ -1,680 +1,879 @@ @@ -1,680 +1,879 @@
1/* $NetBSD: i2c.c,v 1.60 2018/06/07 05:56:18 thorpej Exp $ */ 1/* $NetBSD: i2c.c,v 1.61 2018/06/07 13:30:49 thorpej Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wasabi Systems, Inc. 4 * Copyright (c) 2003 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 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 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#ifdef _KERNEL_OPT 38#ifdef _KERNEL_OPT
39#include "opt_i2c.h" 39#include "opt_i2c.h"
40#endif 40#endif
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.60 2018/06/07 05:56:18 thorpej Exp $"); 43__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.61 2018/06/07 13:30:49 thorpej Exp $");
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/device.h> 47#include <sys/device.h>
48#include <sys/event.h> 48#include <sys/event.h>
49#include <sys/conf.h> 49#include <sys/conf.h>
50#include <sys/malloc.h> 50#include <sys/malloc.h>
51#include <sys/kmem.h> 51#include <sys/kmem.h>
52#include <sys/kthread.h> 52#include <sys/kthread.h>
53#include <sys/proc.h> 53#include <sys/proc.h>
54#include <sys/kernel.h> 54#include <sys/kernel.h>
55#include <sys/fcntl.h> 55#include <sys/fcntl.h>
56#include <sys/module.h> 56#include <sys/module.h>
57#include <sys/once.h> 57#include <sys/once.h>
58#include <sys/mutex.h> 58#include <sys/mutex.h>
59 59
60#include <dev/i2c/i2cvar.h> 60#include <dev/i2c/i2cvar.h>
61 61
62#include "ioconf.h" 62#include "ioconf.h"
63#include "locators.h" 63#include "locators.h"
64 64
65#ifndef I2C_MAX_ADDR 65#ifndef I2C_MAX_ADDR
66#define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */ 66#define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */
67#endif 67#endif
68 68
69struct iic_softc { 69struct iic_softc {
 70 device_t sc_dev;
70 i2c_tag_t sc_tag; 71 i2c_tag_t sc_tag;
71 int sc_type; 72 int sc_type;
72 device_t sc_devices[I2C_MAX_ADDR + 1]; 73 device_t sc_devices[I2C_MAX_ADDR + 1];
73}; 74};
74 75
75static dev_type_open(iic_open); 76static dev_type_open(iic_open);
76static dev_type_close(iic_close); 77static dev_type_close(iic_close);
77static dev_type_ioctl(iic_ioctl); 78static dev_type_ioctl(iic_ioctl);
78 79
79int iic_init(void); 80int iic_init(void);
80 81
81kmutex_t iic_mtx; 82kmutex_t iic_mtx;
82int iic_refcnt; 83int iic_refcnt;
83 84
84ONCE_DECL(iic_once); 85ONCE_DECL(iic_once);
85 86
86const struct cdevsw iic_cdevsw = { 87const struct cdevsw iic_cdevsw = {
87 .d_open = iic_open, 88 .d_open = iic_open,
88 .d_close = iic_close, 89 .d_close = iic_close,
89 .d_read = noread, 90 .d_read = noread,
90 .d_write = nowrite, 91 .d_write = nowrite,
91 .d_ioctl = iic_ioctl, 92 .d_ioctl = iic_ioctl,
92 .d_stop = nostop, 93 .d_stop = nostop,
93 .d_tty = notty, 94 .d_tty = notty,
94 .d_poll = nopoll, 95 .d_poll = nopoll,
95 .d_mmap = nommap, 96 .d_mmap = nommap,
96 .d_kqfilter = nokqfilter, 97 .d_kqfilter = nokqfilter,
97 .d_discard = nodiscard, 98 .d_discard = nodiscard,
98 .d_flag = D_OTHER 99 .d_flag = D_OTHER
99}; 100};
100 101
101static void iic_smbus_intr_thread(void *); 102static void iic_smbus_intr_thread(void *);
102static void iic_fill_compat(struct i2c_attach_args*, const char*, 103static void iic_fill_compat(struct i2c_attach_args*, const char*,
103 size_t, char **); 104 size_t, char **);
104 105
105static int 106static int
106iic_print_direct(void *aux, const char *pnp) 107iic_print_direct(void *aux, const char *pnp)
107{ 108{
108 struct i2c_attach_args *ia = aux; 109 struct i2c_attach_args *ia = aux;
109 110
110 if (pnp != NULL) 111 if (pnp != NULL)
111 aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp, 112 aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp,
112 ia->ia_addr); 113 ia->ia_addr);
113 else 114 else
114 aprint_normal(" addr 0x%02x", ia->ia_addr); 115 aprint_normal(" addr 0x%02x", ia->ia_addr);
115 116
116 return UNCONF; 117 return UNCONF;
117} 118}
118 119
119static int 120static int
120iic_print(void *aux, const char *pnp) 121iic_print(void *aux, const char *pnp)
121{ 122{
122 struct i2c_attach_args *ia = aux; 123 struct i2c_attach_args *ia = aux;
123 124
124 if (ia->ia_addr != (i2c_addr_t)IICCF_ADDR_DEFAULT) 125 if (ia->ia_addr != (i2c_addr_t)IICCF_ADDR_DEFAULT)
125 aprint_normal(" addr 0x%x", ia->ia_addr); 126 aprint_normal(" addr 0x%x", ia->ia_addr);
126 127
127 return UNCONF; 128 return UNCONF;
128} 129}
129 130
 131static bool
 132iic_is_special_address(i2c_addr_t addr)
 133{
 134
 135 /*
 136 * See: https://www.i2c-bus.org/addressing/
 137 */
 138
 139 /* General Call (read) / Start Byte (write) */
 140 if (addr == 0x00)
 141 return (true);
 142
 143 /* CBUS Addresses */
 144 if (addr == 0x01)
 145 return (true);
 146
 147 /* Reserved for Different Bus Formats */
 148 if (addr == 0x02)
 149 return (true);
 150
 151 /* Reserved for future purposes */
 152 if (addr == 0x03)
 153 return (true);
 154
 155 /* High Speed Master Code */
 156 if ((addr & 0x7c) == 0x04)
 157 return (true);
 158
 159 /* 10-bit Slave Addressing prefix */
 160 if ((addr & 0x7c) == 0x78)
 161 return (true);
 162
 163 /* Reserved for future purposes */
 164 if ((addr & 0x7c) == 0x7c)
 165 return (true);
 166
 167 return (false);
 168}
 169
 170static int
 171iic_probe_none(struct iic_softc *sc,
 172 const struct i2c_attach_args *ia, int flags)
 173{
 174
 175 return (0);
 176}
 177
 178static int
 179iic_probe_smbus_quick_write(struct iic_softc *sc,
 180 const struct i2c_attach_args *ia, int flags)
 181{
 182 int error;
 183
 184 if ((error = iic_acquire_bus(ia->ia_tag, flags)) == 0) {
 185 error = iic_smbus_quick_write(ia->ia_tag, ia->ia_addr, flags);
 186 }
 187 (void) iic_release_bus(ia->ia_tag, flags);
 188
 189 return (error);
 190}
 191
 192static int
 193iic_probe_smbus_receive_byte(struct iic_softc *sc,
 194 const struct i2c_attach_args *ia, int flags)
 195{
 196 int error;
 197
 198 if ((error = iic_acquire_bus(ia->ia_tag, flags)) == 0) {
 199 uint8_t dummy;
 200
 201 error = iic_smbus_receive_byte(ia->ia_tag, ia->ia_addr,
 202 &dummy, flags);
 203 }
 204 (void) iic_release_bus(ia->ia_tag, flags);
 205
 206 return (error);
 207}
 208
 209static bool
 210iic_indirect_driver_is_whitelisted(struct iic_softc *sc, cfdata_t cf)
 211{
 212 prop_object_iterator_t iter;
 213 prop_array_t whitelist;
 214 prop_string_t pstr;
 215 prop_type_t ptype;
 216 bool rv = false;
 217
 218 whitelist = prop_dictionary_get(device_properties(sc->sc_dev),
 219 I2C_PROP_INDIRECT_DEVICE_WHITELIST);
 220 if (whitelist == NULL) {
 221 /* No whitelist -> everything allowed */
 222 return (true);
 223 }
 224
 225 if ((ptype = prop_object_type(whitelist)) != PROP_TYPE_ARRAY) {
 226 aprint_error_dev(sc->sc_dev,
 227 "invalid property type (%d) for '%s'; must be array (%d)\n",
 228 ptype, I2C_PROP_INDIRECT_DEVICE_WHITELIST, PROP_TYPE_ARRAY);
 229 return (false);
 230 }
 231
 232 iter = prop_array_iterator(whitelist);
 233 while ((pstr = prop_object_iterator_next(iter)) != NULL) {
 234 if (prop_string_equals_cstring(pstr, cf->cf_name)) {
 235 rv = true;
 236 break;
 237 }
 238 }
 239 prop_object_iterator_release(iter);
 240
 241 return (rv);
 242}
 243
130static int 244static int
131iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 245iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
132{ 246{
133 struct iic_softc *sc = device_private(parent); 247 struct iic_softc *sc = device_private(parent);
134 struct i2c_attach_args ia; 248 struct i2c_attach_args ia;
 249 int (*probe_func)(struct iic_softc *,
 250 const struct i2c_attach_args *, int);
 251 prop_string_t pstr;
 252 i2c_addr_t first_addr, last_addr;
135 253
136 /* 254 /*
137 * I2C doesn't have any regular probing capability. If we 255 * Before we do any more work, consult the allowed-driver
138 * encounter a cfdata with a wild-carded address or a wild- 256 * white-list for this bus (if any).
139 * carded parent spec, we skip them because they can only 
140 * be used for direct-coniguration. 
141 */ 257 */
142 if (cf->cf_loc[IICCF_ADDR] == IICCF_ADDR_DEFAULT || 258 if (iic_indirect_driver_is_whitelisted(sc, cf) == false)
143 cf->cf_pspec->cfp_unit == DVUNIT_ANY) 259 return (0);
144 return 0; 260
 261 /* default to "quick write". */
 262 probe_func = iic_probe_smbus_quick_write;
 263
 264 pstr = prop_dictionary_get(device_properties(sc->sc_dev),
 265 I2C_PROP_INDIRECT_PROBE_STRATEGY);
 266 if (pstr == NULL) {
 267 /* Use the default. */
 268 } else if (prop_string_equals_cstring(pstr,
 269 I2C_PROBE_STRATEGY_QUICK_WRITE)) {
 270 probe_func = iic_probe_smbus_quick_write;
 271 } else if (prop_string_equals_cstring(pstr,
 272 I2C_PROBE_STRATEGY_RECEIVE_BYTE)) {
 273 probe_func = iic_probe_smbus_receive_byte;
 274 } else if (prop_string_equals_cstring(pstr,
 275 I2C_PROBE_STRATEGY_NONE)) {
 276 probe_func = iic_probe_none;
 277 } else {
 278 aprint_error_dev(sc->sc_dev,
 279 "unknown probe strategy '%s'; defaulting to '%s'\n",
 280 prop_string_cstring_nocopy(pstr),
 281 I2C_PROBE_STRATEGY_QUICK_WRITE);
 282
 283 /* Use the default. */
 284 }
145 285
146 ia.ia_tag = sc->sc_tag; 286 ia.ia_tag = sc->sc_tag;
147 ia.ia_size = cf->cf_loc[IICCF_SIZE]; 287 ia.ia_size = cf->cf_loc[IICCF_SIZE];
148 ia.ia_type = sc->sc_type; 288 ia.ia_type = sc->sc_type;
149 289
150 ia.ia_name = NULL; 290 ia.ia_name = NULL;
151 ia.ia_ncompat = 0; 291 ia.ia_ncompat = 0;
152 ia.ia_compat = NULL; 292 ia.ia_compat = NULL;
153 ia.ia_prop = NULL; 293 ia.ia_prop = NULL;
154 294
155 for (ia.ia_addr = 0; ia.ia_addr <= I2C_MAX_ADDR; ia.ia_addr++) { 295 if (cf->cf_loc[IICCF_ADDR] == IICCF_ADDR_DEFAULT) {
 296 /*
 297 * This particular config directive has
 298 * wildcarded the address, so we will
 299 * scan the entire bus for it.
 300 */
 301 first_addr = 0;
 302 last_addr = I2C_MAX_ADDR;
 303 } else {
 304 /*
 305 * This config directive hard-wires the i2c
 306 * bus address for the device, so there is
 307 * no need to go poking around at any other
 308 * addresses.
 309 */
 310 if (cf->cf_loc[IICCF_ADDR] < 0 ||
 311 cf->cf_loc[IICCF_ADDR] > I2C_MAX_ADDR) {
 312 /* Invalid config directive! */
 313 return (0);
 314 }
 315 first_addr = last_addr = cf->cf_loc[IICCF_ADDR];
 316 }
 317
 318 for (ia.ia_addr = first_addr; ia.ia_addr <= last_addr; ia.ia_addr++) {
 319 int error, match_result;
 320
 321 /*
 322 * Skip I2C addresses that are reserved for
 323 * special purposes.
 324 */
 325 if (iic_is_special_address(ia.ia_addr))
 326 continue;
 327
 328 /*
 329 * Skip addresses where a device is already attached.
 330 */
156 if (sc->sc_devices[ia.ia_addr] != NULL) 331 if (sc->sc_devices[ia.ia_addr] != NULL)
157 continue; 332 continue;
158 333
159 if (cf->cf_loc[IICCF_ADDR] != ia.ia_addr) 334 /*
 335 * Call the "match" routine for the device. If that
 336 * returns success, then call the probe strategy
 337 * function.
 338 *
 339 * We do it in this order because i2c devices tend
 340 * to be found at a small number of possible addresses
 341 * (e.g. read-time clocks that are only ever found at
 342 * 0x68). This gives the driver a chance to skip any
 343 * address that are not valid for the device, saving
 344 * us from having to poke at the bus to see if anything
 345 * is there.
 346 */
 347 match_result = config_match(parent, cf, &ia);
 348 if (match_result <= 0)
 349 continue;
 350
 351 /*
 352 * If the quality of the match by the driver was low
 353 * (i.e. matched on being a valid address only, didn't
 354 * perform any hardware probe), invoke our probe routine
 355 * to see if it looks like something is really there.
 356 */
 357 if (match_result == I2C_MATCH_ADDRESS_ONLY &&
 358 (error = (*probe_func)(sc, &ia, I2C_F_POLL)) != 0)
160 continue; 359 continue;
161 360
162 if (config_match(parent, cf, &ia) > 0) 361 sc->sc_devices[ia.ia_addr] =
163 sc->sc_devices[ia.ia_addr] = 362 config_attach(parent, cf, &ia, iic_print);
164 config_attach(parent, cf, &ia, iic_print); 
165 } 363 }
166 364
167 return 0; 365 return 0;
168} 366}
169 367
170static void 368static void
171iic_child_detach(device_t parent, device_t child) 369iic_child_detach(device_t parent, device_t child)
172{ 370{
173 struct iic_softc *sc = device_private(parent); 371 struct iic_softc *sc = device_private(parent);
174 int i; 372 int i;
175 373
176 for (i = 0; i <= I2C_MAX_ADDR; i++) 374 for (i = 0; i <= I2C_MAX_ADDR; i++)
177 if (sc->sc_devices[i] == child) { 375 if (sc->sc_devices[i] == child) {
178 sc->sc_devices[i] = NULL; 376 sc->sc_devices[i] = NULL;
179 break; 377 break;
180 } 378 }
181} 379}
182 380
183static int 381static int
184iic_rescan(device_t self, const char *ifattr, const int *locators) 382iic_rescan(device_t self, const char *ifattr, const int *locators)
185{ 383{
186 config_search_ia(iic_search, self, ifattr, NULL); 384 config_search_ia(iic_search, self, ifattr, NULL);
187 return 0; 385 return 0;
188} 386}
189 387
190static int 388static int
191iic_match(device_t parent, cfdata_t cf, void *aux) 389iic_match(device_t parent, cfdata_t cf, void *aux)
192{ 390{
193 391
194 return 1; 392 return 1;
195} 393}
196 394
197static void 395static void
198iic_attach(device_t parent, device_t self, void *aux) 396iic_attach(device_t parent, device_t self, void *aux)
199{ 397{
200 struct iic_softc *sc = device_private(self); 398 struct iic_softc *sc = device_private(self);
201 struct i2cbus_attach_args *iba = aux; 399 struct i2cbus_attach_args *iba = aux;
202 prop_array_t child_devices; 400 prop_array_t child_devices;
203 prop_dictionary_t props; 401 prop_dictionary_t props;
204 char *buf; 402 char *buf;
205 i2c_tag_t ic; 403 i2c_tag_t ic;
206 int rv; 404 int rv;
207 bool indirect_config; 405 bool indirect_config;
208 406
209 aprint_naive("\n"); 407 aprint_naive("\n");
210 aprint_normal(": I2C bus\n"); 408 aprint_normal(": I2C bus\n");
211 409
 410 sc->sc_dev = self;
212 sc->sc_tag = iba->iba_tag; 411 sc->sc_tag = iba->iba_tag;
213 sc->sc_type = iba->iba_type; 412 sc->sc_type = iba->iba_type;
214 ic = sc->sc_tag; 413 ic = sc->sc_tag;
215 ic->ic_devname = device_xname(self); 414 ic->ic_devname = device_xname(self);
216 415
217 LIST_INIT(&(sc->sc_tag->ic_list)); 416 LIST_INIT(&(sc->sc_tag->ic_list));
218 LIST_INIT(&(sc->sc_tag->ic_proc_list)); 417 LIST_INIT(&(sc->sc_tag->ic_proc_list));
219 418
220 rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL, 419 rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
221 iic_smbus_intr_thread, ic, &ic->ic_intr_thread, 420 iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
222 "%s", ic->ic_devname); 421 "%s", ic->ic_devname);
223 if (rv) 422 if (rv)
224 aprint_error_dev(self, "unable to create intr thread\n"); 423 aprint_error_dev(self, "unable to create intr thread\n");
225 424
226 if (!pmf_device_register(self, NULL, NULL)) 425 if (!pmf_device_register(self, NULL, NULL))
227 aprint_error_dev(self, "couldn't establish power handler\n"); 426 aprint_error_dev(self, "couldn't establish power handler\n");
228 427
229 if (iba->iba_child_devices) { 428 if (iba->iba_child_devices) {
230 child_devices = iba->iba_child_devices; 429 child_devices = iba->iba_child_devices;
231 indirect_config = false; 430 indirect_config = false;
232 } else { 431 } else {
233 props = device_properties(parent); 432 props = device_properties(parent);
234 if (!prop_dictionary_get_bool(props, "i2c-indirect-config", 433 if (!prop_dictionary_get_bool(props, "i2c-indirect-config",
235 &indirect_config)) 434 &indirect_config))
236 indirect_config = true; 435 indirect_config = true;
237 child_devices = prop_dictionary_get(props, "i2c-child-devices"); 436 child_devices = prop_dictionary_get(props, "i2c-child-devices");
238 } 437 }
239 438
240 if (child_devices) { 439 if (child_devices) {
241 unsigned int i, count; 440 unsigned int i, count;
242 prop_dictionary_t dev; 441 prop_dictionary_t dev;
243 prop_data_t cdata; 442 prop_data_t cdata;
244 uint32_t addr, size; 443 uint32_t addr, size;
245 uint64_t cookie; 444 uint64_t cookie;
246 const char *name; 445 const char *name;
247 struct i2c_attach_args ia; 446 struct i2c_attach_args ia;
248 int loc[IICCF_NLOCS]; 447 int loc[IICCF_NLOCS];
249 448
250 memset(loc, 0, sizeof loc); 449 memset(loc, 0, sizeof loc);
251 count = prop_array_count(child_devices); 450 count = prop_array_count(child_devices);
252 for (i = 0; i < count; i++) { 451 for (i = 0; i < count; i++) {
253 dev = prop_array_get(child_devices, i); 452 dev = prop_array_get(child_devices, i);
254 if (!dev) continue; 453 if (!dev) continue;
255 if (!prop_dictionary_get_cstring_nocopy( 454 if (!prop_dictionary_get_cstring_nocopy(
256 dev, "name", &name)) 455 dev, "name", &name))
257 continue; 456 continue;
258 if (!prop_dictionary_get_uint32(dev, "addr", &addr)) 457 if (!prop_dictionary_get_uint32(dev, "addr", &addr))
259 continue; 458 continue;
260 if (!prop_dictionary_get_uint64(dev, "cookie", &cookie)) 459 if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
261 cookie = 0; 460 cookie = 0;
262 loc[IICCF_ADDR] = addr; 461 loc[IICCF_ADDR] = addr;
263 if (prop_dictionary_get_uint32(dev, "size", &size)) 462 if (prop_dictionary_get_uint32(dev, "size", &size))
264 loc[IICCF_SIZE] = size; 463 loc[IICCF_SIZE] = size;
265 else 464 else
266 size = loc[IICCF_SIZE] = IICCF_SIZE_DEFAULT; 465 size = loc[IICCF_SIZE] = IICCF_SIZE_DEFAULT;
267 466
268 memset(&ia, 0, sizeof ia); 467 memset(&ia, 0, sizeof ia);
269 ia.ia_addr = addr; 468 ia.ia_addr = addr;
270 ia.ia_type = sc->sc_type; 469 ia.ia_type = sc->sc_type;
271 ia.ia_tag = ic; 470 ia.ia_tag = ic;
272 ia.ia_name = name; 471 ia.ia_name = name;
273 ia.ia_cookie = cookie; 472 ia.ia_cookie = cookie;
274 ia.ia_size = size; 473 ia.ia_size = size;
275 ia.ia_prop = dev; 474 ia.ia_prop = dev;
276 475
277 buf = NULL; 476 buf = NULL;
278 cdata = prop_dictionary_get(dev, "compatible"); 477 cdata = prop_dictionary_get(dev, "compatible");
279 if (cdata) 478 if (cdata)
280 iic_fill_compat(&ia, 479 iic_fill_compat(&ia,
281 prop_data_data_nocopy(cdata), 480 prop_data_data_nocopy(cdata),
282 prop_data_size(cdata), &buf); 481 prop_data_size(cdata), &buf);
283 482
284 if (addr > I2C_MAX_ADDR) { 483 if (addr > I2C_MAX_ADDR) {
285 aprint_error_dev(self, 484 aprint_error_dev(self,
286 "WARNING: ignoring bad device address " 485 "WARNING: ignoring bad device address "
287 "@ 0x%02x\n", addr); 486 "@ 0x%02x\n", addr);
288 } else if (sc->sc_devices[addr] == NULL) { 487 } else if (sc->sc_devices[addr] == NULL) {
289 sc->sc_devices[addr] = 488 sc->sc_devices[addr] =
290 config_found_sm_loc(self, "iic", loc, &ia, 489 config_found_sm_loc(self, "iic", loc, &ia,
291 iic_print_direct, NULL); 490 iic_print_direct, NULL);
292 } 491 }
293 492
294 if (ia.ia_compat) 493 if (ia.ia_compat)
295 free(ia.ia_compat, M_TEMP); 494 free(ia.ia_compat, M_TEMP);
296 if (buf) 495 if (buf)
297 free(buf, M_TEMP); 496 free(buf, M_TEMP);
298 } 497 }
299 } else if (indirect_config) { 498 } else if (indirect_config) {
300 /* 499 /*
301 * Attach all i2c devices described in the kernel 500 * Attach all i2c devices described in the kernel
302 * configuration file. 501 * configuration file.
303 */ 502 */
304 iic_rescan(self, "iic", NULL); 503 iic_rescan(self, "iic", NULL);
305 } 504 }
306} 505}
307 506
308static int 507static int
309iic_detach(device_t self, int flags) 508iic_detach(device_t self, int flags)
310{ 509{
311 struct iic_softc *sc = device_private(self); 510 struct iic_softc *sc = device_private(self);
312 i2c_tag_t ic = sc->sc_tag; 511 i2c_tag_t ic = sc->sc_tag;
313 int i, error; 512 int i, error;
314 void *hdl; 513 void *hdl;
315 514
316 for (i = 0; i <= I2C_MAX_ADDR; i++) { 515 for (i = 0; i <= I2C_MAX_ADDR; i++) {
317 if (sc->sc_devices[i]) { 516 if (sc->sc_devices[i]) {
318 error = config_detach(sc->sc_devices[i], flags); 517 error = config_detach(sc->sc_devices[i], flags);
319 if (error) 518 if (error)
320 return error; 519 return error;
321 } 520 }
322 } 521 }
323 522
324 if (ic->ic_running) { 523 if (ic->ic_running) {
325 ic->ic_running = 0; 524 ic->ic_running = 0;
326 wakeup(ic); 525 wakeup(ic);
327 kthread_join(ic->ic_intr_thread); 526 kthread_join(ic->ic_intr_thread);
328 } 527 }
329 528
330 if (!LIST_EMPTY(&ic->ic_list)) { 529 if (!LIST_EMPTY(&ic->ic_list)) {
331 device_printf(self, "WARNING: intr handler list not empty\n"); 530 device_printf(self, "WARNING: intr handler list not empty\n");
332 while (!LIST_EMPTY(&ic->ic_list)) { 531 while (!LIST_EMPTY(&ic->ic_list)) {
333 hdl = LIST_FIRST(&ic->ic_list); 532 hdl = LIST_FIRST(&ic->ic_list);
334 iic_smbus_intr_disestablish(ic, hdl); 533 iic_smbus_intr_disestablish(ic, hdl);
335 } 534 }
336 } 535 }
337 if (!LIST_EMPTY(&ic->ic_proc_list)) { 536 if (!LIST_EMPTY(&ic->ic_proc_list)) {
338 device_printf(self, "WARNING: proc handler list not empty\n"); 537 device_printf(self, "WARNING: proc handler list not empty\n");
339 while (!LIST_EMPTY(&ic->ic_proc_list)) { 538 while (!LIST_EMPTY(&ic->ic_proc_list)) {
340 hdl = LIST_FIRST(&ic->ic_proc_list); 539 hdl = LIST_FIRST(&ic->ic_proc_list);
341 iic_smbus_intr_disestablish_proc(ic, hdl); 540 iic_smbus_intr_disestablish_proc(ic, hdl);
342 } 541 }
343 } 542 }
344 543
345 pmf_device_deregister(self); 544 pmf_device_deregister(self);
346 545
347 return 0; 546 return 0;
348} 547}
349 548
350static void 549static void
351iic_smbus_intr_thread(void *aux) 550iic_smbus_intr_thread(void *aux)
352{ 551{
353 i2c_tag_t ic; 552 i2c_tag_t ic;
354 struct ic_intr_list *il; 553 struct ic_intr_list *il;
355 554
356 ic = (i2c_tag_t)aux; 555 ic = (i2c_tag_t)aux;
357 ic->ic_running = 1; 556 ic->ic_running = 1;
358 ic->ic_pending = 0; 557 ic->ic_pending = 0;
359 558
360 while (ic->ic_running) { 559 while (ic->ic_running) {
361 if (ic->ic_pending == 0) 560 if (ic->ic_pending == 0)
362 tsleep(ic, PZERO, "iicintr", hz); 561 tsleep(ic, PZERO, "iicintr", hz);
363 if (ic->ic_pending > 0) { 562 if (ic->ic_pending > 0) {
364 LIST_FOREACH(il, &(ic->ic_proc_list), il_next) { 563 LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
365 (*il->il_intr)(il->il_intrarg); 564 (*il->il_intr)(il->il_intrarg);
366 } 565 }
367 ic->ic_pending--; 566 ic->ic_pending--;
368 } 567 }
369 } 568 }
370 569
371 kthread_exit(0); 570 kthread_exit(0);
372} 571}
373 572
374void * 573void *
375iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg) 574iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
376{ 575{
377 struct ic_intr_list *il; 576 struct ic_intr_list *il;
378 577
379 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK); 578 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
380 if (il == NULL) 579 if (il == NULL)
381 return NULL; 580 return NULL;
382 581
383 il->il_intr = intr; 582 il->il_intr = intr;
384 il->il_intrarg = intrarg; 583 il->il_intrarg = intrarg;
385 584
386 LIST_INSERT_HEAD(&(ic->ic_list), il, il_next); 585 LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
387 586
388 return il; 587 return il;
389} 588}
390 589
391void 590void
392iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl) 591iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
393{ 592{
394 struct ic_intr_list *il; 593 struct ic_intr_list *il;
395 594
396 il = (struct ic_intr_list *)hdl; 595 il = (struct ic_intr_list *)hdl;
397 596
398 LIST_REMOVE(il, il_next); 597 LIST_REMOVE(il, il_next);
399 free(il, M_DEVBUF); 598 free(il, M_DEVBUF);
400 599
401 return; 600 return;
402} 601}
403 602
404void * 603void *
405iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg) 604iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
406{ 605{
407 struct ic_intr_list *il; 606 struct ic_intr_list *il;
408 607
409 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK); 608 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
410 if (il == NULL) 609 if (il == NULL)
411 return NULL; 610 return NULL;
412 611
413 il->il_intr = intr; 612 il->il_intr = intr;
414 il->il_intrarg = intrarg; 613 il->il_intrarg = intrarg;
415 614
416 LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next); 615 LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
417 616
418 return il; 617 return il;
419} 618}
420 619
421void 620void
422iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl) 621iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
423{ 622{
424 struct ic_intr_list *il; 623 struct ic_intr_list *il;
425 624
426 il = (struct ic_intr_list *)hdl; 625 il = (struct ic_intr_list *)hdl;
427 626
428 LIST_REMOVE(il, il_next); 627 LIST_REMOVE(il, il_next);
429 free(il, M_DEVBUF); 628 free(il, M_DEVBUF);
430 629
431 return; 630 return;
432} 631}
433 632
434int 633int
435iic_smbus_intr(i2c_tag_t ic) 634iic_smbus_intr(i2c_tag_t ic)
436{ 635{
437 struct ic_intr_list *il; 636 struct ic_intr_list *il;
438 637
439 LIST_FOREACH(il, &(ic->ic_list), il_next) { 638 LIST_FOREACH(il, &(ic->ic_list), il_next) {
440 (*il->il_intr)(il->il_intrarg); 639 (*il->il_intr)(il->il_intrarg);
441 } 640 }
442 641
443 ic->ic_pending++; 642 ic->ic_pending++;
444 wakeup(ic); 643 wakeup(ic);
445 644
446 return 1; 645 return 1;
447} 646}
448 647
449static void 648static void
450iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len, 649iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
451 char **buffer) 650 char **buffer)
452{ 651{
453 int count, i; 652 int count, i;
454 const char *c, *start, **ptr; 653 const char *c, *start, **ptr;
455 654
456 *buffer = NULL; 655 *buffer = NULL;
457 for (i = count = 0, c = compat; i < len; i++, c++) 656 for (i = count = 0, c = compat; i < len; i++, c++)
458 if (*c == 0) 657 if (*c == 0)
459 count++; 658 count++;
460 count += 2; 659 count += 2;
461 ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK); 660 ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
462 if (!ptr) return; 661 if (!ptr) return;
463 662
464 for (i = count = 0, start = c = compat; i < len; i++, c++) { 663 for (i = count = 0, start = c = compat; i < len; i++, c++) {
465 if (*c == 0) { 664 if (*c == 0) {
466 ptr[count++] = start; 665 ptr[count++] = start;
467 start = c+1; 666 start = c+1;
468 } 667 }
469 } 668 }
470 if (start < compat+len) { 669 if (start < compat+len) {
471 /* last string not 0 terminated */ 670 /* last string not 0 terminated */
472 size_t l = c-start; 671 size_t l = c-start;
473 *buffer = malloc(l+1, M_TEMP, M_WAITOK); 672 *buffer = malloc(l+1, M_TEMP, M_WAITOK);
474 memcpy(*buffer, start, l); 673 memcpy(*buffer, start, l);
475 (*buffer)[l] = 0; 674 (*buffer)[l] = 0;
476 ptr[count++] = *buffer; 675 ptr[count++] = *buffer;
477 } 676 }
478 ptr[count] = NULL; 677 ptr[count] = NULL;
479 678
480 ia->ia_compat = ptr; 679 ia->ia_compat = ptr;
481 ia->ia_ncompat = count; 680 ia->ia_ncompat = count;
482} 681}
483 682
484int 683int
485iic_compat_match(struct i2c_attach_args *ia, const char ** compats) 684iic_compat_match(struct i2c_attach_args *ia, const char ** compats)
486{ 685{
487 int i; 686 int i;
488 687
489 for (; compats && *compats; compats++) { 688 for (; compats && *compats; compats++) {
490 for (i = 0; i < ia->ia_ncompat; i++) { 689 for (i = 0; i < ia->ia_ncompat; i++) {
491 if (strcmp(*compats, ia->ia_compat[i]) == 0) 690 if (strcmp(*compats, ia->ia_compat[i]) == 0)
492 return 1; 691 return 1;
493 } 692 }
494 } 693 }
495 return 0; 694 return 0;
496} 695}
497 696
498static int 697static int
499iic_open(dev_t dev, int flag, int fmt, lwp_t *l) 698iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
500{ 699{
501 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev)); 700 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
502 701
503 mutex_enter(&iic_mtx); 702 mutex_enter(&iic_mtx);
504 if (sc == NULL) { 703 if (sc == NULL) {
505 mutex_exit(&iic_mtx); 704 mutex_exit(&iic_mtx);
506 return ENXIO; 705 return ENXIO;
507 } 706 }
508 iic_refcnt++; 707 iic_refcnt++;
509 mutex_exit(&iic_mtx); 708 mutex_exit(&iic_mtx);
510 709
511 return 0; 710 return 0;
512} 711}
513 712
514static int 713static int
515iic_close(dev_t dev, int flag, int fmt, lwp_t *l) 714iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
516{ 715{
517 716
518 mutex_enter(&iic_mtx); 717 mutex_enter(&iic_mtx);
519 iic_refcnt--; 718 iic_refcnt--;
520 mutex_exit(&iic_mtx); 719 mutex_exit(&iic_mtx);
521 720
522 return 0; 721 return 0;
523} 722}
524 723
525static int 724static int
526iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag) 725iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
527{ 726{
528 i2c_tag_t ic = sc->sc_tag; 727 i2c_tag_t ic = sc->sc_tag;
529 uint8_t buf[I2C_EXEC_MAX_BUFLEN]; 728 uint8_t buf[I2C_EXEC_MAX_BUFLEN];
530 void *cmd = NULL; 729 void *cmd = NULL;
531 int error; 730 int error;
532 731
533 /* Validate parameters */ 732 /* Validate parameters */
534 if (iie->iie_addr > I2C_MAX_ADDR) 733 if (iie->iie_addr > I2C_MAX_ADDR)
535 return EINVAL; 734 return EINVAL;
536 if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN || 735 if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
537 iie->iie_buflen > I2C_EXEC_MAX_BUFLEN) 736 iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
538 return EINVAL; 737 return EINVAL;
539 if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0) 738 if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
540 return EINVAL; 739 return EINVAL;
541 if (iie->iie_buf != NULL && iie->iie_buflen == 0) 740 if (iie->iie_buf != NULL && iie->iie_buflen == 0)
542 return EINVAL; 741 return EINVAL;
543 if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0) 742 if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
544 return EBADF; 743 return EBADF;
545 744
546#if 0 745#if 0
547 /* Disallow userspace access to devices that have drivers attached. */ 746 /* Disallow userspace access to devices that have drivers attached. */
548 if (sc->sc_devices[iie->iie_addr] != NULL) 747 if (sc->sc_devices[iie->iie_addr] != NULL)
549 return EBUSY; 748 return EBUSY;
550#endif 749#endif
551 750
552 if (iie->iie_cmd != NULL) { 751 if (iie->iie_cmd != NULL) {
553 cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP); 752 cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
554 error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen); 753 error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
555 if (error) 754 if (error)
556 goto out; 755 goto out;
557 } 756 }
558 757
559 if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) { 758 if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
560 error = copyin(iie->iie_buf, buf, iie->iie_buflen); 759 error = copyin(iie->iie_buf, buf, iie->iie_buflen);
561 if (error) 760 if (error)
562 goto out; 761 goto out;
563 } 762 }
564 763
565 iic_acquire_bus(ic, 0); 764 iic_acquire_bus(ic, 0);
566 error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen, 765 error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
567 buf, iie->iie_buflen, 0); 766 buf, iie->iie_buflen, 0);
568 iic_release_bus(ic, 0); 767 iic_release_bus(ic, 0);
569 768
570 /* 769 /*
571 * Some drivers return error codes on failure, and others return -1. 770 * Some drivers return error codes on failure, and others return -1.
572 */ 771 */
573 if (error < 0) 772 if (error < 0)
574 error = EIO; 773 error = EIO;
575 774
576out: 775out:
577 if (cmd) 776 if (cmd)
578 kmem_free(cmd, iie->iie_cmdlen); 777 kmem_free(cmd, iie->iie_cmdlen);
579 778
580 if (error) 779 if (error)
581 return error; 780 return error;
582 781
583 if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op)) 782 if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
584 error = copyout(buf, iie->iie_buf, iie->iie_buflen); 783 error = copyout(buf, iie->iie_buf, iie->iie_buflen);
585 784
586 return error; 785 return error;
587} 786}
588 787
589static int 788static int
590iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l) 789iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
591{ 790{
592 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev)); 791 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
593 792
594 if (sc == NULL) 793 if (sc == NULL)
595 return ENXIO; 794 return ENXIO;
596 795
597 switch (cmd) { 796 switch (cmd) {
598 case I2C_IOCTL_EXEC: 797 case I2C_IOCTL_EXEC:
599 return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag); 798 return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
600 default: 799 default:
601 return ENODEV; 800 return ENODEV;
602 } 801 }
603} 802}
604 803
605 804
606CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc), 805CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc),
607 iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach); 806 iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach);
608 807
609MODULE(MODULE_CLASS_DRIVER, iic, "i2cexec,i2c_bitbang"); 808MODULE(MODULE_CLASS_DRIVER, iic, "i2cexec,i2c_bitbang");
610 809
611#ifdef _MODULE 810#ifdef _MODULE
612#include "ioconf.c" 811#include "ioconf.c"
613#endif 812#endif
614 813
615int 814int
616iic_init(void) 815iic_init(void)
617{ 816{
618 817
619 mutex_init(&iic_mtx, MUTEX_DEFAULT, IPL_NONE); 818 mutex_init(&iic_mtx, MUTEX_DEFAULT, IPL_NONE);
620 iic_refcnt = 0; 819 iic_refcnt = 0;
621 return 0; 820 return 0;
622} 821}
623 822
624static int 823static int
625iic_modcmd(modcmd_t cmd, void *opaque) 824iic_modcmd(modcmd_t cmd, void *opaque)
626{ 825{
627#ifdef _MODULE 826#ifdef _MODULE
628 int bmajor, cmajor; 827 int bmajor, cmajor;
629#endif 828#endif
630 int error; 829 int error;
631 830
632 error = 0; 831 error = 0;
633 switch (cmd) { 832 switch (cmd) {
634 case MODULE_CMD_INIT: 833 case MODULE_CMD_INIT:
635 RUN_ONCE(&iic_once, iic_init); 834 RUN_ONCE(&iic_once, iic_init);
636 835
637#ifdef _MODULE 836#ifdef _MODULE
638 mutex_enter(&iic_mtx); 837 mutex_enter(&iic_mtx);
639 bmajor = cmajor = -1; 838 bmajor = cmajor = -1;
640 error = devsw_attach("iic", NULL, &bmajor, 839 error = devsw_attach("iic", NULL, &bmajor,
641 &iic_cdevsw, &cmajor); 840 &iic_cdevsw, &cmajor);
642 if (error != 0) { 841 if (error != 0) {
643 mutex_exit(&iic_mtx); 842 mutex_exit(&iic_mtx);
644 break; 843 break;
645 } 844 }
646 error = config_init_component(cfdriver_ioconf_iic, 845 error = config_init_component(cfdriver_ioconf_iic,
647 cfattach_ioconf_iic, cfdata_ioconf_iic); 846 cfattach_ioconf_iic, cfdata_ioconf_iic);
648 if (error) { 847 if (error) {
649 aprint_error("%s: unable to init component\n", 848 aprint_error("%s: unable to init component\n",
650 iic_cd.cd_name); 849 iic_cd.cd_name);
651 (void)devsw_detach(NULL, &iic_cdevsw); 850 (void)devsw_detach(NULL, &iic_cdevsw);
652 } 851 }
653 mutex_exit(&iic_mtx); 852 mutex_exit(&iic_mtx);
654#endif 853#endif
655 break; 854 break;
656 case MODULE_CMD_FINI: 855 case MODULE_CMD_FINI:
657 mutex_enter(&iic_mtx); 856 mutex_enter(&iic_mtx);
658 if (iic_refcnt != 0) { 857 if (iic_refcnt != 0) {
659 mutex_exit(&iic_mtx); 858 mutex_exit(&iic_mtx);
660 return EBUSY; 859 return EBUSY;
661 } 860 }
662#ifdef _MODULE 861#ifdef _MODULE
663 error = config_fini_component(cfdriver_ioconf_iic, 862 error = config_fini_component(cfdriver_ioconf_iic,
664 cfattach_ioconf_iic, cfdata_ioconf_iic); 863 cfattach_ioconf_iic, cfdata_ioconf_iic);
665 if (error != 0) { 864 if (error != 0) {
666 mutex_exit(&iic_mtx); 865 mutex_exit(&iic_mtx);
667 break; 866 break;
668 } 867 }
669 error = devsw_detach(NULL, &iic_cdevsw); 868 error = devsw_detach(NULL, &iic_cdevsw);
670 if (error != 0) 869 if (error != 0)
671 config_init_component(cfdriver_ioconf_iic, 870 config_init_component(cfdriver_ioconf_iic,
672 cfattach_ioconf_iic, cfdata_ioconf_iic); 871 cfattach_ioconf_iic, cfdata_ioconf_iic);
673#endif 872#endif
674 mutex_exit(&iic_mtx); 873 mutex_exit(&iic_mtx);
675 break; 874 break;
676 default: 875 default:
677 error = ENOTTY; 876 error = ENOTTY;
678 } 877 }
679 return error; 878 return error;
680} 879}

cvs diff -r1.12 -r1.13 src/sys/dev/i2c/i2cvar.h (switch to unified diff)

--- src/sys/dev/i2c/i2cvar.h 2018/06/07 05:56:18 1.12
+++ src/sys/dev/i2c/i2cvar.h 2018/06/07 13:30:49 1.13
@@ -1,198 +1,229 @@ @@ -1,198 +1,229 @@
1/* $NetBSD: i2cvar.h,v 1.12 2018/06/07 05:56:18 thorpej Exp $ */ 1/* $NetBSD: i2cvar.h,v 1.13 2018/06/07 13:30:49 thorpej Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wasabi Systems, Inc. 4 * Copyright (c) 2003 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Steve C. Woodford and Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Steve C. Woodford and Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 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 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#ifndef _DEV_I2C_I2CVAR_H_ 38#ifndef _DEV_I2C_I2CVAR_H_
39#define _DEV_I2C_I2CVAR_H_ 39#define _DEV_I2C_I2CVAR_H_
40 40
41#include <dev/i2c/i2c_io.h> 41#include <dev/i2c/i2c_io.h>
42#include <prop/proplib.h> 42#include <prop/proplib.h>
43 43
44/* Flags passed to i2c routines. */ 44/* Flags passed to i2c routines. */
45#define I2C_F_WRITE 0x00 /* new transfer is a write */ 45#define I2C_F_WRITE 0x00 /* new transfer is a write */
46#define I2C_F_READ 0x01 /* new transfer is a read */ 46#define I2C_F_READ 0x01 /* new transfer is a read */
47#define I2C_F_LAST 0x02 /* last byte of read */ 47#define I2C_F_LAST 0x02 /* last byte of read */
48#define I2C_F_STOP 0x04 /* send stop after byte */ 48#define I2C_F_STOP 0x04 /* send stop after byte */
49#define I2C_F_POLL 0x08 /* poll, don't sleep */ 49#define I2C_F_POLL 0x08 /* poll, don't sleep */
50#define I2C_F_PEC 0x10 /* smbus packet error checking */ 50#define I2C_F_PEC 0x10 /* smbus packet error checking */
51 51
 52/* i2c bus instance properties */
 53#define I2C_PROP_INDIRECT_PROBE_STRATEGY \
 54 "i2c-indirect-probe-strategy"
 55#define I2C_PROBE_STRATEGY_QUICK_WRITE \
 56 "smbus-quick-write"
 57#define I2C_PROBE_STRATEGY_RECEIVE_BYTE \
 58 "smbus-receive-byte"
 59#define I2C_PROBE_STRATEGY_NONE \
 60 "none"
 61
 62#define I2C_PROP_INDIRECT_DEVICE_WHITELIST \
 63 "i2c-indirect-device-whitelist"
 64 /* value is a prop_array of prop_strings */
 65
52struct ic_intr_list { 66struct ic_intr_list {
53 LIST_ENTRY(ic_intr_list) il_next; 67 LIST_ENTRY(ic_intr_list) il_next;
54 int (*il_intr)(void *); 68 int (*il_intr)(void *);
55 void *il_intrarg; 69 void *il_intrarg;
56}; 70};
57 71
58/* 72/*
59 * This structure provides the interface between the i2c framework 73 * This structure provides the interface between the i2c framework
60 * and the underlying i2c controller. 74 * and the underlying i2c controller.
61 * 75 *
62 * Note that this structure is designed specifically to allow us 76 * Note that this structure is designed specifically to allow us
63 * to either use the autoconfiguration framework or not. This 77 * to either use the autoconfiguration framework or not. This
64 * allows a driver for a board with a private i2c bus use generic 78 * allows a driver for a board with a private i2c bus use generic
65 * i2c client drivers for chips that might be on that board. 79 * i2c client drivers for chips that might be on that board.
66 */ 80 */
67typedef struct i2c_controller { 81typedef struct i2c_controller {
68 void *ic_cookie; /* controller private */ 82 void *ic_cookie; /* controller private */
69 83
70 /* 84 /*
71 * These provide synchronization in the presence of 85 * These provide synchronization in the presence of
72 * multiple users of the i2c bus. When a device 86 * multiple users of the i2c bus. When a device
73 * driver wishes to perform transfers on the i2c 87 * driver wishes to perform transfers on the i2c
74 * bus, the driver should acquire the bus. When 88 * bus, the driver should acquire the bus. When
75 * the driver is finished, it should release the 89 * the driver is finished, it should release the
76 * bus. 90 * bus.
77 * 91 *
78 * This is provided by the back-end since a single 92 * This is provided by the back-end since a single
79 * controller may present e.g. i2c and smbus views 93 * controller may present e.g. i2c and smbus views
80 * of the same set of i2c wires. 94 * of the same set of i2c wires.
81 */ 95 */
82 int (*ic_acquire_bus)(void *, int); 96 int (*ic_acquire_bus)(void *, int);
83 void (*ic_release_bus)(void *, int); 97 void (*ic_release_bus)(void *, int);
84 98
85 /* 99 /*
86 * The preferred API for clients of the i2c interface 100 * The preferred API for clients of the i2c interface
87 * is the scripted API. This handles i2c controllers 101 * is the scripted API. This handles i2c controllers
88 * that do not provide raw access to the i2c signals. 102 * that do not provide raw access to the i2c signals.
89 */ 103 */
90 int (*ic_exec)(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 104 int (*ic_exec)(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
91 void *, size_t, int); 105 void *, size_t, int);
92 106
93 int (*ic_send_start)(void *, int); 107 int (*ic_send_start)(void *, int);
94 int (*ic_send_stop)(void *, int); 108 int (*ic_send_stop)(void *, int);
95 int (*ic_initiate_xfer)(void *, i2c_addr_t, int); 109 int (*ic_initiate_xfer)(void *, i2c_addr_t, int);
96 int (*ic_read_byte)(void *, uint8_t *, int); 110 int (*ic_read_byte)(void *, uint8_t *, int);
97 int (*ic_write_byte)(void *, uint8_t, int); 111 int (*ic_write_byte)(void *, uint8_t, int);
98 112
99 LIST_HEAD(, ic_intr_list) ic_list; 113 LIST_HEAD(, ic_intr_list) ic_list;
100 LIST_HEAD(, ic_intr_list) ic_proc_list; 114 LIST_HEAD(, ic_intr_list) ic_proc_list;
101 volatile int ic_running; 115 volatile int ic_running;
102 volatile int ic_pending; 116 volatile int ic_pending;
103 struct lwp *ic_intr_thread; 117 struct lwp *ic_intr_thread;
104 const char *ic_devname; 118 const char *ic_devname;
105} *i2c_tag_t; 119} *i2c_tag_t;
106 120
107/* I2C bus types */ 121/* I2C bus types */
108#define I2C_TYPE_SMBUS 1 122#define I2C_TYPE_SMBUS 1
109 123
110/* Used to attach the i2c framework to the controller. */ 124/* Used to attach the i2c framework to the controller. */
111struct i2cbus_attach_args { 125struct i2cbus_attach_args {
112 i2c_tag_t iba_tag; /* the controller */ 126 i2c_tag_t iba_tag; /* the controller */
113 int iba_type; /* bus type */ 127 int iba_type; /* bus type */
114 prop_array_t iba_child_devices; /* child devices (direct config) */ 128 prop_array_t iba_child_devices; /* child devices (direct config) */
115}; 129};
116 130
117/* Used to attach devices on the i2c bus. */ 131/* Used to attach devices on the i2c bus. */
118struct i2c_attach_args { 132struct i2c_attach_args {
119 i2c_tag_t ia_tag; /* our controller */ 133 i2c_tag_t ia_tag; /* our controller */
120 i2c_addr_t ia_addr; /* address of device */ 134 i2c_addr_t ia_addr; /* address of device */
121 int ia_size; /* size (for EEPROMs) */ 135 int ia_size; /* size (for EEPROMs) */
122 int ia_type; /* bus type */ 136 int ia_type; /* bus type */
123 /* only set if using direct config */ 137 /* only set if using direct config */
124 const char * ia_name; /* name of the device */ 138 const char * ia_name; /* name of the device */
125 int ia_ncompat; /* number of pointers in the 139 int ia_ncompat; /* number of pointers in the
126 ia_compat array */ 140 ia_compat array */
127 const char ** ia_compat; /* chip names */ 141 const char ** ia_compat; /* chip names */
128 prop_dictionary_t ia_prop; /* dictionnary for this device */ 142 prop_dictionary_t ia_prop; /* dictionnary for this device */
129 /* 143 /*
130 * The following is of limited usefulness and should only be used 144 * The following is of limited usefulness and should only be used
131 * in rare cases where we really know what we are doing. Example: 145 * in rare cases where we really know what we are doing. Example:
132 * a machine dependent i2c driver (located in sys/arch/$arch/dev) 146 * a machine dependent i2c driver (located in sys/arch/$arch/dev)
133 * needing to access some firmware properties. 147 * needing to access some firmware properties.
134 * Depending on the firmware in use, an identifier for the device 148 * Depending on the firmware in use, an identifier for the device
135 * may be present. Example: on OpenFirmware machines the device 149 * may be present. Example: on OpenFirmware machines the device
136 * tree OF node - if available. This info is hard to transport 150 * tree OF node - if available. This info is hard to transport
137 * down to MD drivers through the MI i2c bus otherwise. 151 * down to MD drivers through the MI i2c bus otherwise.
138 *  152 *
139 * On ACPI platforms this is the ACPI_HANDLE of the device. 153 * On ACPI platforms this is the ACPI_HANDLE of the device.
140 */ 154 */
141 uintptr_t ia_cookie; /* OF node in openfirmware machines */ 155 uintptr_t ia_cookie; /* OF node in openfirmware machines */
142}; 156};
143 157
144/* 158/*
145 * API presented to i2c controllers. 159 * API presented to i2c controllers.
146 */ 160 */
147int iicbus_print(void *, const char *); 161int iicbus_print(void *, const char *);
148int iic_compat_match(struct i2c_attach_args*, const char **); 162int iic_compat_match(struct i2c_attach_args*, const char **);
149 163
 164/*
 165 * Constants to indicate the quality of a match made by a driver's
 166 * match routine, from lowest to higest:
 167 *
 168 * -- Address only; no other checks were made.
 169 *
 170 * -- Address + device probed and recognized.
 171 *
 172 * -- Direct-config match by "compatible" string.
 173 *
 174 * -- Direct-config match by specific driver name.
 175 */
 176#define I2C_MATCH_ADDRESS_ONLY 1
 177#define I2C_MATCH_ADDRESS_AND_PROBE 2
 178#define I2C_MATCH_DIRECT_COMPATIBLE 10
 179#define I2C_MATCH_DIRECT_SPECIFIC 50
 180
150#ifdef _I2C_PRIVATE 181#ifdef _I2C_PRIVATE
151/* 182/*
152 * Macros used internally by the i2c framework. 183 * Macros used internally by the i2c framework.
153 */ 184 */
154#define iic_send_start(ic, flags) \ 185#define iic_send_start(ic, flags) \
155 (*(ic)->ic_send_start)((ic)->ic_cookie, (flags)) 186 (*(ic)->ic_send_start)((ic)->ic_cookie, (flags))
156#define iic_send_stop(ic, flags) \ 187#define iic_send_stop(ic, flags) \
157 (*(ic)->ic_send_stop)((ic)->ic_cookie, (flags)) 188 (*(ic)->ic_send_stop)((ic)->ic_cookie, (flags))
158#define iic_initiate_xfer(ic, addr, flags) \ 189#define iic_initiate_xfer(ic, addr, flags) \
159 (*(ic)->ic_initiate_xfer)((ic)->ic_cookie, (addr), (flags)) 190 (*(ic)->ic_initiate_xfer)((ic)->ic_cookie, (addr), (flags))
160 191
161#define iic_read_byte(ic, bytep, flags) \ 192#define iic_read_byte(ic, bytep, flags) \
162 (*(ic)->ic_read_byte)((ic)->ic_cookie, (bytep), (flags)) 193 (*(ic)->ic_read_byte)((ic)->ic_cookie, (bytep), (flags))
163#define iic_write_byte(ic, byte, flags) \ 194#define iic_write_byte(ic, byte, flags) \
164 (*(ic)->ic_write_byte)((ic)->ic_cookie, (byte), (flags)) 195 (*(ic)->ic_write_byte)((ic)->ic_cookie, (byte), (flags))
165#endif /* _I2C_PRIVATE */ 196#endif /* _I2C_PRIVATE */
166 197
167/* 198/*
168 * Simplified API for clients of the i2c framework. Definitions 199 * Simplified API for clients of the i2c framework. Definitions
169 * in <dev/i2c/i2c_io.h>. 200 * in <dev/i2c/i2c_io.h>.
170 */ 201 */
171#define iic_acquire_bus(ic, flags) \ 202#define iic_acquire_bus(ic, flags) \
172 (*(ic)->ic_acquire_bus)((ic)->ic_cookie, (flags)) 203 (*(ic)->ic_acquire_bus)((ic)->ic_cookie, (flags))
173#define iic_release_bus(ic, flags) \ 204#define iic_release_bus(ic, flags) \
174 (*(ic)->ic_release_bus)((ic)->ic_cookie, (flags)) 205 (*(ic)->ic_release_bus)((ic)->ic_cookie, (flags))
175 206
176int iic_exec(i2c_tag_t, i2c_op_t, i2c_addr_t, const void *, 207int iic_exec(i2c_tag_t, i2c_op_t, i2c_addr_t, const void *,
177 size_t, void *, size_t, int); 208 size_t, void *, size_t, int);
178 209
179int iic_smbus_write_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t, int); 210int iic_smbus_write_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t, int);
180int iic_smbus_write_word(i2c_tag_t, i2c_addr_t, uint8_t, uint16_t, int); 211int iic_smbus_write_word(i2c_tag_t, i2c_addr_t, uint8_t, uint16_t, int);
181int iic_smbus_read_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *, int); 212int iic_smbus_read_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *, int);
182int iic_smbus_read_word(i2c_tag_t, i2c_addr_t, uint8_t, uint16_t *, int); 213int iic_smbus_read_word(i2c_tag_t, i2c_addr_t, uint8_t, uint16_t *, int);
183int iic_smbus_receive_byte(i2c_tag_t, i2c_addr_t, uint8_t *, int); 214int iic_smbus_receive_byte(i2c_tag_t, i2c_addr_t, uint8_t *, int);
184int iic_smbus_send_byte(i2c_tag_t, i2c_addr_t, uint8_t, int); 215int iic_smbus_send_byte(i2c_tag_t, i2c_addr_t, uint8_t, int);
185int iic_smbus_quick_read(i2c_tag_t, i2c_addr_t, int); 216int iic_smbus_quick_read(i2c_tag_t, i2c_addr_t, int);
186int iic_smbus_quick_write(i2c_tag_t, i2c_addr_t, int); 217int iic_smbus_quick_write(i2c_tag_t, i2c_addr_t, int);
187int iic_smbus_block_read(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *, 218int iic_smbus_block_read(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *,
188 size_t, int); 219 size_t, int);
189int iic_smbus_block_write(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *, 220int iic_smbus_block_write(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *,
190 size_t, int); 221 size_t, int);
191 222
192void * iic_smbus_intr_establish(i2c_tag_t, int (*)(void *), void *); 223void * iic_smbus_intr_establish(i2c_tag_t, int (*)(void *), void *);
193void * iic_smbus_intr_establish_proc(i2c_tag_t, int (*)(void *), void *); 224void * iic_smbus_intr_establish_proc(i2c_tag_t, int (*)(void *), void *);
194void iic_smbus_intr_disestablish(i2c_tag_t, void *); 225void iic_smbus_intr_disestablish(i2c_tag_t, void *);
195void iic_smbus_intr_disestablish_proc(i2c_tag_t, void *); 226void iic_smbus_intr_disestablish_proc(i2c_tag_t, void *);
196int iic_smbus_intr(i2c_tag_t); 227int iic_smbus_intr(i2c_tag_t);
197 228
198#endif /* _DEV_I2C_I2CVAR_H_ */ 229#endif /* _DEV_I2C_I2CVAR_H_ */