1 1.2 riastrad /* $NetBSD: ds2482ow.c,v 1.2 2024/11/06 15:49:36 riastradh Exp $ */ 2 1.1 brad 3 1.1 brad /* 4 1.1 brad * Copyright (c) 2024 Brad Spencer <brad (at) anduin.eldar.org> 5 1.1 brad * 6 1.1 brad * Permission to use, copy, modify, and distribute this software for any 7 1.1 brad * purpose with or without fee is hereby granted, provided that the above 8 1.1 brad * copyright notice and this permission notice appear in all copies. 9 1.1 brad * 10 1.1 brad * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 1.1 brad * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 1.1 brad * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 1.1 brad * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 1.1 brad * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 1.1 brad * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 1.1 brad * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 1.1 brad */ 18 1.1 brad 19 1.1 brad #include <sys/cdefs.h> 20 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: ds2482ow.c,v 1.2 2024/11/06 15:49:36 riastradh Exp $"); 21 1.1 brad 22 1.1 brad /* 23 1.2 riastrad * Driver for the DS2482-100 and DS2482-800 I2C to Onewire bridge 24 1.2 riastrad */ 25 1.1 brad 26 1.1 brad #include <sys/param.h> 27 1.2 riastrad 28 1.2 riastrad #include <sys/device.h> 29 1.1 brad #include <sys/kernel.h> 30 1.1 brad #include <sys/module.h> 31 1.2 riastrad #include <sys/mutex.h> 32 1.1 brad #include <sys/sysctl.h> 33 1.2 riastrad #include <sys/systm.h> 34 1.1 brad 35 1.2 riastrad #include <dev/i2c/ds2482owreg.h> 36 1.2 riastrad #include <dev/i2c/ds2482owvar.h> 37 1.1 brad #include <dev/i2c/i2cvar.h> 38 1.1 brad #include <dev/onewire/onewirevar.h> 39 1.1 brad 40 1.1 brad #define DS2482_ONEWIRE_SINGLE_BIT_READ 0xF7 /* Artifical */ 41 1.1 brad #define DS2482_ONEWIRE_SINGLE_BIT_WRITE 0xF8 /* Artifical */ 42 1.1 brad 43 1.1 brad static int ds2482_poke(i2c_tag_t, i2c_addr_t, bool); 44 1.1 brad static int ds2482_match(device_t, cfdata_t, void *); 45 1.1 brad static void ds2482_attach(device_t, device_t, void *); 46 1.1 brad static int ds2482_detach(device_t, int); 47 1.1 brad static int ds2482_verify_sysctl(SYSCTLFN_ARGS); 48 1.1 brad 49 1.1 brad static int ds2482_ow_reset(void *); 50 1.1 brad static int ds2482_ow_read_bit(void *); 51 1.1 brad static void ds2482_ow_write_bit(void *, int); 52 1.1 brad static int ds2482_ow_read_byte(void *); 53 1.1 brad static void ds2482_ow_write_byte(void *, int); 54 1.1 brad static int ds2482_ow_triplet(void *, int); 55 1.1 brad 56 1.1 brad #define DS2482_DEBUG 57 1.1 brad 58 1.1 brad #ifdef DS2482_DEBUG 59 1.2 riastrad #define DPRINTF(s, l, x) \ 60 1.2 riastrad do { \ 61 1.2 riastrad if (l <= s->sc_ds2482debug) \ 62 1.2 riastrad aprint_normal x; \ 63 1.2 riastrad } while (/*CONSTCOND*/0) 64 1.1 brad #else 65 1.2 riastrad #define DPRINTF(s, l, x) __nothing 66 1.1 brad #endif 67 1.1 brad 68 1.1 brad #ifdef DS2482_DEBUG 69 1.2 riastrad #define DPRINTF2(dl, l, x) \ 70 1.2 riastrad do { \ 71 1.2 riastrad if (l <= dl) \ 72 1.2 riastrad aprint_normal x; \ 73 1.2 riastrad } while (/*CONSTCOND*/0) 74 1.1 brad #else 75 1.2 riastrad #define DPRINTF2(dl, l, x) __nothing 76 1.1 brad #endif 77 1.1 brad 78 1.1 brad CFATTACH_DECL_NEW(ds2482ow, sizeof(struct ds2482ow_sc), 79 1.1 brad ds2482_match, ds2482_attach, ds2482_detach, NULL); 80 1.1 brad 81 1.1 brad #define DS2482_QUICK_DELAY 18 82 1.1 brad #define DS2482_SLOW_DELAY 35 83 1.1 brad 84 1.1 brad int 85 1.1 brad ds2482_verify_sysctl(SYSCTLFN_ARGS) 86 1.1 brad { 87 1.1 brad int error, t; 88 1.1 brad struct sysctlnode node; 89 1.1 brad 90 1.1 brad node = *rnode; 91 1.1 brad t = *(int *)rnode->sysctl_data; 92 1.1 brad node.sysctl_data = &t; 93 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 94 1.1 brad if (error || newp == NULL) 95 1.1 brad return error; 96 1.1 brad 97 1.1 brad if (t < 0) 98 1.1 brad return EINVAL; 99 1.1 brad 100 1.1 brad *(int *)rnode->sysctl_data = t; 101 1.1 brad 102 1.1 brad return 0; 103 1.1 brad } 104 1.1 brad 105 1.1 brad static int 106 1.1 brad ds2482_set_pullup(i2c_tag_t tag, i2c_addr_t addr, bool activepullup, 107 1.1 brad bool strongpullup, int debuglevel) 108 1.1 brad { 109 1.1 brad int error; 110 1.1 brad uint8_t cmd = DS2482_WRITE_CONFIG; 111 1.1 brad uint8_t pu = 0; 112 1.1 brad uint8_t pux; 113 1.1 brad 114 1.2 riastrad if (activepullup) 115 1.1 brad pu = pu | DS2482_CONFIG_APU; 116 1.2 riastrad if (strongpullup) 117 1.1 brad pu = pu | DS2482_CONFIG_SPU; 118 1.1 brad 119 1.2 riastrad /* 120 1.2 riastrad * The Write Config command wants the top bits of the config 121 1.2 riastrad * buffer to be the ones complement of the lower bits. 122 1.1 brad */ 123 1.1 brad 124 1.1 brad pux = ~(pu << 4); 125 1.1 brad pux = pux & 0xf0; 126 1.1 brad pu = pu | pux; 127 1.1 brad 128 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd, 1, &pu, 1, 129 1.2 riastrad 0); 130 1.2 riastrad DPRINTF2(debuglevel, 4, ("ds2482_set_pullup: pu: %02x; error: %x %d\n", 131 1.2 riastrad pu, error, error)); 132 1.1 brad 133 1.1 brad return error; 134 1.1 brad } 135 1.1 brad 136 1.1 brad static int 137 1.1 brad ds2482_wait_with_status(i2c_tag_t tag, i2c_addr_t addr, uint8_t *status, 138 1.1 brad unsigned int d, bool set_pointer, int debuglevel) 139 1.1 brad { 140 1.1 brad int error = 0; 141 1.1 brad uint8_t xcmd, xbuf; 142 1.1 brad 143 1.1 brad DPRINTF2(debuglevel, 5, ("ds2482_wait_with_status: start\n")); 144 1.1 brad 145 1.1 brad xcmd = DS2482_SET_READ_POINTER; 146 1.1 brad xbuf = DS2482_REGISTER_STATUS; 147 1.2 riastrad if (set_pointer) { 148 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 149 1.2 riastrad &xbuf, 1, 0); 150 1.2 riastrad } 151 1.2 riastrad if (!error) { 152 1.2 riastrad error = iic_exec(tag, I2C_OP_READ, addr, NULL, 0, status, 1, 153 1.2 riastrad 0); 154 1.2 riastrad if ((*status & DS2482_STATUS_1WB) && !error) { 155 1.1 brad do { 156 1.1 brad delay(d); 157 1.2 riastrad error = iic_exec(tag, I2C_OP_READ, addr, 158 1.2 riastrad NULL, 0, status, 1, 0); 159 1.2 riastrad } while ((*status & DS2482_STATUS_1WB) && !error); 160 1.1 brad } 161 1.1 brad } 162 1.1 brad 163 1.2 riastrad DPRINTF2(debuglevel, 5, 164 1.2 riastrad ("ds2482_wait_with_status: end ; status: %02x %d ; error: %x %d\n", 165 1.2 riastrad *status, *status, error, error)); 166 1.1 brad 167 1.1 brad return error; 168 1.1 brad } 169 1.1 brad 170 1.1 brad static int 171 1.1 brad ds2482_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t *cmd, 172 1.1 brad uint8_t *cmdarg, uint8_t *obuf, size_t obuflen, bool activepullup, 173 1.1 brad bool strongpullup, int debuglevel) 174 1.1 brad { 175 1.1 brad int error; 176 1.1 brad uint8_t xcmd; 177 1.1 brad uint8_t xbuf; 178 1.1 brad 179 1.1 brad switch (*cmd) { 180 1.2 riastrad /* 181 1.2 riastrad * The datasheet says that none of these are effected 182 1.2 riastrad * by what sort of pullup is set and only the Write 183 1.2 riastrad * Config command needs to happen when idle. 184 1.1 brad */ 185 1.1 brad case DS2482_SET_READ_POINTER: 186 1.1 brad case DS2482_WRITE_CONFIG: 187 1.1 brad case DS2482_SELECT_CHANNEL: 188 1.1 brad KASSERT(cmdarg != NULL); 189 1.1 brad 190 1.1 brad error = 0; 191 1.2 riastrad if (*cmd == DS2482_WRITE_CONFIG) { 192 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 193 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/true, 194 1.2 riastrad debuglevel); 195 1.2 riastrad } 196 1.2 riastrad if (!error) { 197 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, 198 1.2 riastrad cmd, 1, cmdarg, 1, 0); 199 1.2 riastrad } 200 1.2 riastrad DPRINTF2(debuglevel, 4, 201 1.2 riastrad ("ds2482_cmd: cmd: %02x ; error: %x %d\n", 202 1.2 riastrad *cmd, error, error)); 203 1.1 brad break; 204 1.1 brad 205 1.1 brad case DS2482_DEVICE_RESET: 206 1.1 brad case DS2482_ONEWIRE_RESET: 207 1.2 riastrad /* 208 1.2 riastrad * Device reset resets everything, including pullup 209 1.2 riastrad * configuration settings, but that doesn't matter as 210 1.2 riastrad * we will always set the config before doing anything 211 1.2 riastrad * that actions on the 1-Wire bus. 212 1.1 brad * 213 1.2 riastrad * The data sheet warns about using the strong pull up 214 1.2 riastrad * feature with a 1-Wire reset, so we will simply not 215 1.2 riastrad * allow that combination. 216 1.1 brad * 217 1.2 riastrad * The data sheet does not mention if the 1-Wire reset 218 1.2 riastrad * effects just a single channel all channels. It 219 1.2 riastrad * seems likely that it is the currently active 220 1.2 riastrad * channel, and the driver works on that assumption. 221 1.2 riastrad */ 222 1.1 brad error = 0; 223 1.1 brad if (*cmd == DS2482_ONEWIRE_RESET) { 224 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 225 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/true, 226 1.2 riastrad debuglevel); 227 1.2 riastrad if (!error) { 228 1.2 riastrad error = ds2482_set_pullup(tag, addr, 229 1.2 riastrad activepullup, /*strongpullup*/false, 230 1.2 riastrad debuglevel); 231 1.2 riastrad } 232 1.2 riastrad } 233 1.2 riastrad if (!error) { 234 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, 235 1.2 riastrad cmd, 1, NULL, 0, 0); 236 1.1 brad } 237 1.2 riastrad DPRINTF2(debuglevel, 4, 238 1.2 riastrad ("ds2482_cmd: cmd: %02x ; error: %x %d\n", 239 1.2 riastrad *cmd, error, error)); 240 1.1 brad if (*cmd == DS2482_DEVICE_RESET) 241 1.1 brad delay(1); 242 1.1 brad if (*cmd == DS2482_ONEWIRE_RESET) 243 1.1 brad delay(1300); 244 1.1 brad break; 245 1.1 brad 246 1.1 brad case DS2482_ONEWIRE_SINGLE_BIT_WRITE: 247 1.1 brad KASSERT(cmdarg != NULL); 248 1.1 brad 249 1.2 riastrad DPRINTF2(debuglevel, 4, 250 1.2 riastrad ("ds2482_cmd: DS2482_ONEWIRE_SINGLE_BIT_WRITE:" 251 1.2 riastrad " cmdarg: %02x %d\n", *cmdarg, *cmdarg)); 252 1.1 brad 253 1.1 brad xcmd = DS2482_SET_READ_POINTER; 254 1.1 brad xbuf = DS2482_REGISTER_STATUS; 255 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 256 1.2 riastrad &xbuf, 1, 0); 257 1.2 riastrad if (!error) { 258 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 259 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/false, 260 1.2 riastrad debuglevel); 261 1.2 riastrad } 262 1.2 riastrad if (!error) { 263 1.1 brad xcmd = DS2482_ONEWIRE_SINGLE_BIT; 264 1.1 brad xbuf = DS2482_ONEWIRE_BIT_ZERO; 265 1.1 brad if (*cmdarg & 0x01) 266 1.1 brad xbuf = DS2482_ONEWIRE_BIT_ONE; 267 1.2 riastrad error = ds2482_set_pullup(tag, addr, 268 1.2 riastrad activepullup, strongpullup, debuglevel); 269 1.2 riastrad if (!error) { 270 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE, addr, 271 1.2 riastrad &xcmd, 1, &xbuf, 1, 0); 272 1.2 riastrad } 273 1.2 riastrad if (!error) { 274 1.1 brad xbuf = 0xff; 275 1.2 riastrad error = ds2482_wait_with_status(tag, addr, 276 1.2 riastrad &xbuf, DS2482_SLOW_DELAY, 277 1.2 riastrad /*set_pointer*/false, debuglevel); 278 1.1 brad } 279 1.1 brad } 280 1.1 brad break; 281 1.1 brad 282 1.1 brad case DS2482_ONEWIRE_SINGLE_BIT_READ: 283 1.1 brad KASSERT(obuf != NULL); 284 1.1 brad KASSERT(obuflen == 1); 285 1.1 brad 286 1.2 riastrad DPRINTF2(debuglevel, 4, 287 1.2 riastrad ("ds2482_cmd: DS2482_ONEWIRE_SINGLE_BIT_READ\n")); 288 1.1 brad 289 1.1 brad xcmd = DS2482_SET_READ_POINTER; 290 1.1 brad xbuf = DS2482_REGISTER_STATUS; 291 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 292 1.2 riastrad &xbuf, 1, 0); 293 1.2 riastrad if (!error) { 294 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 295 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/false, 296 1.2 riastrad debuglevel); 297 1.2 riastrad } 298 1.2 riastrad if (!error) { 299 1.1 brad xcmd = DS2482_ONEWIRE_SINGLE_BIT; 300 1.1 brad xbuf = DS2482_ONEWIRE_BIT_ONE; 301 1.2 riastrad error = ds2482_set_pullup(tag, addr, 302 1.2 riastrad activepullup, strongpullup, debuglevel); 303 1.2 riastrad if (!error) { 304 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE, addr, 305 1.2 riastrad &xcmd, 1, &xbuf, 1, 0); 306 1.2 riastrad } 307 1.2 riastrad if (!error) { 308 1.1 brad xbuf = 0xff; 309 1.2 riastrad error = ds2482_wait_with_status(tag, addr, 310 1.2 riastrad &xbuf, DS2482_SLOW_DELAY, 311 1.2 riastrad /*set_pointer*/false, debuglevel); 312 1.2 riastrad if (!error) { 313 1.2 riastrad *obuf = (xbuf & DS2482_STATUS_SBR) >> 314 1.2 riastrad DS2482_STATUS_SBR_SHIFT; 315 1.1 brad } 316 1.1 brad } 317 1.1 brad } 318 1.1 brad break; 319 1.1 brad 320 1.1 brad case DS2482_ONEWIRE_WRITE_BYTE: 321 1.1 brad KASSERT(cmdarg != NULL); 322 1.1 brad 323 1.2 riastrad DPRINTF2(debuglevel, 4, 324 1.2 riastrad ("ds2482_cmd: DS2482_ONEWIRE_WRITE_BYTE:" 325 1.2 riastrad " cmdarg: %02x %d\n", *cmdarg, *cmdarg)); 326 1.1 brad 327 1.1 brad xcmd = DS2482_SET_READ_POINTER; 328 1.1 brad xbuf = DS2482_REGISTER_STATUS; 329 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 330 1.2 riastrad &xbuf, 1, 0); 331 1.2 riastrad if (!error) { 332 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 333 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/false, 334 1.2 riastrad debuglevel); 335 1.2 riastrad } 336 1.2 riastrad if (!error) { 337 1.2 riastrad error = ds2482_set_pullup(tag, addr, 338 1.2 riastrad activepullup, strongpullup, debuglevel); 339 1.2 riastrad if (!error) { 340 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE, addr, 341 1.2 riastrad cmd, 1, cmdarg, 1, 0); 342 1.2 riastrad } 343 1.2 riastrad if (!error) { 344 1.1 brad xbuf = 0xff; 345 1.2 riastrad error = ds2482_wait_with_status(tag, addr, 346 1.2 riastrad &xbuf, DS2482_SLOW_DELAY, 347 1.2 riastrad /*set_pointer*/false, debuglevel); 348 1.1 brad } 349 1.1 brad } 350 1.1 brad break; 351 1.1 brad 352 1.1 brad case DS2482_ONEWIRE_READ_BYTE: 353 1.1 brad KASSERT(obuf != NULL); 354 1.1 brad KASSERT(obuflen == 1); 355 1.1 brad 356 1.2 riastrad DPRINTF2(debuglevel, 4, 357 1.2 riastrad ("ds2482_cmd: DS2482_ONEWIRE_READ_BYTE\n")); 358 1.1 brad 359 1.1 brad xcmd = DS2482_SET_READ_POINTER; 360 1.1 brad xbuf = DS2482_REGISTER_STATUS; 361 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 362 1.2 riastrad &xbuf, 1, 0); 363 1.2 riastrad if (!error) { 364 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 365 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/false, 366 1.2 riastrad debuglevel); 367 1.2 riastrad } 368 1.2 riastrad if (!error) { 369 1.2 riastrad error = ds2482_set_pullup(tag, addr, 370 1.2 riastrad activepullup, strongpullup, debuglevel); 371 1.2 riastrad if (!error) { 372 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE, addr, 373 1.2 riastrad cmd, 1, NULL, 0, 0); 374 1.2 riastrad } 375 1.2 riastrad if (!error) { 376 1.1 brad xbuf = 0xff; 377 1.2 riastrad error = ds2482_wait_with_status(tag, addr, 378 1.2 riastrad &xbuf, DS2482_SLOW_DELAY, 379 1.2 riastrad /*set_pointer*/false, debuglevel); 380 1.2 riastrad if (!error) { 381 1.1 brad xcmd = DS2482_SET_READ_POINTER; 382 1.1 brad xbuf = DS2482_REGISTER_DATA; 383 1.2 riastrad error = iic_exec(tag, 384 1.2 riastrad I2C_OP_WRITE_WITH_STOP, addr, 385 1.2 riastrad &xcmd, 1, &xbuf, 1, 0); 386 1.2 riastrad if (!error) { 387 1.1 brad xbuf = 0xff; 388 1.2 riastrad error = iic_exec(tag, 389 1.2 riastrad I2C_OP_READ_WITH_STOP, 390 1.2 riastrad addr, NULL, 0, 391 1.2 riastrad &xbuf, 1, 0); 392 1.2 riastrad if (!error) { 393 1.1 brad *obuf = xbuf; 394 1.1 brad } 395 1.1 brad } 396 1.1 brad } 397 1.1 brad } 398 1.1 brad } 399 1.1 brad break; 400 1.1 brad 401 1.1 brad case DS2482_ONEWIRE_TRIPLET: 402 1.1 brad KASSERT(cmdarg != NULL); 403 1.1 brad KASSERT(obuf != NULL); 404 1.1 brad KASSERT(obuflen == 1); 405 1.1 brad 406 1.2 riastrad DPRINTF2(debuglevel, 4, 407 1.2 riastrad ("ds2482_cmd: DS2482_ONEWIRE_TRIPLET: cmdarg: %02x %d\n", 408 1.2 riastrad *cmdarg, *cmdarg)); 409 1.1 brad 410 1.1 brad xcmd = DS2482_SET_READ_POINTER; 411 1.1 brad xbuf = DS2482_REGISTER_STATUS; 412 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 413 1.2 riastrad &xbuf, 1, 0); 414 1.2 riastrad if (!error) { 415 1.2 riastrad error = ds2482_wait_with_status(tag, addr, &xbuf, 416 1.2 riastrad DS2482_QUICK_DELAY, /*set_pointer*/false, 417 1.2 riastrad debuglevel); 418 1.2 riastrad } 419 1.2 riastrad if (!error) { 420 1.1 brad xbuf = DS2482_TRIPLET_DIR_ZERO; 421 1.1 brad if (*cmdarg & 0x01) { 422 1.1 brad xbuf = DS2482_TRIPLET_DIR_ONE; 423 1.1 brad } 424 1.2 riastrad error = ds2482_set_pullup(tag, addr, 425 1.2 riastrad activepullup, strongpullup, debuglevel); 426 1.2 riastrad if (!error) { 427 1.2 riastrad error = iic_exec(tag, I2C_OP_WRITE, addr, 428 1.2 riastrad cmd, 1, &xbuf, 1, 0); 429 1.2 riastrad } 430 1.2 riastrad if (!error) { 431 1.1 brad xbuf = 0xff; 432 1.2 riastrad error = ds2482_wait_with_status(tag, addr, 433 1.2 riastrad &xbuf, DS2482_SLOW_DELAY, 434 1.2 riastrad /*set_pointer*/false, debuglevel); 435 1.2 riastrad if (!error) { 436 1.2 riastrad /* 437 1.2 riastrad * This is undocumented 438 1.2 riastrad * anywhere I could find, but 439 1.2 riastrad * what has to be returned is 440 1.2 riastrad * 0x01 is the triplet path was 441 1.2 riastrad * taken, 0x02 is the 442 1.2 riastrad * Not-triplet path was taken, 443 1.2 riastrad * and 0x00 is neither was 444 1.2 riastrad * taken. The DIR bit in the 445 1.2 riastrad * status of the DS2482 may 446 1.2 riastrad * help with this some, but 447 1.2 riastrad * what is below seems to work. 448 1.1 brad */ 449 1.1 brad *obuf = 0; 450 1.1 brad if (xbuf & DS2482_STATUS_TSB) { 451 1.1 brad *obuf = 0x01; 452 1.1 brad } else { 453 1.1 brad if (xbuf & DS2482_STATUS_SBR) { 454 1.1 brad *obuf = 0x02; 455 1.1 brad } 456 1.1 brad } 457 1.1 brad } 458 1.1 brad } 459 1.1 brad } 460 1.1 brad break; 461 1.1 brad 462 1.1 brad default: 463 1.1 brad error = EINVAL; 464 1.1 brad break; 465 1.1 brad } 466 1.1 brad 467 1.1 brad return error; 468 1.1 brad } 469 1.1 brad 470 1.1 brad static int 471 1.2 riastrad ds2482_cmdr(struct ds2482ow_sc *sc, uint8_t cmd, uint8_t cmdarg, 472 1.2 riastrad uint8_t *buf, size_t blen) 473 1.1 brad { 474 1.2 riastrad 475 1.1 brad DPRINTF(sc, 3, ("%s: ds2482_cmdr: cmd: %02x\n", 476 1.1 brad device_xname(sc->sc_dev), cmd)); 477 1.2 riastrad return ds2482_cmd(sc->sc_tag, sc->sc_addr, &cmd, &cmdarg, buf, blen, 478 1.2 riastrad sc->sc_activepullup, sc->sc_strongpullup, sc->sc_ds2482debug); 479 1.1 brad } 480 1.1 brad 481 1.1 brad static const uint8_t ds2482_channels[] = { 482 1.1 brad DS2482_CHANNEL_IO0, 483 1.1 brad DS2482_CHANNEL_IO1, 484 1.1 brad DS2482_CHANNEL_IO2, 485 1.1 brad DS2482_CHANNEL_IO3, 486 1.1 brad DS2482_CHANNEL_IO4, 487 1.1 brad DS2482_CHANNEL_IO5, 488 1.1 brad DS2482_CHANNEL_IO6, 489 1.1 brad DS2482_CHANNEL_IO7 490 1.1 brad }; 491 1.1 brad 492 1.1 brad static int 493 1.1 brad ds2482_set_channel(struct ds2482ow_sc *sc, int channel) 494 1.1 brad { 495 1.1 brad int error = 0; 496 1.1 brad 497 1.1 brad KASSERT(channel >= 0 && channel < DS2482_NUM_INSTANCES); 498 1.1 brad 499 1.2 riastrad if (sc->sc_is_800) { 500 1.2 riastrad error = ds2482_cmdr(sc, DS2482_SELECT_CHANNEL, 501 1.2 riastrad ds2482_channels[channel], NULL, 0); 502 1.2 riastrad } 503 1.1 brad 504 1.1 brad return error; 505 1.1 brad } 506 1.1 brad 507 1.1 brad static int 508 1.1 brad ds2482_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug) 509 1.1 brad { 510 1.1 brad uint8_t reg = DS2482_SET_READ_POINTER; 511 1.1 brad uint8_t rbuf = DS2482_REGISTER_STATUS; 512 1.1 brad uint8_t obuf; 513 1.1 brad int error; 514 1.1 brad 515 1.2 riastrad error = ds2482_cmd(tag, addr, ®, &rbuf, &obuf, 1, 516 1.2 riastrad /*activepullup*/false, /*strongpullup*/false, 0); 517 1.1 brad if (matchdebug) { 518 1.1 brad printf("poke X 1: %d\n", error); 519 1.1 brad } 520 1.1 brad return error; 521 1.1 brad } 522 1.1 brad 523 1.1 brad static int 524 1.1 brad ds2482_match(device_t parent, cfdata_t match, void *aux) 525 1.1 brad { 526 1.1 brad struct i2c_attach_args *ia = aux; 527 1.1 brad int error, match_result; 528 1.1 brad const bool matchdebug = false; 529 1.1 brad 530 1.1 brad if (iic_use_direct_match(ia, match, NULL, &match_result)) 531 1.1 brad return match_result; 532 1.1 brad 533 1.1 brad /* indirect config - check for configured address */ 534 1.1 brad if (!(ia->ia_addr >= DS2482_LOWEST_ADDR && 535 1.1 brad ia->ia_addr <= DS2482_HIGHEST_ADDR)) 536 1.1 brad return 0; 537 1.1 brad 538 1.1 brad /* 539 1.1 brad * Check to see if something is really at this i2c address. This will 540 1.1 brad * keep phantom devices from appearing 541 1.1 brad */ 542 1.1 brad if (iic_acquire_bus(ia->ia_tag, 0) != 0) { 543 1.1 brad if (matchdebug) 544 1.1 brad printf("in match acquire bus failed\n"); 545 1.1 brad return 0; 546 1.1 brad } 547 1.1 brad 548 1.1 brad error = ds2482_poke(ia->ia_tag, ia->ia_addr, matchdebug); 549 1.1 brad iic_release_bus(ia->ia_tag, 0); 550 1.1 brad 551 1.1 brad return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0; 552 1.1 brad } 553 1.1 brad 554 1.1 brad static void 555 1.1 brad ds2482_attach(device_t parent, device_t self, void *aux) 556 1.1 brad { 557 1.1 brad struct ds2482ow_sc *sc; 558 1.1 brad struct i2c_attach_args *ia; 559 1.1 brad int error, i, num_channels = 1; 560 1.1 brad struct onewirebus_attach_args oba; 561 1.1 brad const struct sysctlnode *cnode; 562 1.1 brad int sysctlroot_num, pullup_num; 563 1.1 brad 564 1.1 brad ia = aux; 565 1.1 brad sc = device_private(self); 566 1.1 brad 567 1.1 brad sc->sc_dev = self; 568 1.1 brad sc->sc_tag = ia->ia_tag; 569 1.1 brad sc->sc_addr = ia->ia_addr; 570 1.1 brad sc->sc_ds2482debug = 0; 571 1.1 brad sc->sc_activepullup = false; 572 1.1 brad sc->sc_strongpullup = false; 573 1.1 brad sc->sc_is_800 = false; 574 1.1 brad 575 1.1 brad aprint_normal("\n"); 576 1.1 brad 577 1.1 brad mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 578 1.1 brad 579 1.1 brad if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 580 1.1 brad 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 581 1.1 brad SYSCTL_DESCR("DS2482 controls"), NULL, 0, NULL, 0, CTL_HW, 582 1.1 brad CTL_CREATE, CTL_EOL)) != 0) 583 1.1 brad goto out; 584 1.1 brad 585 1.1 brad sysctlroot_num = cnode->sysctl_num; 586 1.1 brad 587 1.1 brad #ifdef DS2482_DEBUG 588 1.1 brad if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 589 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 590 1.1 brad SYSCTL_DESCR("Debug level"), ds2482_verify_sysctl, 0, 591 1.1 brad &sc->sc_ds2482debug, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 592 1.1 brad CTL_EOL)) != 0) 593 1.1 brad goto out; 594 1.1 brad #endif 595 1.1 brad 596 1.1 brad if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 597 1.1 brad 0, CTLTYPE_NODE, "pullup", 598 1.1 brad SYSCTL_DESCR("Pullup controls"), NULL, 0, NULL, 0, CTL_HW, 599 1.1 brad sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 600 1.1 brad goto out; 601 1.1 brad 602 1.1 brad pullup_num = cnode->sysctl_num; 603 1.1 brad 604 1.1 brad if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 605 1.1 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "active", 606 1.1 brad SYSCTL_DESCR("Active pullup"), NULL, 0, &sc->sc_activepullup, 607 1.1 brad 0, CTL_HW, sysctlroot_num, pullup_num, CTL_CREATE, CTL_EOL)) != 0) 608 1.1 brad goto out; 609 1.1 brad 610 1.1 brad if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 611 1.1 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "strong", 612 1.1 brad SYSCTL_DESCR("Strong pullup"), NULL, 0, &sc->sc_strongpullup, 613 1.1 brad 0, CTL_HW, sysctlroot_num, pullup_num, CTL_CREATE, CTL_EOL)) != 0) 614 1.1 brad goto out; 615 1.1 brad 616 1.1 brad error = iic_acquire_bus(sc->sc_tag, 0); 617 1.1 brad if (error) { 618 1.1 brad aprint_error_dev(self, "Could not acquire iic bus: %d\n", 619 1.1 brad error); 620 1.1 brad goto out; 621 1.1 brad } 622 1.1 brad 623 1.1 brad error = ds2482_cmdr(sc, DS2482_DEVICE_RESET, 0, NULL, 0); 624 1.1 brad if (error != 0) 625 1.1 brad aprint_error_dev(self, "Reset failed: %d\n", error); 626 1.1 brad 627 1.2 riastrad if (!error) { 628 1.1 brad int xerror; 629 1.2 riastrad xerror = ds2482_cmdr(sc, DS2482_SELECT_CHANNEL, 630 1.2 riastrad DS2482_CHANNEL_IO0, NULL, 0); 631 1.2 riastrad if (!xerror) 632 1.1 brad sc->sc_is_800 = true; 633 1.1 brad } 634 1.1 brad 635 1.1 brad iic_release_bus(sc->sc_tag, 0); 636 1.1 brad 637 1.1 brad if (error != 0) { 638 1.1 brad aprint_error_dev(self, "Unable to setup device\n"); 639 1.1 brad goto out; 640 1.1 brad } 641 1.1 brad 642 1.2 riastrad if (sc->sc_is_800) { 643 1.1 brad num_channels = DS2482_NUM_INSTANCES; 644 1.1 brad } 645 1.1 brad 646 1.2 riastrad aprint_normal_dev(self, "Maxim DS2482-%s I2C to 1-Wire bridge," 647 1.2 riastrad " Channels available: %d\n", 648 1.2 riastrad sc->sc_is_800 ? "800" : "100", 649 1.1 brad num_channels); 650 1.1 brad 651 1.2 riastrad for (i = 0; i < num_channels; i++) { 652 1.1 brad sc->sc_instances[i].sc_i_channel = i; 653 1.1 brad sc->sc_instances[i].sc = sc; 654 1.2 riastrad sc->sc_instances[i].sc_i_ow_bus.bus_cookie = 655 1.2 riastrad &sc->sc_instances[i]; 656 1.1 brad sc->sc_instances[i].sc_i_ow_bus.bus_reset = ds2482_ow_reset; 657 1.2 riastrad sc->sc_instances[i].sc_i_ow_bus.bus_read_bit = 658 1.2 riastrad ds2482_ow_read_bit; 659 1.2 riastrad sc->sc_instances[i].sc_i_ow_bus.bus_write_bit = 660 1.2 riastrad ds2482_ow_write_bit; 661 1.2 riastrad sc->sc_instances[i].sc_i_ow_bus.bus_read_byte = 662 1.2 riastrad ds2482_ow_read_byte; 663 1.2 riastrad sc->sc_instances[i].sc_i_ow_bus.bus_write_byte = 664 1.2 riastrad ds2482_ow_write_byte; 665 1.2 riastrad sc->sc_instances[i].sc_i_ow_bus.bus_triplet = 666 1.2 riastrad ds2482_ow_triplet; 667 1.1 brad 668 1.1 brad memset(&oba, 0, sizeof(oba)); 669 1.1 brad oba.oba_bus = &sc->sc_instances[i].sc_i_ow_bus; 670 1.2 riastrad sc->sc_instances[i].sc_i_ow_dev = 671 1.2 riastrad config_found(self, &oba, onewirebus_print, CFARGS_NONE); 672 1.1 brad } 673 1.1 brad 674 1.1 brad out: 675 1.1 brad return; 676 1.1 brad } 677 1.1 brad 678 1.2 riastrad /* 679 1.2 riastrad * Hmmm... except in the case of reset, there really doesn't seem to 680 1.2 riastrad * be any way with the onewire(4) API to indicate an error condition. 681 1.2 riastrad */ 682 1.1 brad 683 1.1 brad static int 684 1.2 riastrad ds2482_generic_action(struct ds2482_instance *sci, uint8_t cmd, uint8_t cmdarg, 685 1.2 riastrad uint8_t *buf, size_t blen) 686 1.1 brad { 687 1.1 brad struct ds2482ow_sc *sc = sci->sc; 688 1.1 brad int rv; 689 1.1 brad 690 1.1 brad mutex_enter(&sc->sc_mutex); 691 1.1 brad rv = iic_acquire_bus(sc->sc_tag, 0); 692 1.1 brad if (!rv) { 693 1.1 brad rv = ds2482_set_channel(sc, sci->sc_i_channel); 694 1.1 brad if (!rv) 695 1.1 brad rv = ds2482_cmdr(sc, cmd, cmdarg, buf, blen); 696 1.1 brad } 697 1.1 brad iic_release_bus(sc->sc_tag, 0); 698 1.1 brad mutex_exit(&sc->sc_mutex); 699 1.1 brad 700 1.1 brad return rv; 701 1.1 brad } 702 1.1 brad 703 1.1 brad static int 704 1.1 brad ds2482_ow_reset(void *arg) 705 1.1 brad { 706 1.1 brad struct ds2482_instance *sci = arg; 707 1.1 brad struct ds2482ow_sc *sc = sci->sc; 708 1.1 brad int rv; 709 1.1 brad 710 1.1 brad rv = ds2482_generic_action(sci, DS2482_ONEWIRE_RESET, 0, NULL, 0); 711 1.1 brad 712 1.1 brad DPRINTF(sc, 3, ("%s: ds2482_ow_reset: channel: %d ; rv: %x %d\n", 713 1.1 brad device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv)); 714 1.1 brad 715 1.1 brad return rv; 716 1.1 brad } 717 1.1 brad 718 1.1 brad static int 719 1.1 brad ds2482_ow_read_bit(void *arg) 720 1.1 brad { 721 1.1 brad struct ds2482_instance *sci = arg; 722 1.1 brad struct ds2482ow_sc *sc = sci->sc; 723 1.1 brad int rv; 724 1.1 brad uint8_t buf = 0x55; 725 1.1 brad 726 1.2 riastrad rv = ds2482_generic_action(sci, DS2482_ONEWIRE_SINGLE_BIT_READ, 0, 727 1.2 riastrad &buf, 1); 728 1.1 brad 729 1.2 riastrad DPRINTF(sc, 3, 730 1.2 riastrad ("%s: ds2482_read_bit: channel: %d ; rv: %x %d ; buf: %02x %d\n", 731 1.1 brad device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv, buf, buf)); 732 1.1 brad 733 1.1 brad return (int)buf; 734 1.1 brad } 735 1.1 brad 736 1.1 brad static void 737 1.1 brad ds2482_ow_write_bit(void *arg, int value) 738 1.1 brad { 739 1.1 brad struct ds2482_instance *sci = arg; 740 1.1 brad struct ds2482ow_sc *sc = sci->sc; 741 1.1 brad int rv; 742 1.1 brad 743 1.2 riastrad rv = ds2482_generic_action(sci, DS2482_ONEWIRE_SINGLE_BIT_WRITE, 744 1.2 riastrad (uint8_t)value, NULL, 0); 745 1.1 brad 746 1.2 riastrad DPRINTF(sc, 3, ("%s: ds2482_write_bit: channel: %d ;" 747 1.2 riastrad " rv: %x %d ; value: %02x %d\n", 748 1.2 riastrad device_xname(sc->sc_dev), sci->sc_i_channel, 749 1.2 riastrad rv, rv, (uint8_t)value, (uint8_t)value)); 750 1.1 brad } 751 1.1 brad 752 1.1 brad static int 753 1.1 brad ds2482_ow_read_byte(void *arg) 754 1.1 brad { 755 1.1 brad struct ds2482_instance *sci = arg; 756 1.1 brad uint8_t buf = 0x55; 757 1.1 brad struct ds2482ow_sc *sc = sci->sc; 758 1.1 brad int rv; 759 1.1 brad 760 1.1 brad rv = ds2482_generic_action(sci, DS2482_ONEWIRE_READ_BYTE, 0, &buf, 1); 761 1.1 brad 762 1.2 riastrad DPRINTF(sc, 3, 763 1.2 riastrad ("%s: ds2482_read_byte: channel: %d ; rv: %x %d ; buf: %02x %d\n", 764 1.1 brad device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv, buf, buf)); 765 1.1 brad 766 1.1 brad return (int)buf; 767 1.1 brad } 768 1.1 brad 769 1.1 brad static void 770 1.1 brad ds2482_ow_write_byte(void *arg, int value) 771 1.1 brad { 772 1.1 brad struct ds2482_instance *sci = arg; 773 1.1 brad struct ds2482ow_sc *sc = sci->sc; 774 1.1 brad int rv; 775 1.1 brad 776 1.2 riastrad rv = ds2482_generic_action(sci, DS2482_ONEWIRE_WRITE_BYTE, 777 1.2 riastrad (uint8_t)value, NULL, 0); 778 1.1 brad 779 1.2 riastrad DPRINTF(sc, 3, ("%s: ds2482_write_byte: channel: %d ;" 780 1.2 riastrad " rv: %x %d ; value: %02x %d\n", 781 1.2 riastrad device_xname(sc->sc_dev), sci->sc_i_channel, 782 1.2 riastrad rv, rv, (uint8_t)value, (uint8_t)value)); 783 1.1 brad } 784 1.1 brad 785 1.1 brad static int 786 1.1 brad ds2482_ow_triplet(void *arg, int dir) 787 1.1 brad { 788 1.1 brad struct ds2482_instance *sci = arg; 789 1.1 brad uint8_t buf = 0x55; 790 1.1 brad struct ds2482ow_sc *sc = sci->sc; 791 1.1 brad int rv; 792 1.1 brad 793 1.2 riastrad rv = ds2482_generic_action(sci, DS2482_ONEWIRE_TRIPLET, (uint8_t)dir, 794 1.2 riastrad &buf, 1); 795 1.1 brad 796 1.2 riastrad DPRINTF(sc, 3, ("%s: ds2482_triplet: channel: %d ;" 797 1.2 riastrad " rv: %x %d ; dir: %x %d ; buf: %02x %d\n", 798 1.2 riastrad device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv, 799 1.2 riastrad dir, dir, (uint8_t)buf, (uint8_t)buf)); 800 1.1 brad 801 1.1 brad return (int)buf; 802 1.1 brad } 803 1.1 brad 804 1.1 brad static int 805 1.1 brad ds2482_detach(device_t self, int flags) 806 1.1 brad { 807 1.1 brad struct ds2482ow_sc *sc; 808 1.1 brad 809 1.1 brad sc = device_private(self); 810 1.1 brad 811 1.1 brad /* Remove the sysctl tree */ 812 1.1 brad sysctl_teardown(&sc->sc_ds2482log); 813 1.1 brad 814 1.1 brad /* Remove the mutex */ 815 1.1 brad mutex_destroy(&sc->sc_mutex); 816 1.1 brad 817 1.1 brad return 0; 818 1.1 brad } 819 1.1 brad 820 1.1 brad MODULE(MODULE_CLASS_DRIVER, ds2482ow, "iic,onewire"); 821 1.1 brad 822 1.1 brad #ifdef _MODULE 823 1.1 brad #include "ioconf.c" 824 1.1 brad #endif 825 1.1 brad 826 1.1 brad static int 827 1.1 brad ds2482ow_modcmd(modcmd_t cmd, void *opaque) 828 1.1 brad { 829 1.1 brad 830 1.1 brad switch (cmd) { 831 1.1 brad case MODULE_CMD_INIT: 832 1.1 brad #ifdef _MODULE 833 1.1 brad return config_init_component(cfdriver_ioconf_ds2482ow, 834 1.1 brad cfattach_ioconf_ds2482ow, cfdata_ioconf_ds2482ow); 835 1.1 brad #else 836 1.1 brad return 0; 837 1.1 brad #endif 838 1.1 brad case MODULE_CMD_FINI: 839 1.1 brad #ifdef _MODULE 840 1.1 brad return config_fini_component(cfdriver_ioconf_ds2482ow, 841 1.1 brad cfattach_ioconf_ds2482ow, cfdata_ioconf_ds2482ow); 842 1.1 brad #else 843 1.1 brad return 0; 844 1.1 brad #endif 845 1.1 brad default: 846 1.1 brad return ENOTTY; 847 1.1 brad } 848 1.1 brad } 849