| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
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 |
| @@ -30,53 +30,54 @@ | | | @@ -30,53 +30,54 @@ |
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 | |
69 | struct iic_softc { | | 69 | struct 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 | |
75 | static dev_type_open(iic_open); | | 76 | static dev_type_open(iic_open); |
76 | static dev_type_close(iic_close); | | 77 | static dev_type_close(iic_close); |
77 | static dev_type_ioctl(iic_ioctl); | | 78 | static dev_type_ioctl(iic_ioctl); |
78 | | | 79 | |
79 | int iic_init(void); | | 80 | int iic_init(void); |
80 | | | 81 | |
81 | kmutex_t iic_mtx; | | 82 | kmutex_t iic_mtx; |
82 | int iic_refcnt; | | 83 | int iic_refcnt; |
| @@ -117,61 +118,258 @@ iic_print_direct(void *aux, const char * | | | @@ -117,61 +118,258 @@ iic_print_direct(void *aux, const char * |
117 | } | | 118 | } |
118 | | | 119 | |
119 | static int | | 120 | static int |
120 | iic_print(void *aux, const char *pnp) | | 121 | iic_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 | |
| | | 131 | static bool |
| | | 132 | iic_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 | |
| | | 170 | static int |
| | | 171 | iic_probe_none(struct iic_softc *sc, |
| | | 172 | const struct i2c_attach_args *ia, int flags) |
| | | 173 | { |
| | | 174 | |
| | | 175 | return (0); |
| | | 176 | } |
| | | 177 | |
| | | 178 | static int |
| | | 179 | iic_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 | |
| | | 192 | static int |
| | | 193 | iic_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 | |
| | | 209 | static bool |
| | | 210 | iic_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 | |
130 | static int | | 244 | static int |
131 | iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) | | 245 | iic_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 | |
170 | static void | | 368 | static void |
171 | iic_child_detach(device_t parent, device_t child) | | 369 | iic_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) { |
| @@ -199,26 +397,27 @@ iic_attach(device_t parent, device_t sel | | | @@ -199,26 +397,27 @@ iic_attach(device_t parent, device_t sel |
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"); |