1 1.7 thorpej /* $NetBSD: umcpmio.c,v 1.7 2025/09/15 13:23:03 thorpej 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.7 thorpej __KERNEL_RCSID(0, "$NetBSD: umcpmio.c,v 1.7 2025/09/15 13:23:03 thorpej Exp $"); 21 1.1 brad 22 1.1 brad /* 23 1.2 riastrad * Driver for the Microchip MCP2221 / MCP2221A USB multi-io chip 24 1.2 riastrad */ 25 1.1 brad 26 1.1 brad #ifdef _KERNEL_OPT 27 1.1 brad #include "opt_usb.h" 28 1.1 brad #endif 29 1.1 brad 30 1.1 brad #include <sys/param.h> 31 1.2 riastrad #include <sys/types.h> 32 1.2 riastrad 33 1.1 brad #include <sys/conf.h> 34 1.2 riastrad #include <sys/device.h> 35 1.2 riastrad #include <sys/file.h> 36 1.2 riastrad #include <sys/gpio.h> 37 1.2 riastrad #include <sys/kauth.h> 38 1.1 brad #include <sys/kernel.h> 39 1.1 brad #include <sys/kmem.h> 40 1.2 riastrad #include <sys/lwp.h> 41 1.1 brad #include <sys/sysctl.h> 42 1.2 riastrad #include <sys/systm.h> 43 1.1 brad #include <sys/tty.h> 44 1.1 brad #include <sys/vnode.h> 45 1.1 brad 46 1.2 riastrad #include <dev/i2c/i2cvar.h> 47 1.2 riastrad 48 1.1 brad #include <dev/gpio/gpiovar.h> 49 1.1 brad 50 1.2 riastrad #include <dev/hid/hid.h> 51 1.1 brad 52 1.2 riastrad #include <dev/usb/uhidev.h> 53 1.1 brad #include <dev/usb/usb.h> 54 1.2 riastrad #include <dev/usb/usbdevs.h> 55 1.1 brad #include <dev/usb/usbdi.h> 56 1.1 brad #include <dev/usb/usbdi_util.h> 57 1.2 riastrad #include <dev/usb/usbhid.h> 58 1.1 brad 59 1.1 brad #include <dev/usb/umcpmio.h> 60 1.1 brad #include <dev/usb/umcpmio_hid_reports.h> 61 1.1 brad #include <dev/usb/umcpmio_io.h> 62 1.2 riastrad #include <dev/usb/umcpmio_subr.h> 63 1.1 brad 64 1.2 riastrad int umcpmio_send_report(struct umcpmio_softc *, uint8_t *, size_t, uint8_t *, 65 1.2 riastrad int); 66 1.1 brad 67 1.1 brad static const struct usb_devno umcpmio_devs[] = { 68 1.1 brad { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_MCP2221 }, 69 1.1 brad }; 70 1.1 brad #define umcpmio_lookup(v, p) usb_lookup(umcpmio_devs, v, p) 71 1.1 brad 72 1.1 brad static int umcpmio_match(device_t, cfdata_t, void *); 73 1.1 brad static void umcpmio_attach(device_t, device_t, void *); 74 1.1 brad static int umcpmio_detach(device_t, int); 75 1.1 brad static int umcpmio_activate(device_t, enum devact); 76 1.1 brad static int umcpmio_verify_sysctl(SYSCTLFN_ARGS); 77 1.1 brad static int umcpmio_verify_dac_sysctl(SYSCTLFN_ARGS); 78 1.1 brad static int umcpmio_verify_adc_sysctl(SYSCTLFN_ARGS); 79 1.1 brad static int umcpmio_verify_gpioclock_dc_sysctl(SYSCTLFN_ARGS); 80 1.1 brad static int umcpmio_verify_gpioclock_cd_sysctl(SYSCTLFN_ARGS); 81 1.1 brad 82 1.1 brad #define UMCPMIO_DEBUG 1 83 1.1 brad #ifdef UMCPMIO_DEBUG 84 1.2 riastrad #define DPRINTF(x) do { if (umcpmiodebug) printf x; } while (0) 85 1.2 riastrad #define DPRINTFN(n, x) do { if (umcpmiodebug > (n)) printf x; } while (0) 86 1.1 brad int umcpmiodebug = 0; 87 1.1 brad #else 88 1.1 brad #define DPRINTF(x) __nothing 89 1.2 riastrad #define DPRINTFN(n, x) __nothing 90 1.1 brad #endif 91 1.1 brad 92 1.1 brad CFATTACH_DECL_NEW(umcpmio, sizeof(struct umcpmio_softc), umcpmio_match, 93 1.1 brad umcpmio_attach, umcpmio_detach, umcpmio_activate); 94 1.1 brad 95 1.2 riastrad static void 96 1.2 riastrad WAITMS(int ms) 97 1.2 riastrad { 98 1.2 riastrad if (ms > 0) 99 1.2 riastrad delay(ms * 1000); 100 1.2 riastrad } 101 1.1 brad 102 1.1 brad extern struct cfdriver umcpmio_cd; 103 1.1 brad 104 1.1 brad static dev_type_open(umcpmio_dev_open); 105 1.1 brad static dev_type_read(umcpmio_dev_read); 106 1.1 brad static dev_type_write(umcpmio_dev_write); 107 1.1 brad static dev_type_close(umcpmio_dev_close); 108 1.1 brad static dev_type_ioctl(umcpmio_dev_ioctl); 109 1.2 riastrad 110 1.1 brad const struct cdevsw umcpmio_cdevsw = { 111 1.1 brad .d_open = umcpmio_dev_open, 112 1.1 brad .d_close = umcpmio_dev_close, 113 1.1 brad .d_read = umcpmio_dev_read, 114 1.1 brad .d_write = umcpmio_dev_write, 115 1.1 brad .d_ioctl = umcpmio_dev_ioctl, 116 1.1 brad .d_stop = nostop, 117 1.1 brad .d_tty = notty, 118 1.1 brad .d_poll = nopoll, 119 1.1 brad .d_mmap = nommap, 120 1.1 brad .d_kqfilter = nokqfilter, 121 1.1 brad .d_discard = nodiscard, 122 1.1 brad .d_flag = D_OTHER 123 1.1 brad }; 124 1.1 brad 125 1.1 brad static const char umcpmio_valid_vrefs[] = 126 1.1 brad "4.096V, 2.048V, 1.024V, OFF, VDD"; 127 1.1 brad 128 1.1 brad static const char umcpmio_valid_dcs[] = 129 1.1 brad "75%, 50%, 25%, 0%"; 130 1.1 brad 131 1.1 brad static const char umcpmio_valid_cds[] = 132 1.1 brad "375kHz, 750kHz, 1.5MHz, 3MHz, 6MHz, 12MHz, 24MHz"; 133 1.1 brad 134 1.1 brad static void 135 1.1 brad umcpmio_dump_buffer(bool enabled, uint8_t *buf, u_int len, const char *name) 136 1.1 brad { 137 1.2 riastrad int i; 138 1.2 riastrad 139 1.1 brad if (enabled) { 140 1.2 riastrad DPRINTF(("%s:", name)); 141 1.2 riastrad for (i = 0; i < len; i++) { 142 1.2 riastrad DPRINTF((" %02x", buf[i])); 143 1.1 brad } 144 1.1 brad DPRINTF(("\n")); 145 1.1 brad } 146 1.1 brad } 147 1.1 brad 148 1.2 riastrad /* 149 1.2 riastrad * Communication with the HID function requires sending a HID report 150 1.2 riastrad * request and then waiting for a response. 151 1.1 brad * 152 1.1 brad * The panic that occurs when trying to use the interrupt... i.e. 153 1.1 brad * attaching though this driver seems to be related to the fact that 154 1.1 brad * a spin lock is held and the USB stack wants to wait. 155 1.1 brad * 156 1.1 brad * The USB stack *IS* going to have to wait for the response from 157 1.1 brad * the device, somehow... 158 1.1 brad * 159 1.1 brad * It didn't seem possible to defer the uhidev_write to a thread. 160 1.1 brad * Attempts to yield() while spinning hard also did not work and 161 1.1 brad * not yield()ing didn't allow anything else to run. 162 1.1 brad * 163 1.1 brad */ 164 1.1 brad 165 1.1 brad /* 166 1.1 brad * This is the panic you will get: 167 1.1 brad * 168 1.2 riastrad * panic: kernel diagnostic assertion "ci->ci_mtx_count == -1" failed: file "../../../../kern/kern_synch.c", line 762 mi_switch: cpu0: ci_mtx_count (-2) != -1 (block with spin-mutex held) 169 1.2 riastrad */ 170 1.1 brad 171 1.1 brad static void 172 1.1 brad umcpmio_uhidev_intr(void *cookie, void *ibuf, u_int len) 173 1.1 brad { 174 1.1 brad struct umcpmio_softc *sc = cookie; 175 1.1 brad 176 1.1 brad if (sc->sc_dying) 177 1.1 brad return; 178 1.1 brad 179 1.2 riastrad DPRINTFN(30, ("umcpmio_uhidev_intr: len=%d\n", len)); 180 1.1 brad 181 1.1 brad mutex_enter(&sc->sc_res_mutex); 182 1.1 brad switch(len) { 183 1.1 brad case MCP2221_RES_BUFFER_SIZE: 184 1.1 brad if (sc->sc_res_buffer != NULL) { 185 1.2 riastrad memcpy(sc->sc_res_buffer, ibuf, 186 1.2 riastrad MCP2221_RES_BUFFER_SIZE); 187 1.1 brad sc->sc_res_ready = true; 188 1.1 brad cv_signal(&sc->sc_res_cv); 189 1.1 brad } else { 190 1.2 riastrad int d = umcpmiodebug; 191 1.2 riastrad device_printf(sc->sc_dev, 192 1.2 riastrad "umcpmio_uhidev_intr: NULL sc_res_buffer:" 193 1.2 riastrad " len=%d\n", 194 1.2 riastrad len); 195 1.2 riastrad umcpmiodebug = 20; 196 1.2 riastrad umcpmio_dump_buffer(true, (uint8_t *)ibuf, len, 197 1.2 riastrad "umcpmio_uhidev_intr: ibuf"); 198 1.2 riastrad umcpmiodebug = d; 199 1.1 brad } 200 1.1 brad 201 1.1 brad break; 202 1.1 brad default: 203 1.2 riastrad device_printf(sc->sc_dev, 204 1.2 riastrad "umcpmio_uhidev_intr: Unknown interrupt length: %d", 205 1.2 riastrad len); 206 1.1 brad break; 207 1.1 brad } 208 1.1 brad mutex_exit(&sc->sc_res_mutex); 209 1.1 brad } 210 1.1 brad 211 1.1 brad /* Send a HID report. This needs to be called with the action mutex held */ 212 1.1 brad 213 1.1 brad int 214 1.1 brad umcpmio_send_report(struct umcpmio_softc *sc, uint8_t *sendbuf, 215 1.1 brad size_t sendlen, uint8_t *resbuf, int timeout) 216 1.1 brad { 217 1.1 brad int err = 0; 218 1.2 riastrad int err_count = 0; 219 1.1 brad 220 1.1 brad if (sc->sc_dying) 221 1.1 brad return EIO; 222 1.1 brad 223 1.1 brad KASSERT(mutex_owned(&sc->sc_action_mutex)); 224 1.1 brad 225 1.1 brad if (sc->sc_res_buffer != NULL) { 226 1.2 riastrad device_printf(sc->sc_dev, 227 1.2 riastrad "umcpmio_send_report: sc->sc_res_buffer is not NULL\n"); 228 1.1 brad } 229 1.1 brad sc->sc_res_buffer = resbuf; 230 1.1 brad sc->sc_res_ready = false; 231 1.1 brad 232 1.1 brad err = uhidev_write(sc->sc_hdev, sendbuf, sendlen); 233 1.1 brad 234 1.1 brad if (err) { 235 1.2 riastrad DPRINTF(("umcpmio_send_report: uhidev_write errored with:" 236 1.2 riastrad " err=%d\n", err)); 237 1.1 brad goto out; 238 1.1 brad } 239 1.1 brad 240 1.2 riastrad DPRINTFN(30, ("umcpmio_send_report: about to wait on cv. err=%d\n", 241 1.2 riastrad err)); 242 1.1 brad 243 1.1 brad mutex_enter(&sc->sc_res_mutex); 244 1.1 brad while (!sc->sc_res_ready) { 245 1.2 riastrad DPRINTFN(20, ("umcpmio_send_report: LOOP for response." 246 1.2 riastrad " sc_res_ready=%d, err_count=%d, timeout=%d\n", 247 1.2 riastrad sc->sc_res_ready, err_count, mstohz(timeout))); 248 1.1 brad 249 1.2 riastrad err = cv_timedwait_sig(&sc->sc_res_cv, &sc->sc_res_mutex, 250 1.2 riastrad mstohz(timeout)); 251 1.1 brad 252 1.2 riastrad /* 253 1.2 riastrad * We are only going to allow this to loop on an error, 254 1.1 brad * any error at all, so many times. 255 1.1 brad */ 256 1.1 brad if (err) { 257 1.2 riastrad DPRINTF(("umcpmio_send_report:" 258 1.2 riastrad " cv_timedwait_sig reported an error:" 259 1.2 riastrad " err=%d, sc->sc_res_ready=%d\n", 260 1.2 riastrad err, sc->sc_res_ready)); 261 1.1 brad err_count++; 262 1.1 brad } 263 1.1 brad 264 1.2 riastrad /* 265 1.2 riastrad * The CV was interrupted, but the buffer is ready so, 266 1.2 riastrad * clear the error and break out. 267 1.1 brad */ 268 1.1 brad if ((err == ERESTART) && (sc->sc_res_ready)) { 269 1.2 riastrad DPRINTF(("umcpmio_send_report:" 270 1.2 riastrad " ERESTART and buffer is ready\n")); 271 1.1 brad err = 0; 272 1.1 brad break; 273 1.1 brad } 274 1.1 brad 275 1.2 riastrad /* 276 1.2 riastrad * Too many times though the loop, just break out. Turn 277 1.1 brad * a ERESTART (interruption) into a I/O error at this point. 278 1.1 brad */ 279 1.1 brad if (err_count > sc->sc_response_errcnt) { 280 1.2 riastrad DPRINTF(("umcpmio_send_report: err_count exceeded:" 281 1.2 riastrad " err=%d\n", err)); 282 1.1 brad if (err == ERESTART) 283 1.1 brad err = EIO; 284 1.1 brad break; 285 1.1 brad } 286 1.1 brad 287 1.1 brad /* This is a normal timeout, without interruption, try again */ 288 1.1 brad if (err == EWOULDBLOCK) { 289 1.2 riastrad DPRINTF(("umcpmio_send_report: EWOULDBLOCK:" 290 1.2 riastrad " err_count=%d\n", err_count)); 291 1.1 brad continue; 292 1.1 brad } 293 1.1 brad 294 1.2 riastrad /* 295 1.2 riastrad * The CV was interrupted and the buffer wasn't filled 296 1.2 riastrad * in, so try again 297 1.2 riastrad */ 298 1.1 brad if ((err == ERESTART) && (!sc->sc_res_ready)) { 299 1.2 riastrad DPRINTF(("umcpmio_send_report:" 300 1.2 riastrad " ERESTART and buffer is NOT ready." 301 1.2 riastrad " err_count=%d\n", err_count)); 302 1.1 brad continue; 303 1.1 brad } 304 1.1 brad } 305 1.1 brad 306 1.1 brad sc->sc_res_buffer = NULL; 307 1.1 brad sc->sc_res_ready = false; 308 1.1 brad mutex_exit(&sc->sc_res_mutex); 309 1.1 brad 310 1.1 brad /* Turn most errors into an I/O error */ 311 1.1 brad if (err && 312 1.1 brad err != ERESTART) 313 1.1 brad err = EIO; 314 1.1 brad 315 1.1 brad out: 316 1.1 brad return err; 317 1.1 brad } 318 1.1 brad 319 1.1 brad /* These are standard gpio reads and set calls */ 320 1.1 brad 321 1.1 brad static int 322 1.1 brad umcpmio_gpio_pin_read(void *arg, int pin) 323 1.1 brad { 324 1.1 brad struct umcpmio_softc *sc = arg; 325 1.1 brad int r = GPIO_PIN_LOW; 326 1.1 brad 327 1.1 brad r = umcpmio_get_gpio_value(sc, pin, true); 328 1.1 brad 329 1.2 riastrad return r; 330 1.1 brad } 331 1.1 brad 332 1.1 brad static void 333 1.1 brad umcpmio_gpio_pin_write(void *arg, int pin, int value) 334 1.1 brad { 335 1.1 brad struct umcpmio_softc *sc = arg; 336 1.1 brad 337 1.1 brad umcpmio_set_gpio_value_one(sc, pin, value, true); 338 1.1 brad } 339 1.1 brad 340 1.2 riastrad /* 341 1.2 riastrad * Internal function that does the dirty work of setting a gpio 342 1.1 brad * pin to its "type". 343 1.1 brad * 344 1.2 riastrad * There are really two ways to do some of this, one is to set the pin 345 1.2 riastrad * to input and output, or whatever, using SRAM calls, the other is to 346 1.2 riastrad * use the GPIO config calls to set input and output and SRAM for 347 1.2 riastrad * everything else. This just uses SRAM for everything. 348 1.1 brad */ 349 1.1 brad 350 1.1 brad static int 351 1.4 riastrad umcpmio_gpio_pin_ctlctl(void *arg, int pin, int flags) 352 1.1 brad { 353 1.1 brad struct umcpmio_softc *sc = arg; 354 1.1 brad struct mcp2221_set_sram_req set_sram_req; 355 1.1 brad struct mcp2221_set_sram_res set_sram_res; 356 1.1 brad struct mcp2221_get_sram_res current_sram_res; 357 1.1 brad struct mcp2221_get_gpio_cfg_res current_gpio_cfg_res; 358 1.1 brad int err = 0; 359 1.1 brad 360 1.1 brad if (sc->sc_dying) 361 1.1 brad return 0; 362 1.1 brad 363 1.4 riastrad KASSERT(mutex_owned(&sc->sc_action_mutex)); 364 1.1 brad 365 1.1 brad err = umcpmio_get_sram(sc, ¤t_sram_res, false); 366 1.1 brad if (err) 367 1.1 brad goto out; 368 1.1 brad 369 1.1 brad err = umcpmio_get_gpio_cfg(sc, ¤t_gpio_cfg_res, false); 370 1.1 brad if (err) 371 1.1 brad goto out; 372 1.1 brad 373 1.2 riastrad /* 374 1.2 riastrad * You can't just set one pin, you must set all of them, so copy the 375 1.1 brad * current settings for the pin we are not messing with. 376 1.1 brad * 377 1.1 brad * And, yes, of course, if the MCP-2210 is ever supported with this 378 1.1 brad * driver, this sort of unrolling will need to be turned into 379 1.1 brad * something different, but for now, just unroll as there are only 380 1.1 brad * 4 pins to care about. 381 1.1 brad * 382 1.1 brad */ 383 1.1 brad 384 1.1 brad memset(&set_sram_req, 0, MCP2221_REQ_BUFFER_SIZE); 385 1.1 brad switch (pin) { 386 1.1 brad case 0: 387 1.1 brad set_sram_req.gp1_settings = current_sram_res.gp1_settings; 388 1.1 brad set_sram_req.gp2_settings = current_sram_res.gp2_settings; 389 1.1 brad set_sram_req.gp3_settings = current_sram_res.gp3_settings; 390 1.1 brad break; 391 1.1 brad case 1: 392 1.1 brad set_sram_req.gp0_settings = current_sram_res.gp0_settings; 393 1.1 brad set_sram_req.gp2_settings = current_sram_res.gp2_settings; 394 1.1 brad set_sram_req.gp3_settings = current_sram_res.gp3_settings; 395 1.1 brad break; 396 1.1 brad case 2: 397 1.1 brad set_sram_req.gp0_settings = current_sram_res.gp0_settings; 398 1.1 brad set_sram_req.gp1_settings = current_sram_res.gp1_settings; 399 1.1 brad set_sram_req.gp3_settings = current_sram_res.gp3_settings; 400 1.1 brad break; 401 1.1 brad case 3: 402 1.1 brad set_sram_req.gp0_settings = current_sram_res.gp0_settings; 403 1.1 brad set_sram_req.gp1_settings = current_sram_res.gp1_settings; 404 1.1 brad set_sram_req.gp2_settings = current_sram_res.gp2_settings; 405 1.1 brad break; 406 1.1 brad } 407 1.1 brad umcpmio_set_gpio_designation_sram(&set_sram_req, pin, flags); 408 1.1 brad umcpmio_set_gpio_dir_sram(&set_sram_req, pin, flags); 409 1.1 brad 410 1.1 brad /* 411 1.2 riastrad * This part is unfortunate... if a pin is set to output, the 412 1.2 riastrad * value set on the pin is not mirrored by the chip into SRAM, 413 1.2 riastrad * but the chip will use the value from SRAM to set the value of 414 1.2 riastrad * the pin. What this means is that we have to learn the value 415 1.2 riastrad * from the GPIO config and make sure it is set properly when 416 1.2 riastrad * updating SRAM. 417 1.1 brad */ 418 1.1 brad 419 1.1 brad if (current_gpio_cfg_res.gp0_pin_dir == MCP2221_GPIO_CFG_DIR_OUTPUT) { 420 1.2 riastrad if (current_gpio_cfg_res.gp0_pin_value == 1) { 421 1.2 riastrad set_sram_req.gp0_settings |= 422 1.2 riastrad MCP2221_SRAM_GPIO_OUTPUT_HIGH; 423 1.2 riastrad } else { 424 1.2 riastrad set_sram_req.gp0_settings &= 425 1.2 riastrad ~MCP2221_SRAM_GPIO_OUTPUT_HIGH; 426 1.2 riastrad } 427 1.1 brad } 428 1.1 brad if (current_gpio_cfg_res.gp1_pin_dir == MCP2221_GPIO_CFG_DIR_OUTPUT) { 429 1.2 riastrad if (current_gpio_cfg_res.gp1_pin_value == 1) { 430 1.2 riastrad set_sram_req.gp1_settings |= 431 1.2 riastrad MCP2221_SRAM_GPIO_OUTPUT_HIGH; 432 1.2 riastrad } else { 433 1.2 riastrad set_sram_req.gp1_settings &= 434 1.2 riastrad ~MCP2221_SRAM_GPIO_OUTPUT_HIGH; 435 1.2 riastrad } 436 1.1 brad } 437 1.1 brad if (current_gpio_cfg_res.gp2_pin_dir == MCP2221_GPIO_CFG_DIR_OUTPUT) { 438 1.2 riastrad if (current_gpio_cfg_res.gp2_pin_value == 1) { 439 1.2 riastrad set_sram_req.gp2_settings |= 440 1.2 riastrad MCP2221_SRAM_GPIO_OUTPUT_HIGH; 441 1.2 riastrad } else { 442 1.2 riastrad set_sram_req.gp2_settings &= 443 1.2 riastrad ~MCP2221_SRAM_GPIO_OUTPUT_HIGH; 444 1.2 riastrad } 445 1.1 brad } 446 1.1 brad if (current_gpio_cfg_res.gp3_pin_dir == MCP2221_GPIO_CFG_DIR_OUTPUT) { 447 1.2 riastrad if (current_gpio_cfg_res.gp3_pin_value == 1) { 448 1.2 riastrad set_sram_req.gp3_settings |= 449 1.2 riastrad MCP2221_SRAM_GPIO_OUTPUT_HIGH; 450 1.2 riastrad } else { 451 1.2 riastrad set_sram_req.gp3_settings &= 452 1.2 riastrad ~MCP2221_SRAM_GPIO_OUTPUT_HIGH; 453 1.2 riastrad } 454 1.1 brad } 455 1.1 brad 456 1.1 brad err = umcpmio_put_sram(sc, &set_sram_req, &set_sram_res, false); 457 1.3 riastrad if (err) 458 1.3 riastrad goto out; 459 1.3 riastrad 460 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 461 1.3 riastrad (uint8_t *)&set_sram_res, MCP2221_RES_BUFFER_SIZE, 462 1.3 riastrad "umcpmio_gpio_pin_ctlctl set sram buffer copy"); 463 1.3 riastrad if (set_sram_res.cmd != MCP2221_CMD_SET_SRAM || 464 1.3 riastrad set_sram_res.completion != MCP2221_CMD_COMPLETE_OK) { 465 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_gpio_pin_ctlctl:" 466 1.3 riastrad " not the command desired, or error: %02x %02x\n", 467 1.3 riastrad set_sram_res.cmd, 468 1.3 riastrad set_sram_res.completion); 469 1.3 riastrad err = EIO; 470 1.3 riastrad goto out; 471 1.1 brad } 472 1.1 brad 473 1.3 riastrad sc->sc_gpio_pins[pin].pin_flags = flags; 474 1.3 riastrad err = 0; 475 1.3 riastrad 476 1.1 brad out: 477 1.1 brad return err; 478 1.1 brad } 479 1.1 brad 480 1.1 brad static void 481 1.1 brad umcpmio_gpio_pin_ctl(void *arg, int pin, int flags) 482 1.1 brad { 483 1.1 brad struct umcpmio_softc *sc = arg; 484 1.1 brad 485 1.1 brad if (sc->sc_dying) 486 1.1 brad return; 487 1.1 brad 488 1.4 riastrad mutex_enter(&sc->sc_action_mutex); 489 1.4 riastrad umcpmio_gpio_pin_ctlctl(sc, pin, flags); 490 1.4 riastrad mutex_exit(&sc->sc_action_mutex); 491 1.1 brad } 492 1.1 brad 493 1.1 brad /* 494 1.2 riastrad * XXX - 495 1.2 riastrad * 496 1.2 riastrad * Since testing of gpio interrupts wasn't possible, this part probably 497 1.2 riastrad * is not complete. At the very least, there is a scheduled callout 498 1.2 riastrad * that needs to exist to read the interrupt status. The chip does not 499 1.2 riastrad * send anything on its own when the interrupt happens. 500 1.1 brad */ 501 1.1 brad 502 1.1 brad static void * 503 1.1 brad umcpmio_gpio_intr_establish(void *vsc, int pin, int ipl, int irqmode, 504 1.1 brad int (*func)(void *), void *arg) 505 1.1 brad { 506 1.1 brad struct umcpmio_softc *sc = vsc; 507 1.1 brad struct umcpmio_irq *irq = &sc->sc_gpio_irqs[0]; 508 1.1 brad struct mcp2221_set_sram_req set_sram_req; 509 1.1 brad struct mcp2221_set_sram_res set_sram_res; 510 1.1 brad struct mcp2221_get_sram_res current_sram_res; 511 1.1 brad int err = 0; 512 1.1 brad 513 1.1 brad if (sc->sc_dying) 514 1.2 riastrad return NULL; 515 1.1 brad 516 1.1 brad irq->sc_gpio_irqfunc = func; 517 1.1 brad irq->sc_gpio_irqarg = arg; 518 1.1 brad 519 1.2 riastrad DPRINTF(("umcpmio_intr_establish: pin=%d, irqmode=%04x\n", 520 1.2 riastrad pin, irqmode)); 521 1.1 brad 522 1.1 brad mutex_enter(&sc->sc_action_mutex); 523 1.1 brad 524 1.1 brad err = umcpmio_get_sram(sc, ¤t_sram_res, false); 525 1.1 brad if (err) 526 1.1 brad goto out; 527 1.1 brad 528 1.1 brad memset(&set_sram_req, 0, MCP2221_REQ_BUFFER_SIZE); 529 1.1 brad set_sram_req.gp0_settings = current_sram_res.gp0_settings; 530 1.1 brad set_sram_req.gp2_settings = current_sram_res.gp2_settings; 531 1.1 brad set_sram_req.gp3_settings = current_sram_res.gp3_settings; 532 1.1 brad umcpmio_set_gpio_irq_sram(&set_sram_req, irqmode); 533 1.1 brad err = umcpmio_put_sram(sc, &set_sram_req, &set_sram_res, false); 534 1.3 riastrad if (err) { 535 1.2 riastrad device_printf(sc->sc_dev, "umcpmio_intr_establish:" 536 1.2 riastrad " set sram error: err=%d\n", 537 1.1 brad err); 538 1.3 riastrad goto out; 539 1.3 riastrad } 540 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 541 1.3 riastrad (uint8_t *)&set_sram_res, MCP2221_RES_BUFFER_SIZE, 542 1.3 riastrad "umcpmio_intr_establish set sram buffer copy"); 543 1.3 riastrad if (set_sram_res.cmd != MCP2221_CMD_SET_SRAM || 544 1.3 riastrad set_sram_res.completion != MCP2221_CMD_COMPLETE_OK) { 545 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_intr_establish:" 546 1.3 riastrad " not the command desired, or error: %02x %02x\n", 547 1.3 riastrad set_sram_res.cmd, 548 1.3 riastrad set_sram_res.completion); 549 1.3 riastrad goto out; 550 1.1 brad } 551 1.1 brad 552 1.3 riastrad sc->sc_gpio_pins[1].pin_flags = GPIO_PIN_ALT2; 553 1.3 riastrad 554 1.1 brad out: 555 1.1 brad mutex_exit(&sc->sc_action_mutex); 556 1.1 brad 557 1.2 riastrad return irq; 558 1.1 brad } 559 1.1 brad 560 1.1 brad static void 561 1.1 brad umcpmio_gpio_intr_disestablish(void *vsc, void *ih) 562 1.1 brad { 563 1.1 brad struct umcpmio_softc *sc = vsc; 564 1.1 brad struct mcp2221_set_sram_req set_sram_req; 565 1.1 brad struct mcp2221_set_sram_res set_sram_res; 566 1.1 brad struct mcp2221_get_sram_res current_sram_res; 567 1.1 brad int err = 0; 568 1.1 brad 569 1.1 brad if (sc->sc_dying) 570 1.1 brad return; 571 1.1 brad 572 1.1 brad DPRINTF(("umcpmio_intr_disestablish:\n")); 573 1.1 brad 574 1.1 brad mutex_enter(&sc->sc_action_mutex); 575 1.1 brad 576 1.1 brad err = umcpmio_get_sram(sc, ¤t_sram_res, false); 577 1.1 brad if (err) 578 1.1 brad goto out; 579 1.1 brad 580 1.1 brad memset(&set_sram_req, 0, MCP2221_REQ_BUFFER_SIZE); 581 1.1 brad set_sram_req.gp0_settings = current_sram_res.gp0_settings; 582 1.1 brad set_sram_req.gp2_settings = current_sram_res.gp2_settings; 583 1.1 brad set_sram_req.gp3_settings = current_sram_res.gp3_settings; 584 1.1 brad umcpmio_set_gpio_irq_sram(&set_sram_req, 0); 585 1.1 brad err = umcpmio_put_sram(sc, &set_sram_req, &set_sram_res, true); 586 1.3 riastrad if (err) { 587 1.2 riastrad device_printf(sc->sc_dev, "umcpmio_intr_disestablish:" 588 1.2 riastrad " set sram error: err=%d\n", 589 1.1 brad err); 590 1.3 riastrad goto out; 591 1.3 riastrad } 592 1.3 riastrad 593 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 594 1.3 riastrad (uint8_t *)&set_sram_res, MCP2221_RES_BUFFER_SIZE, 595 1.3 riastrad "umcpmio_intr_disestablish set sram buffer copy"); 596 1.3 riastrad if (set_sram_res.cmd == MCP2221_CMD_SET_SRAM && 597 1.3 riastrad set_sram_res.completion == MCP2221_CMD_COMPLETE_OK) { 598 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_intr_disestablish:" 599 1.3 riastrad " not the command desired, or error: %02x %02x\n", 600 1.3 riastrad set_sram_res.cmd, 601 1.3 riastrad set_sram_res.completion); 602 1.3 riastrad goto out; 603 1.1 brad } 604 1.3 riastrad 605 1.3 riastrad sc->sc_gpio_pins[1].pin_flags = GPIO_PIN_INPUT; 606 1.3 riastrad 607 1.1 brad out: 608 1.1 brad mutex_exit(&sc->sc_action_mutex); 609 1.1 brad } 610 1.1 brad 611 1.1 brad static bool 612 1.1 brad umcpmio_gpio_intrstr(void *vsc, int pin, int irqmode, char *buf, size_t buflen) 613 1.1 brad { 614 1.1 brad 615 1.1 brad if (pin < 0 || pin >= MCP2221_NPINS) { 616 1.2 riastrad DPRINTF(("umcpmio_gpio_intrstr:" 617 1.2 riastrad " pin %d less than zero or too big\n", 618 1.2 riastrad pin)); 619 1.2 riastrad return false; 620 1.1 brad } 621 1.1 brad 622 1.1 brad if (pin != 1) { 623 1.2 riastrad DPRINTF(("umcpmio_gpio_intrstr: pin %d was not 1\n", 624 1.2 riastrad pin)); 625 1.2 riastrad return false; 626 1.1 brad } 627 1.1 brad 628 1.1 brad snprintf(buf, buflen, "GPIO %d", pin); 629 1.1 brad 630 1.2 riastrad return true; 631 1.1 brad } 632 1.1 brad 633 1.1 brad /* Clear status of the I2C engine */ 634 1.1 brad 635 1.1 brad static int 636 1.1 brad umcpmio_i2c_clear(struct umcpmio_softc *sc, bool takemutex) 637 1.1 brad { 638 1.1 brad int err = 0; 639 1.1 brad struct mcp2221_status_req status_req; 640 1.1 brad struct mcp2221_status_res status_res; 641 1.1 brad 642 1.1 brad memset(&status_req, 0, MCP2221_REQ_BUFFER_SIZE); 643 1.1 brad status_req.cmd = MCP2221_CMD_STATUS; 644 1.1 brad status_req.cancel_transfer = MCP2221_I2C_DO_CANCEL; 645 1.1 brad 646 1.1 brad if (takemutex) 647 1.1 brad mutex_enter(&sc->sc_action_mutex); 648 1.2 riastrad err = umcpmio_send_report(sc, 649 1.2 riastrad (uint8_t *)&status_req, MCP2221_REQ_BUFFER_SIZE, 650 1.2 riastrad (uint8_t *)&status_res, sc->sc_cv_wait); 651 1.1 brad if (takemutex) 652 1.1 brad mutex_exit(&sc->sc_action_mutex); 653 1.3 riastrad if (err) { 654 1.2 riastrad device_printf(sc->sc_dev, "umcpmio_i2c_clear: request error:" 655 1.2 riastrad " err=%d\n", err); 656 1.1 brad err = EIO; 657 1.3 riastrad goto out; 658 1.3 riastrad } 659 1.3 riastrad 660 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 661 1.3 riastrad (uint8_t *)&status_res, MCP2221_RES_BUFFER_SIZE, 662 1.3 riastrad "umcpmio_i2c_clear buffer copy"); 663 1.3 riastrad 664 1.3 riastrad if (status_res.cmd != MCP2221_CMD_STATUS && 665 1.3 riastrad status_res.completion != MCP2221_CMD_COMPLETE_OK) { 666 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_i2c_clear:" 667 1.3 riastrad " cmd exec: not the command desired, or error:" 668 1.3 riastrad " %02x %02x\n", 669 1.3 riastrad status_res.cmd, 670 1.3 riastrad status_res.completion); 671 1.3 riastrad err = EIO; 672 1.3 riastrad goto out; 673 1.1 brad } 674 1.1 brad 675 1.3 riastrad umcpmio_dump_buffer(true, 676 1.3 riastrad (uint8_t *)&status_res, MCP2221_RES_BUFFER_SIZE, 677 1.3 riastrad "umcpmio_i2c_clear res buffer"); 678 1.3 riastrad 679 1.3 riastrad out: 680 1.2 riastrad return err; 681 1.1 brad } 682 1.1 brad 683 1.2 riastrad /* 684 1.2 riastrad * There isn't much required to acquire or release the I2C bus, but the man 685 1.1 brad * pages says these are needed 686 1.1 brad */ 687 1.1 brad 688 1.1 brad static int 689 1.1 brad umcpmio_acquire_bus(void *v, int flags) 690 1.1 brad { 691 1.2 riastrad return 0; 692 1.1 brad } 693 1.1 brad 694 1.1 brad static void 695 1.1 brad umcpmio_release_bus(void *v, int flags) 696 1.1 brad { 697 1.1 brad return; 698 1.1 brad } 699 1.1 brad 700 1.2 riastrad /* 701 1.2 riastrad * The I2C write and I2C read functions mostly use an algorithm that Adafruit 702 1.1 brad * came up with in their Python based driver. A lot of other people have used 703 1.1 brad * this same algorithm to good effect. If changes are made to the I2C read and 704 1.1 brad * write functions, it is HIGHLY advisable that a MCP2221 or MCP2221A be on 705 1.1 brad * hand to test them. 706 1.1 brad */ 707 1.1 brad 708 1.1 brad /* This is what is considered a fatal return from the engine. */ 709 1.1 brad 710 1.1 brad static bool 711 1.1 brad umcpmio_i2c_fatal(uint8_t state) 712 1.1 brad { 713 1.1 brad int r = false; 714 1.1 brad 715 1.1 brad if (state == MCP2221_ENGINE_ADDRNACK || 716 1.1 brad state == MCP2221_ENGINE_STARTTIMEOUT || 717 1.1 brad state == MCP2221_ENGINE_REPSTARTTIMEOUT || 718 1.1 brad state == MCP2221_ENGINE_STOPTIMEOUT || 719 1.1 brad state == MCP2221_ENGINE_READTIMEOUT || 720 1.1 brad state == MCP2221_ENGINE_WRITETIMEOUT || 721 1.1 brad state == MCP2221_ENGINE_ADDRTIMEOUT) 722 1.1 brad r = true; 723 1.2 riastrad return r; 724 1.1 brad } 725 1.1 brad 726 1.1 brad static int 727 1.1 brad umcpmio_i2c_write(struct umcpmio_softc *sc, i2c_op_t op, i2c_addr_t addr, 728 1.2 riastrad const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, 729 1.2 riastrad int flags) 730 1.1 brad { 731 1.1 brad struct mcp2221_i2c_req i2c_req; 732 1.1 brad struct mcp2221_i2c_res i2c_res; 733 1.1 brad struct mcp2221_status_res status_res; 734 1.1 brad int remaining; 735 1.1 brad int err = 0; 736 1.1 brad uint8_t cmd; 737 1.1 brad size_t totallen = 0; 738 1.1 brad int wretry = sc->sc_retry_busy_write; 739 1.1 brad int wsretry = sc->sc_retry_busy_write; 740 1.1 brad 741 1.1 brad err = umcpmio_get_status(sc, &status_res, true); 742 1.1 brad if (err) 743 1.1 brad goto out; 744 1.1 brad if (status_res.internal_i2c_state != 0) { 745 1.2 riastrad DPRINTF(("umcpmio_i2c_write: internal state not zero," 746 1.2 riastrad " clearing. internal_i2c_state=%02x\n", 747 1.2 riastrad status_res.internal_i2c_state)); 748 1.1 brad err = umcpmio_i2c_clear(sc, true); 749 1.1 brad } 750 1.1 brad if (err) 751 1.1 brad goto out; 752 1.1 brad 753 1.1 brad if (cmdbuf != NULL) 754 1.1 brad totallen += cmdlen; 755 1.1 brad if (databuf != NULL) 756 1.1 brad totallen += datalen; 757 1.1 brad 758 1.1 brad again: 759 1.1 brad memset(&i2c_req, 0, MCP2221_REQ_BUFFER_SIZE); 760 1.1 brad cmd = MCP2221_I2C_WRITE_DATA_NS; 761 1.1 brad if (I2C_OP_STOP_P(op)) 762 1.1 brad cmd = MCP2221_I2C_WRITE_DATA; 763 1.1 brad i2c_req.cmd = cmd; 764 1.1 brad i2c_req.lsblen = totallen; 765 1.1 brad i2c_req.msblen = 0; 766 1.1 brad i2c_req.slaveaddr = addr << 1; 767 1.1 brad 768 1.1 brad remaining = 0; 769 1.1 brad if (cmdbuf != NULL) { 770 1.1 brad memcpy(&i2c_req.data[0], cmdbuf, cmdlen); 771 1.1 brad remaining = cmdlen; 772 1.1 brad } 773 1.1 brad if (databuf != NULL) 774 1.1 brad memcpy(&i2c_req.data[remaining], databuf, datalen); 775 1.1 brad 776 1.2 riastrad DPRINTF(("umcpmio_i2c_write: I2C WRITE: cmd: %02x\n", cmd)); 777 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 778 1.2 riastrad (uint8_t *)&i2c_req, MCP2221_REQ_BUFFER_SIZE, 779 1.2 riastrad "umcpmio_i2c_write: write req buffer copy"); 780 1.1 brad 781 1.1 brad mutex_enter(&sc->sc_action_mutex); 782 1.2 riastrad err = umcpmio_send_report(sc, 783 1.2 riastrad (uint8_t *)&i2c_req, MCP2221_REQ_BUFFER_SIZE, 784 1.2 riastrad (uint8_t *)&i2c_res, sc->sc_cv_wait); 785 1.1 brad mutex_exit(&sc->sc_action_mutex); 786 1.3 riastrad if (err) { 787 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_i2c_write request error:" 788 1.3 riastrad " err=%d\n", err); 789 1.3 riastrad err = EIO; 790 1.3 riastrad goto out; 791 1.3 riastrad } 792 1.3 riastrad 793 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 794 1.3 riastrad (uint8_t *)&i2c_res, MCP2221_RES_BUFFER_SIZE, 795 1.3 riastrad "umcpmio_i2c_write: write res buffer copy"); 796 1.3 riastrad if (i2c_res.cmd == cmd && 797 1.3 riastrad i2c_res.completion == MCP2221_CMD_COMPLETE_OK) { 798 1.3 riastrad /* 799 1.3 riastrad * Adafruit does a read back of the status at 800 1.3 riastrad * this point. We choose not to do that. That 801 1.3 riastrad * is done later anyway, and it seemed to be 802 1.3 riastrad * redundent. 803 1.3 riastrad */ 804 1.3 riastrad } else if (i2c_res.cmd == cmd && 805 1.3 riastrad i2c_res.completion == MCP2221_I2C_ENGINE_BUSY) { 806 1.3 riastrad DPRINTF(("umcpmio_i2c_write:" 807 1.3 riastrad " I2C engine busy\n")); 808 1.3 riastrad 809 1.3 riastrad if (umcpmio_i2c_fatal(i2c_res.internal_i2c_state)) { 810 1.3 riastrad err = EIO; 811 1.3 riastrad goto out; 812 1.3 riastrad } 813 1.3 riastrad wretry--; 814 1.3 riastrad if (wretry > 0) { 815 1.3 riastrad WAITMS(sc->sc_busy_delay); 816 1.3 riastrad goto again; 817 1.1 brad } else { 818 1.3 riastrad err = EBUSY; 819 1.3 riastrad goto out; 820 1.1 brad } 821 1.1 brad } else { 822 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_i2c_write:" 823 1.3 riastrad " not the command desired, or error:" 824 1.3 riastrad " %02x %02x\n", 825 1.3 riastrad i2c_res.cmd, 826 1.3 riastrad i2c_res.completion); 827 1.1 brad err = EIO; 828 1.3 riastrad goto out; 829 1.1 brad } 830 1.1 brad 831 1.3 riastrad while (wsretry > 0) { 832 1.3 riastrad wsretry--; 833 1.3 riastrad 834 1.3 riastrad DPRINTF(("umcpmio_i2c_write: checking status loop:" 835 1.3 riastrad " wcretry=%d\n", wsretry)); 836 1.3 riastrad 837 1.3 riastrad err = umcpmio_get_status(sc, &status_res, true); 838 1.3 riastrad if (err) { 839 1.3 riastrad err = EIO; 840 1.3 riastrad break; 841 1.3 riastrad } 842 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 843 1.3 riastrad (uint8_t *)&status_res, 844 1.3 riastrad MCP2221_RES_BUFFER_SIZE, 845 1.3 riastrad "umcpmio_i2c_write post check status"); 846 1.3 riastrad /* 847 1.3 riastrad * Since there isn't any documentation on what 848 1.3 riastrad * some of the internal state means, it isn't 849 1.3 riastrad * clear that this is any different than than 850 1.3 riastrad * MCP2221_ENGINE_ADDRNACK in the other state 851 1.3 riastrad * register. 852 1.3 riastrad */ 853 1.3 riastrad 854 1.3 riastrad if (status_res.internal_i2c_state20 & 855 1.3 riastrad MCP2221_ENGINE_T1_MASK_NACK) { 856 1.3 riastrad DPRINTF(("umcpmio_i2c_write post check:" 857 1.3 riastrad " engine internal state T1 says NACK\n")); 858 1.3 riastrad err = EIO; 859 1.3 riastrad break; 860 1.3 riastrad } 861 1.3 riastrad if (status_res.internal_i2c_state == 0) { 862 1.3 riastrad DPRINTF(("umcpmio_i2c_write post check:" 863 1.3 riastrad " engine internal state is ZERO\n")); 864 1.3 riastrad err = 0; 865 1.3 riastrad break; 866 1.3 riastrad } 867 1.3 riastrad if (status_res.internal_i2c_state == 868 1.3 riastrad MCP2221_ENGINE_WRITINGNOSTOP && 869 1.3 riastrad cmd == MCP2221_I2C_WRITE_DATA_NS) { 870 1.3 riastrad DPRINTF(("umcpmio_i2c_write post check:" 871 1.3 riastrad " engine internal state is WRITINGNOSTOP\n")); 872 1.3 riastrad err = 0; 873 1.3 riastrad break; 874 1.3 riastrad } 875 1.3 riastrad if (umcpmio_i2c_fatal(status_res.internal_i2c_state)) { 876 1.3 riastrad DPRINTF(("umcpmio_i2c_write post check:" 877 1.3 riastrad " engine internal state is fatal: %02x\n", 878 1.3 riastrad status_res.internal_i2c_state)); 879 1.3 riastrad err = EIO; 880 1.3 riastrad break; 881 1.1 brad } 882 1.3 riastrad WAITMS(sc->sc_busy_delay); 883 1.1 brad } 884 1.1 brad 885 1.1 brad out: 886 1.2 riastrad return err; 887 1.1 brad } 888 1.1 brad 889 1.2 riastrad /* 890 1.2 riastrad * This one deviates a bit from Adafruit in that is supports a straight 891 1.2 riastrad * read and a write + read. That is, write a register to read from and 892 1.2 riastrad * then do the read. 893 1.1 brad */ 894 1.1 brad 895 1.1 brad static int 896 1.1 brad umcpmio_i2c_read(struct umcpmio_softc *sc, i2c_op_t op, i2c_addr_t addr, 897 1.2 riastrad const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, int 898 1.2 riastrad flags) 899 1.1 brad { 900 1.1 brad struct mcp2221_i2c_req i2c_req; 901 1.1 brad struct mcp2221_i2c_res i2c_res; 902 1.1 brad struct mcp2221_i2c_fetch_req i2c_fetch_req; 903 1.1 brad struct mcp2221_i2c_fetch_res i2c_fetch_res; 904 1.1 brad struct mcp2221_status_res status_res; 905 1.1 brad int err = 0; 906 1.1 brad uint8_t cmd; 907 1.1 brad int rretry = sc->sc_retry_busy_read; 908 1.1 brad 909 1.1 brad if (cmdbuf != NULL) { 910 1.2 riastrad DPRINTF(("umcpmio_i2c_read: has a cmdbuf, doing write first:" 911 1.2 riastrad " addr=%02x\n", addr)); 912 1.2 riastrad err = umcpmio_i2c_write(sc, I2C_OP_WRITE, addr, cmdbuf, cmdlen, 913 1.2 riastrad NULL, 0, flags); 914 1.1 brad } 915 1.1 brad if (err) 916 1.1 brad goto out; 917 1.1 brad 918 1.1 brad err = umcpmio_get_status(sc, &status_res, true); 919 1.1 brad if (err) 920 1.1 brad goto out; 921 1.1 brad 922 1.2 riastrad if (status_res.internal_i2c_state != 0 && 923 1.1 brad status_res.internal_i2c_state != MCP2221_ENGINE_WRITINGNOSTOP) { 924 1.2 riastrad DPRINTF(("umcpmio_i2c_read:" 925 1.2 riastrad " internal state not zero and not WRITINGNOSTOP," 926 1.2 riastrad " clearing. internal_i2c_state=%02x\n", 927 1.2 riastrad status_res.internal_i2c_state)); 928 1.1 brad err = umcpmio_i2c_clear(sc, true); 929 1.1 brad } 930 1.1 brad if (err) 931 1.1 brad goto out; 932 1.1 brad 933 1.1 brad memset(&i2c_req, 0, MCP2221_REQ_BUFFER_SIZE); 934 1.1 brad if (cmdbuf == NULL && 935 1.1 brad status_res.internal_i2c_state != MCP2221_ENGINE_WRITINGNOSTOP) { 936 1.1 brad cmd = MCP2221_I2C_READ_DATA; 937 1.1 brad } else { 938 1.1 brad cmd = MCP2221_I2C_READ_DATA_RS; 939 1.1 brad } 940 1.1 brad 941 1.2 riastrad /* 942 1.2 riastrad * The chip apparently can't do a READ without a STOP 943 1.2 riastrad * operation. Report that, and try treating it like a READ 944 1.2 riastrad * with a STOP. This won't work for a lot of devices. 945 1.1 brad */ 946 1.1 brad 947 1.3 riastrad if (!I2C_OP_STOP_P(op) && sc->sc_reportreadnostop) { 948 1.2 riastrad device_printf(sc->sc_dev, 949 1.2 riastrad "umcpmio_i2c_read: ************ called with READ" 950 1.2 riastrad " without STOP ***************\n"); 951 1.2 riastrad } 952 1.1 brad 953 1.1 brad i2c_req.cmd = cmd; 954 1.1 brad i2c_req.lsblen = datalen; 955 1.1 brad i2c_req.msblen = 0; 956 1.1 brad i2c_req.slaveaddr = (addr << 1) | 0x01; 957 1.1 brad 958 1.2 riastrad DPRINTF(("umcpmio_i2c_read: I2C READ normal read:" 959 1.2 riastrad " cmd=%02x, addr=%02x\n", cmd, addr)); 960 1.1 brad 961 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 962 1.2 riastrad (uint8_t *)&i2c_req, MCP2221_RES_BUFFER_SIZE, 963 1.2 riastrad "umcpmio_i2c_read normal read req buffer copy"); 964 1.1 brad 965 1.1 brad mutex_enter(&sc->sc_action_mutex); 966 1.2 riastrad err = umcpmio_send_report(sc, 967 1.2 riastrad (uint8_t *)&i2c_req, MCP2221_REQ_BUFFER_SIZE, 968 1.2 riastrad (uint8_t *)&i2c_res, sc->sc_cv_wait); 969 1.1 brad mutex_exit(&sc->sc_action_mutex); 970 1.1 brad 971 1.3 riastrad if (err) { 972 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_i2c_read request error:" 973 1.3 riastrad " cmd=%02x, err=%d\n", cmd, err); 974 1.3 riastrad err = EIO; 975 1.3 riastrad goto out; 976 1.3 riastrad } 977 1.3 riastrad 978 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 979 1.3 riastrad (uint8_t *)&i2c_res, MCP2221_RES_BUFFER_SIZE, 980 1.3 riastrad "umcpmio_i2c_read read-request response buffer copy"); 981 1.3 riastrad 982 1.3 riastrad while (rretry > 0) { 983 1.3 riastrad rretry--; 984 1.3 riastrad DPRINTF(("umcpmio_i2c_read: fetch loop: rretry=%d\n", rretry)); 985 1.3 riastrad err = 0; 986 1.3 riastrad memset(&i2c_fetch_req, 0, MCP2221_REQ_BUFFER_SIZE); 987 1.3 riastrad i2c_fetch_req.cmd = MCP2221_CMD_I2C_FETCH_READ_DATA; 988 1.3 riastrad mutex_enter(&sc->sc_action_mutex); 989 1.3 riastrad err = umcpmio_send_report(sc, 990 1.3 riastrad (uint8_t *)&i2c_fetch_req, MCP2221_REQ_BUFFER_SIZE, 991 1.3 riastrad (uint8_t *)&i2c_fetch_res, sc->sc_cv_wait); 992 1.3 riastrad mutex_exit(&sc->sc_action_mutex); 993 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 994 1.3 riastrad (uint8_t *)&i2c_fetch_req, MCP2221_RES_BUFFER_SIZE, 995 1.3 riastrad "umcpmio_i2c_read fetch res buffer copy"); 996 1.1 brad 997 1.3 riastrad if (i2c_fetch_res.cmd != MCP2221_CMD_I2C_FETCH_READ_DATA) { 998 1.3 riastrad device_printf(sc->sc_dev, "umcpmio_i2c_read:" 999 1.3 riastrad " fetch2: not the command desired: %02x\n", 1000 1.3 riastrad i2c_fetch_res.cmd); 1001 1.3 riastrad err = EIO; 1002 1.3 riastrad break; 1003 1.3 riastrad } 1004 1.3 riastrad if (i2c_fetch_res.completion == 1005 1.3 riastrad MCP2221_FETCH_READ_PARTIALDATA || 1006 1.3 riastrad i2c_fetch_res.fetchlen == MCP2221_FETCH_READERROR) { 1007 1.3 riastrad DPRINTF(("umcpmio_i2c_read: fetch loop:" 1008 1.3 riastrad " partial data or read error:" 1009 1.3 riastrad " completion=%02x, fetchlen=%02x\n", 1010 1.3 riastrad i2c_fetch_res.completion, 1011 1.3 riastrad i2c_fetch_res.fetchlen)); 1012 1.3 riastrad WAITMS(sc->sc_busy_delay); 1013 1.3 riastrad err = EAGAIN; 1014 1.3 riastrad continue; 1015 1.3 riastrad } 1016 1.3 riastrad if (i2c_fetch_res.internal_i2c_state == 1017 1.3 riastrad MCP2221_ENGINE_ADDRNACK) { 1018 1.3 riastrad DPRINTF(("umcpmio_i2c_read:" 1019 1.3 riastrad " fetch loop: engine NACK\n")); 1020 1.3 riastrad err = EIO; 1021 1.3 riastrad break; 1022 1.3 riastrad } 1023 1.3 riastrad if (i2c_fetch_res.internal_i2c_state == 0 && 1024 1.3 riastrad i2c_fetch_res.fetchlen == 0) { 1025 1.3 riastrad DPRINTF(("umcpmio_i2c_read: fetch loop:" 1026 1.3 riastrad " internal state and fetch len are ZERO\n")); 1027 1.3 riastrad err = 0; 1028 1.3 riastrad break; 1029 1.3 riastrad } 1030 1.3 riastrad if (i2c_fetch_res.internal_i2c_state == 1031 1.3 riastrad MCP2221_ENGINE_READPARTIAL || 1032 1.3 riastrad i2c_fetch_res.internal_i2c_state == 1033 1.3 riastrad MCP2221_ENGINE_READCOMPLETE) { 1034 1.3 riastrad DPRINTF(("umcpmio_i2c_read:" 1035 1.3 riastrad " fetch loop: read partial or" 1036 1.3 riastrad " read complete: internal_i2c_state=%02x\n", 1037 1.3 riastrad i2c_fetch_res.internal_i2c_state)); 1038 1.1 brad err = 0; 1039 1.3 riastrad break; 1040 1.1 brad } 1041 1.3 riastrad } 1042 1.3 riastrad if (err == EAGAIN) 1043 1.3 riastrad err = ETIMEDOUT; 1044 1.3 riastrad if (err) 1045 1.3 riastrad goto out; 1046 1.3 riastrad 1047 1.3 riastrad if (databuf == NULL || 1048 1.3 riastrad i2c_fetch_res.fetchlen == MCP2221_FETCH_READERROR) { 1049 1.3 riastrad DPRINTF(("umcpmio_i2c_read: copy data:" 1050 1.3 riastrad " databuf is NULL\n")); 1051 1.3 riastrad goto out; 1052 1.3 riastrad } 1053 1.1 brad 1054 1.3 riastrad const int size = uimin(i2c_fetch_res.fetchlen, datalen); 1055 1.3 riastrad DPRINTF(("umcpmio_i2c_read: copy data: size=%d, fetchlen=%d\n", 1056 1.3 riastrad size, i2c_fetch_res.fetchlen)); 1057 1.3 riastrad if (size > 0) { 1058 1.3 riastrad memcpy(databuf, &i2c_fetch_res.data[0], size); 1059 1.1 brad } 1060 1.3 riastrad 1061 1.1 brad out: 1062 1.2 riastrad return err; 1063 1.1 brad } 1064 1.1 brad 1065 1.1 brad static int 1066 1.1 brad umcpmio_i2c_exec(void *v, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 1067 1.1 brad size_t cmdlen, void *databuf, size_t datalen, int flags) 1068 1.1 brad { 1069 1.1 brad struct umcpmio_softc *sc = v; 1070 1.1 brad size_t totallen = 0; 1071 1.1 brad int err = 0; 1072 1.1 brad 1073 1.1 brad if (addr > 0x7f) 1074 1.2 riastrad return ENOTSUP; 1075 1.1 brad 1076 1.1 brad if (cmdbuf != NULL) 1077 1.1 brad totallen += cmdlen; 1078 1.1 brad if (databuf != NULL) 1079 1.1 brad totallen += datalen; 1080 1.1 brad 1081 1.2 riastrad /* 1082 1.2 riastrad * There is a way to do a transfer that is larger than 60 bytes, 1083 1.1 brad * but it requires that your break the transfer up into pieces and 1084 1.1 brad * send them in 60 byte chunks. We just won't support that right now. 1085 1.1 brad * It would be somewhat unusual for there to be a transfer that big, 1086 1.1 brad * unless you are trying to do block transfers and that isn't natively 1087 1.1 brad * supported by the chip anyway... so those have to be broken up and 1088 1.1 brad * sent as bytes. 1089 1.1 brad */ 1090 1.1 brad 1091 1.1 brad if (totallen > 60) 1092 1.2 riastrad return ENOTSUP; 1093 1.1 brad 1094 1.1 brad if (I2C_OP_WRITE_P(op)) { 1095 1.2 riastrad err = umcpmio_i2c_write(sc, op, addr, cmdbuf, cmdlen, 1096 1.2 riastrad databuf, datalen, flags); 1097 1.1 brad 1098 1.1 brad DPRINTF(("umcpmio_exec: I2C WRITE: err=%d\n", err)); 1099 1.1 brad } else { 1100 1.2 riastrad err = umcpmio_i2c_read(sc, op, addr, cmdbuf, cmdlen, 1101 1.2 riastrad databuf, datalen, flags); 1102 1.1 brad 1103 1.1 brad DPRINTF(("umcpmio_exec: I2C READ: err=%d\n", err)); 1104 1.1 brad } 1105 1.1 brad 1106 1.2 riastrad return err; 1107 1.1 brad } 1108 1.1 brad 1109 1.1 brad /* Accessing the ADC and DAC part of the chip */ 1110 1.1 brad 1111 1.2 riastrad #define UMCPMIO_DEV_UNIT(m) ((m) & 0x80 ? ((m) & 0x7f) / 3 : (m)) 1112 1.2 riastrad #define UMCPMIO_DEV_WHAT(m) ((m) & 0x80 ? (((m) & 0x7f) % 3) + 1 : CONTROL_DEV) 1113 1.1 brad 1114 1.1 brad static int 1115 1.1 brad umcpmio_dev_open(dev_t dev, int flags, int fmt, struct lwp *l) 1116 1.1 brad { 1117 1.1 brad struct umcpmio_softc *sc; 1118 1.1 brad int dunit; 1119 1.1 brad int pin = -1; 1120 1.1 brad int error = 0; 1121 1.1 brad 1122 1.1 brad sc = device_lookup_private(&umcpmio_cd, UMCPMIO_DEV_UNIT(minor(dev))); 1123 1.1 brad if (!sc) 1124 1.1 brad return ENXIO; 1125 1.1 brad 1126 1.1 brad dunit = UMCPMIO_DEV_WHAT(minor(dev)); 1127 1.1 brad 1128 1.1 brad if (sc->sc_dev_open[dunit]) { 1129 1.2 riastrad DPRINTF(("umcpmio_dev_open: dunit=%d BUSY\n", dunit)); 1130 1.1 brad return EBUSY; 1131 1.1 brad } 1132 1.1 brad 1133 1.2 riastrad /* 1134 1.2 riastrad * The control device only allows for ioctl calls, so pretty 1135 1.2 riastrad * much allow any sort of access. For the ADC, you perform a 1136 1.2 riastrad * strict O_RDONLY and for the DAC a strict O_WRONLY. It is an 1137 1.2 riastrad * error to try and do a O_RDWR It makes little sense to try 1138 1.2 riastrad * and support select or poll. The ADC and DAC are always 1139 1.2 riastrad * available for use. 1140 1.1 brad */ 1141 1.1 brad 1142 1.1 brad if (dunit != CONTROL_DEV && 1143 1.1 brad ((flags & FREAD) && (flags & FWRITE))) { 1144 1.2 riastrad DPRINTF(("umcpmio_dev_open: Not CONTROL device and trying to" 1145 1.2 riastrad " do READ and WRITE\n")); 1146 1.1 brad return EINVAL; 1147 1.1 brad } 1148 1.1 brad 1149 1.2 riastrad /* 1150 1.2 riastrad * Ya, this unrolling will also have to be changed if the MCP-2210 is 1151 1.1 brad * supported. There are currently only 4 pins, so don't worry too much 1152 1.1 brad * about it. The MCP-2210 has RAM, so there would be a fifth for it. 1153 1.1 brad */ 1154 1.1 brad 1155 1.1 brad mutex_enter(&sc->sc_action_mutex); 1156 1.1 brad if (dunit != CONTROL_DEV) { 1157 1.1 brad switch (dunit) { 1158 1.1 brad case GP1_DEV: 1159 1.1 brad pin = 1; 1160 1.1 brad break; 1161 1.1 brad case GP2_DEV: 1162 1.1 brad pin = 2; 1163 1.1 brad break; 1164 1.1 brad case GP3_DEV: 1165 1.1 brad pin = 3; 1166 1.1 brad break; 1167 1.1 brad default: 1168 1.1 brad error = EINVAL; 1169 1.3 riastrad goto out; 1170 1.1 brad } 1171 1.3 riastrad /* 1172 1.3 riastrad * XXX - we can probably do better here... it 1173 1.3 riastrad * doesn't remember what the pin was set to and 1174 1.3 riastrad * probably should. 1175 1.3 riastrad */ 1176 1.3 riastrad if (flags & FREAD) { 1177 1.3 riastrad error = umcpmio_gpio_pin_ctlctl(sc, pin, 1178 1.4 riastrad GPIO_PIN_ALT0); 1179 1.3 riastrad } else { 1180 1.3 riastrad if (pin == 1) { 1181 1.3 riastrad error = EINVAL; 1182 1.1 brad } else { 1183 1.3 riastrad error = umcpmio_gpio_pin_ctlctl(sc, 1184 1.4 riastrad pin, GPIO_PIN_ALT1); 1185 1.1 brad } 1186 1.1 brad } 1187 1.1 brad } 1188 1.3 riastrad if (error) 1189 1.3 riastrad goto out; 1190 1.3 riastrad sc->sc_dev_open[dunit] = true; 1191 1.3 riastrad out: 1192 1.1 brad mutex_exit(&sc->sc_action_mutex); 1193 1.1 brad 1194 1.2 riastrad DPRINTF(("umcpmio_dev_open: Opened dunit=%d, pin=%d, error=%d\n", 1195 1.2 riastrad dunit, pin, error)); 1196 1.1 brad 1197 1.1 brad return error; 1198 1.1 brad } 1199 1.1 brad 1200 1.1 brad /* Read an ADC value */ 1201 1.1 brad 1202 1.1 brad static int 1203 1.1 brad umcpmio_dev_read(dev_t dev, struct uio *uio, int flags) 1204 1.1 brad { 1205 1.1 brad struct umcpmio_softc *sc; 1206 1.1 brad struct mcp2221_status_res status_res; 1207 1.1 brad int dunit; 1208 1.1 brad int error = 0; 1209 1.1 brad uint8_t adc_lsb; 1210 1.1 brad uint8_t adc_msb; 1211 1.1 brad uint16_t buf; 1212 1.1 brad 1213 1.2 riastrad sc = device_lookup_private(&umcpmio_cd, UMCPMIO_DEV_UNIT(minor(dev))); 1214 1.2 riastrad if (sc == NULL) 1215 1.1 brad return ENXIO; 1216 1.1 brad 1217 1.1 brad dunit = UMCPMIO_DEV_WHAT(minor(dev)); 1218 1.1 brad 1219 1.3 riastrad if (dunit == CONTROL_DEV) { 1220 1.1 brad error = EINVAL; 1221 1.3 riastrad goto out; 1222 1.1 brad } 1223 1.1 brad 1224 1.3 riastrad while (uio->uio_resid && !sc->sc_dying) { 1225 1.3 riastrad error = umcpmio_get_status(sc, &status_res, true); 1226 1.3 riastrad if (error) 1227 1.5 brad break; 1228 1.3 riastrad switch (dunit) { 1229 1.3 riastrad case GP1_DEV: 1230 1.3 riastrad adc_lsb = status_res.adc_channel0_lsb; 1231 1.3 riastrad adc_msb = status_res.adc_channel0_msb; 1232 1.3 riastrad break; 1233 1.3 riastrad case GP2_DEV: 1234 1.3 riastrad adc_lsb = status_res.adc_channel1_lsb; 1235 1.3 riastrad adc_msb = status_res.adc_channel1_msb; 1236 1.3 riastrad break; 1237 1.3 riastrad case GP3_DEV: 1238 1.3 riastrad adc_lsb = status_res.adc_channel2_lsb; 1239 1.3 riastrad adc_msb = status_res.adc_channel2_msb; 1240 1.3 riastrad break; 1241 1.3 riastrad default: 1242 1.3 riastrad error = EINVAL; 1243 1.3 riastrad break; 1244 1.3 riastrad } 1245 1.3 riastrad if (error) 1246 1.5 brad break; 1247 1.3 riastrad if (sc->sc_dying) 1248 1.3 riastrad break; 1249 1.3 riastrad 1250 1.3 riastrad buf = adc_msb << 8; 1251 1.3 riastrad buf |= adc_lsb; 1252 1.3 riastrad error = uiomove(&buf, 2, uio); 1253 1.5 brad if (error) 1254 1.5 brad break; 1255 1.3 riastrad } 1256 1.3 riastrad out: 1257 1.1 brad return error; 1258 1.1 brad } 1259 1.1 brad 1260 1.1 brad /* Write to the DAC */ 1261 1.1 brad 1262 1.1 brad static int 1263 1.1 brad umcpmio_dev_write(dev_t dev, struct uio *uio, int flags) 1264 1.1 brad { 1265 1.1 brad struct umcpmio_softc *sc; 1266 1.1 brad int dunit; 1267 1.1 brad int error = 0; 1268 1.1 brad 1269 1.2 riastrad sc = device_lookup_private(&umcpmio_cd, UMCPMIO_DEV_UNIT(minor(dev))); 1270 1.2 riastrad if (sc == NULL) 1271 1.1 brad return ENXIO; 1272 1.1 brad 1273 1.1 brad dunit = UMCPMIO_DEV_WHAT(minor(dev)); 1274 1.1 brad 1275 1.3 riastrad if (dunit == CONTROL_DEV) { 1276 1.1 brad error = EINVAL; 1277 1.3 riastrad goto out; 1278 1.1 brad } 1279 1.1 brad 1280 1.3 riastrad while (uio->uio_resid && !sc->sc_dying) { 1281 1.3 riastrad uint8_t buf; 1282 1.3 riastrad 1283 1.3 riastrad if ((error = uiomove(&buf, 1, uio)) != 0) 1284 1.3 riastrad break; 1285 1.3 riastrad 1286 1.3 riastrad if (sc->sc_dying) 1287 1.3 riastrad break; 1288 1.3 riastrad 1289 1.3 riastrad error = umcpmio_set_dac_value_one(sc, buf, true); 1290 1.3 riastrad if (error) 1291 1.3 riastrad break; 1292 1.3 riastrad } 1293 1.3 riastrad out: 1294 1.1 brad return error; 1295 1.1 brad } 1296 1.1 brad 1297 1.1 brad /* Close everything up */ 1298 1.1 brad 1299 1.1 brad static int 1300 1.1 brad umcpmio_dev_close(dev_t dev, int flags, int fmt, struct lwp *l) 1301 1.1 brad { 1302 1.1 brad struct umcpmio_softc *sc; 1303 1.1 brad int dunit; 1304 1.1 brad int pin; 1305 1.1 brad int error = 0; 1306 1.1 brad 1307 1.1 brad sc = device_lookup_private(&umcpmio_cd, UMCPMIO_DEV_UNIT(minor(dev))); 1308 1.1 brad if (sc->sc_dying) 1309 1.1 brad return EIO; 1310 1.1 brad 1311 1.1 brad dunit = UMCPMIO_DEV_WHAT(minor(dev)); 1312 1.1 brad 1313 1.1 brad mutex_enter(&sc->sc_action_mutex); 1314 1.1 brad if (dunit != CONTROL_DEV) { 1315 1.1 brad switch (dunit) { 1316 1.1 brad case GP1_DEV: 1317 1.1 brad pin = 1; 1318 1.1 brad break; 1319 1.1 brad case GP2_DEV: 1320 1.1 brad pin = 2; 1321 1.1 brad break; 1322 1.1 brad case GP3_DEV: 1323 1.1 brad pin = 3; 1324 1.1 brad break; 1325 1.1 brad default: 1326 1.1 brad error = EINVAL; 1327 1.3 riastrad goto out; 1328 1.1 brad break; 1329 1.1 brad } 1330 1.3 riastrad /* 1331 1.3 riastrad * XXX - Ya, this really could be done better. 1332 1.3 riastrad * Probably should read the sram config and 1333 1.3 riastrad * maybe the gpio config and save out what the 1334 1.3 riastrad * pin was set to. 1335 1.3 riastrad */ 1336 1.4 riastrad error = umcpmio_gpio_pin_ctlctl(sc, pin, GPIO_PIN_INPUT); 1337 1.1 brad } 1338 1.3 riastrad out: 1339 1.1 brad sc->sc_dev_open[dunit] = false; 1340 1.1 brad mutex_exit(&sc->sc_action_mutex); 1341 1.1 brad 1342 1.1 brad return error; 1343 1.1 brad } 1344 1.1 brad 1345 1.1 brad static int 1346 1.1 brad umcpmio_dev_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1347 1.1 brad { 1348 1.1 brad struct umcpmio_softc *sc; 1349 1.1 brad struct mcp2221_status_res get_status_res; 1350 1.1 brad struct mcp2221_get_sram_res get_sram_res; 1351 1.1 brad struct mcp2221_get_gpio_cfg_res get_gpio_cfg_res; 1352 1.1 brad struct mcp2221_get_flash_res get_flash_res; 1353 1.1 brad struct mcp2221_status_res *ioctl_get_status; 1354 1.1 brad struct mcp2221_get_sram_res *ioctl_get_sram; 1355 1.1 brad struct mcp2221_get_gpio_cfg_res *ioctl_get_gpio_cfg; 1356 1.1 brad struct umcpmio_ioctl_get_flash *ioctl_get_flash; 1357 1.1 brad struct umcpmio_ioctl_put_flash *ioctl_put_flash; 1358 1.1 brad struct mcp2221_put_flash_req put_flash_req; 1359 1.1 brad struct mcp2221_put_flash_res put_flash_res; 1360 1.1 brad int dunit; 1361 1.1 brad int error = 0; 1362 1.1 brad 1363 1.1 brad sc = device_lookup_private(&umcpmio_cd, UMCPMIO_DEV_UNIT(minor(dev))); 1364 1.1 brad if (sc->sc_dying) 1365 1.1 brad return EIO; 1366 1.1 brad 1367 1.1 brad dunit = UMCPMIO_DEV_WHAT(minor(dev)); 1368 1.1 brad 1369 1.1 brad if (dunit != CONTROL_DEV) { 1370 1.2 riastrad /* 1371 1.2 riastrad * It actually is fine to call ioctl with a unsupported 1372 1.2 riastrad * cmd, but be a little noisy if debug is enabled. 1373 1.1 brad */ 1374 1.2 riastrad DPRINTF(("umcpmio_dev_ioctl: dunit is not the CONTROL device:" 1375 1.2 riastrad " dunit=%d, cmd=%ld\n", dunit, cmd)); 1376 1.1 brad return EINVAL; 1377 1.1 brad } 1378 1.1 brad 1379 1.1 brad mutex_enter(&sc->sc_action_mutex); 1380 1.1 brad 1381 1.1 brad switch (cmd) { 1382 1.2 riastrad /* 1383 1.2 riastrad * The GET calls use a shadow buffer for each type of 1384 1.2 riastrad * call. That probably isn't actually needed and the 1385 1.2 riastrad * memcpy could be avoided. but... it is only ever 64 1386 1.2 riastrad * bytes, so maybe not a big deal. 1387 1.1 brad */ 1388 1.1 brad case UMCPMIO_GET_STATUS: 1389 1.1 brad ioctl_get_status = (struct mcp2221_status_res *)data; 1390 1.1 brad error = umcpmio_get_status(sc, &get_status_res, false); 1391 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1392 1.2 riastrad (uint8_t *)&get_status_res, MCP2221_RES_BUFFER_SIZE, 1393 1.2 riastrad "umcpmio_dev_ioctl: UMCPMIO_GET_STATUS: get_status_res"); 1394 1.2 riastrad DPRINTF(("umcpmio_dev_ioctl: UMCPMIO_GET_STATUS:" 1395 1.2 riastrad " umcpmio_get_status error=%d\n", error)); 1396 1.3 riastrad if (error) 1397 1.3 riastrad break; 1398 1.3 riastrad memcpy(ioctl_get_status, &get_status_res, 1399 1.3 riastrad MCP2221_RES_BUFFER_SIZE); 1400 1.1 brad break; 1401 1.1 brad 1402 1.1 brad case UMCPMIO_GET_SRAM: 1403 1.1 brad ioctl_get_sram = (struct mcp2221_get_sram_res *)data; 1404 1.1 brad error = umcpmio_get_sram(sc, &get_sram_res, false); 1405 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1406 1.2 riastrad (uint8_t *)&get_sram_res, MCP2221_RES_BUFFER_SIZE, 1407 1.2 riastrad "umcpmio_dev_ioctl: UMCPMIO_GET_SRAM: get_sram_res"); 1408 1.2 riastrad DPRINTF(("umcpmio_dev_ioctl: UMCPMIO_GET_SRAM:" 1409 1.2 riastrad " umcpmio_get_sram error=%d\n", error)); 1410 1.3 riastrad if (error) 1411 1.3 riastrad break; 1412 1.3 riastrad memcpy(ioctl_get_sram, &get_sram_res, 1413 1.3 riastrad MCP2221_RES_BUFFER_SIZE); 1414 1.1 brad break; 1415 1.1 brad 1416 1.1 brad case UMCPMIO_GET_GP_CFG: 1417 1.1 brad ioctl_get_gpio_cfg = (struct mcp2221_get_gpio_cfg_res *)data; 1418 1.1 brad error = umcpmio_get_gpio_cfg(sc, &get_gpio_cfg_res, false); 1419 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1420 1.2 riastrad (uint8_t *)&get_gpio_cfg_res, MCP2221_RES_BUFFER_SIZE, 1421 1.2 riastrad "umcpmio_dev_ioctl: UMCPMIO_GET_GP_CFG: get_gpio_cfg_res"); 1422 1.2 riastrad DPRINTF(("umcpmio_dev_ioctl: UMCPMIO_GET_GP_CFG:" 1423 1.2 riastrad " umcpmio_get_gpio_cfg error=%d\n", error)); 1424 1.3 riastrad if (error) 1425 1.3 riastrad break; 1426 1.3 riastrad memcpy(ioctl_get_gpio_cfg, &get_gpio_cfg_res, 1427 1.3 riastrad MCP2221_RES_BUFFER_SIZE); 1428 1.1 brad break; 1429 1.1 brad 1430 1.1 brad case UMCPMIO_GET_FLASH: 1431 1.1 brad ioctl_get_flash = (struct umcpmio_ioctl_get_flash *)data; 1432 1.2 riastrad error = umcpmio_get_flash(sc, ioctl_get_flash->subcode, 1433 1.2 riastrad &get_flash_res, false); 1434 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1435 1.2 riastrad (uint8_t *)&get_flash_res, MCP2221_RES_BUFFER_SIZE, 1436 1.2 riastrad "umcpmio_dev_ioctl: UMCPMIO_GET_FLASH: get_flash_res"); 1437 1.2 riastrad DPRINTF(("umcpmio_dev_ioctl: UMCPMIO_GET_FLASH:" 1438 1.2 riastrad " umcpmio_get_flash subcode=%d, error=%d\n", 1439 1.2 riastrad ioctl_get_flash->subcode, error)); 1440 1.3 riastrad if (error) 1441 1.3 riastrad break; 1442 1.3 riastrad memcpy(&ioctl_get_flash->get_flash_res, &get_flash_res, 1443 1.3 riastrad MCP2221_RES_BUFFER_SIZE); 1444 1.1 brad break; 1445 1.1 brad 1446 1.1 brad case UMCPMIO_PUT_FLASH: 1447 1.2 riastrad /* 1448 1.2 riastrad * We only allow the flash parts related to gpio to be changed. 1449 1.1 brad * Bounce any attempt to do something else. Also use a shadow 1450 1.1 brad * buffer for the put, so we get to control just literally 1451 1.1 brad * everything about the write to flash. 1452 1.1 brad */ 1453 1.1 brad ioctl_put_flash = (struct umcpmio_ioctl_put_flash *)data; 1454 1.2 riastrad DPRINTF(("umcpmio_dev_ioctl: UMCPMIO_PUT_FLASH:" 1455 1.2 riastrad " umcpmio_put_flash subcode=%d\n", 1456 1.2 riastrad ioctl_put_flash->subcode)); 1457 1.3 riastrad if (ioctl_put_flash->subcode != MCP2221_FLASH_SUBCODE_GP) { 1458 1.1 brad error = EINVAL; 1459 1.3 riastrad break; 1460 1.1 brad } 1461 1.3 riastrad memset(&put_flash_req, 0, MCP2221_REQ_BUFFER_SIZE); 1462 1.3 riastrad put_flash_req.subcode = ioctl_put_flash->subcode; 1463 1.3 riastrad put_flash_req.u.gp.gp0_settings = 1464 1.3 riastrad ioctl_put_flash->put_flash_req.u.gp.gp0_settings; 1465 1.3 riastrad put_flash_req.u.gp.gp1_settings = 1466 1.3 riastrad ioctl_put_flash->put_flash_req.u.gp.gp1_settings; 1467 1.3 riastrad put_flash_req.u.gp.gp2_settings = 1468 1.3 riastrad ioctl_put_flash->put_flash_req.u.gp.gp2_settings; 1469 1.3 riastrad put_flash_req.u.gp.gp3_settings = 1470 1.3 riastrad ioctl_put_flash->put_flash_req.u.gp.gp3_settings; 1471 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1472 1.3 riastrad (uint8_t *)&ioctl_put_flash->put_flash_req, 1473 1.3 riastrad MCP2221_REQ_BUFFER_SIZE, 1474 1.3 riastrad "umcpmio_dev_ioctl: UMCPMIO_PUT_FLASH:" 1475 1.3 riastrad " ioctl put_flash_req"); 1476 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1477 1.3 riastrad (uint8_t *)&put_flash_req, MCP2221_REQ_BUFFER_SIZE, 1478 1.3 riastrad "umcpmio_dev_ioctl:" 1479 1.3 riastrad " UMCPMIO_PUT_FLASH: put_flash_req"); 1480 1.3 riastrad memset(&put_flash_res, 0, MCP2221_RES_BUFFER_SIZE); 1481 1.3 riastrad error = umcpmio_put_flash(sc, &put_flash_req, 1482 1.3 riastrad &put_flash_res, false); 1483 1.6 riastrad if (error) 1484 1.6 riastrad break; 1485 1.6 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1486 1.6 riastrad (uint8_t *)&put_flash_res, MCP2221_RES_BUFFER_SIZE, 1487 1.6 riastrad "umcpmio_dev_ioctl: UMCPMIO_PUT_FLASH:" 1488 1.6 riastrad " put_flash_res"); 1489 1.6 riastrad memcpy(&ioctl_put_flash->put_flash_res, &put_flash_res, 1490 1.6 riastrad MCP2221_RES_BUFFER_SIZE); 1491 1.1 brad break; 1492 1.1 brad default: 1493 1.1 brad error = EINVAL; 1494 1.1 brad } 1495 1.1 brad 1496 1.1 brad mutex_exit(&sc->sc_action_mutex); 1497 1.1 brad 1498 1.1 brad return error; 1499 1.1 brad } 1500 1.1 brad 1501 1.1 brad /* This is for sysctl variables that don't actually change the chip. */ 1502 1.1 brad 1503 1.1 brad int 1504 1.1 brad umcpmio_verify_sysctl(SYSCTLFN_ARGS) 1505 1.1 brad { 1506 1.1 brad int error, t; 1507 1.1 brad struct sysctlnode node; 1508 1.1 brad 1509 1.1 brad node = *rnode; 1510 1.1 brad t = *(int *)rnode->sysctl_data; 1511 1.1 brad node.sysctl_data = &t; 1512 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1513 1.1 brad if (error || newp == NULL) 1514 1.1 brad return error; 1515 1.1 brad 1516 1.1 brad if (t < 0) 1517 1.1 brad return EINVAL; 1518 1.1 brad 1519 1.1 brad *(int *)rnode->sysctl_data = t; 1520 1.1 brad 1521 1.1 brad return 0; 1522 1.1 brad } 1523 1.1 brad 1524 1.2 riastrad /* 1525 1.2 riastrad * sysctl validation for stuff that interacts with the chip needs to 1526 1.2 riastrad * happen in a transaction. The read of the current state and the 1527 1.2 riastrad * update to new state can't allow for someone to sneak in between the 1528 1.2 riastrad * two. 1529 1.1 brad * 1530 1.2 riastrad * We use text for the values of a lot of these variables so you don't 1531 1.2 riastrad * need the datasheet in front of you. You get to do that with 1532 1.2 riastrad * umcpmioctl(8). 1533 1.1 brad */ 1534 1.1 brad 1535 1.1 brad static struct umcpmio_sysctl_name umcpmio_vref_names[] = { 1536 1.1 brad { 1537 1.1 brad .text = "4.096V", 1538 1.1 brad }, 1539 1.1 brad { 1540 1.1 brad .text = "2.048V", 1541 1.1 brad }, 1542 1.1 brad { 1543 1.1 brad .text = "1.024V", 1544 1.1 brad }, 1545 1.1 brad { 1546 1.1 brad .text = "OFF", 1547 1.1 brad }, 1548 1.1 brad { 1549 1.1 brad .text = "VDD", 1550 1.1 brad } 1551 1.1 brad }; 1552 1.1 brad 1553 1.1 brad int 1554 1.1 brad umcpmio_verify_dac_sysctl(SYSCTLFN_ARGS) 1555 1.1 brad { 1556 1.1 brad char buf[UMCPMIO_VREF_NAME]; 1557 1.1 brad char cbuf[UMCPMIO_VREF_NAME]; 1558 1.1 brad struct umcpmio_softc *sc; 1559 1.1 brad struct sysctlnode node; 1560 1.1 brad int error = 0; 1561 1.1 brad int vrm; 1562 1.1 brad size_t i; 1563 1.1 brad struct mcp2221_get_sram_res sram_res; 1564 1.1 brad 1565 1.1 brad node = *rnode; 1566 1.1 brad sc = node.sysctl_data; 1567 1.1 brad 1568 1.1 brad mutex_enter(&sc->sc_action_mutex); 1569 1.1 brad 1570 1.1 brad error = umcpmio_get_sram(sc, &sram_res, false); 1571 1.1 brad if (error) 1572 1.1 brad goto out; 1573 1.1 brad 1574 1.2 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 1575 1.2 riastrad (uint8_t *)&sram_res, MCP2221_RES_BUFFER_SIZE, 1576 1.2 riastrad "umcpmio_verify_dac_sysctl SRAM res buffer"); 1577 1.1 brad 1578 1.1 brad if (sram_res.dac_reference_voltage & MCP2221_SRAM_DAC_IS_VRM) { 1579 1.2 riastrad vrm = sram_res.dac_reference_voltage & 1580 1.2 riastrad MCP2221_SRAM_DAC_VRM_MASK; 1581 1.1 brad switch (vrm) { 1582 1.1 brad case MCP2221_SRAM_DAC_VRM_4096V: 1583 1.1 brad strncpy(buf, "4.096V", UMCPMIO_VREF_NAME); 1584 1.1 brad break; 1585 1.1 brad case MCP2221_SRAM_DAC_VRM_2048V: 1586 1.1 brad strncpy(buf, "2.048V", UMCPMIO_VREF_NAME); 1587 1.1 brad break; 1588 1.1 brad case MCP2221_SRAM_DAC_VRM_1024V: 1589 1.1 brad strncpy(buf, "1.024V", UMCPMIO_VREF_NAME); 1590 1.1 brad break; 1591 1.1 brad case MCP2221_SRAM_DAC_VRM_OFF: 1592 1.1 brad default: 1593 1.1 brad strncpy(buf, "OFF", UMCPMIO_VREF_NAME); 1594 1.1 brad break; 1595 1.1 brad } 1596 1.1 brad } else { 1597 1.1 brad strncpy(buf, "VDD", UMCPMIO_VREF_NAME); 1598 1.1 brad } 1599 1.1 brad strncpy(cbuf, buf, UMCPMIO_VREF_NAME); 1600 1.1 brad node.sysctl_data = buf; 1601 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1602 1.1 brad if (error || newp == NULL) 1603 1.1 brad goto out; 1604 1.1 brad 1605 1.1 brad for (i = 0; i < __arraycount(umcpmio_vref_names); i++) { 1606 1.1 brad if (strncmp(node.sysctl_data, umcpmio_vref_names[i].text, 1607 1.1 brad UMCPMIO_VREF_NAME) == 0) { 1608 1.1 brad break; 1609 1.1 brad } 1610 1.1 brad } 1611 1.3 riastrad if (i == __arraycount(umcpmio_vref_names)) { 1612 1.1 brad error = EINVAL; 1613 1.3 riastrad goto out; 1614 1.3 riastrad } 1615 1.1 brad 1616 1.3 riastrad if (strncmp(cbuf, buf, UMCPMIO_VREF_NAME) == 0) { 1617 1.3 riastrad error = 0; 1618 1.3 riastrad goto out; 1619 1.1 brad } 1620 1.1 brad 1621 1.3 riastrad DPRINTF(("umcpmio_verify_dac_sysctl: setting DAC vref: %s\n", buf)); 1622 1.3 riastrad error = umcpmio_set_dac_vref_one(sc, buf, false); 1623 1.3 riastrad 1624 1.1 brad out: 1625 1.1 brad mutex_exit(&sc->sc_action_mutex); 1626 1.1 brad return error; 1627 1.1 brad } 1628 1.1 brad 1629 1.1 brad int 1630 1.1 brad umcpmio_verify_adc_sysctl(SYSCTLFN_ARGS) 1631 1.1 brad { 1632 1.1 brad char buf[UMCPMIO_VREF_NAME]; 1633 1.1 brad char cbuf[UMCPMIO_VREF_NAME]; 1634 1.1 brad struct umcpmio_softc *sc; 1635 1.1 brad struct sysctlnode node; 1636 1.1 brad int error = 0; 1637 1.1 brad int vrm; 1638 1.1 brad size_t i; 1639 1.1 brad struct mcp2221_get_sram_res sram_res; 1640 1.1 brad 1641 1.1 brad node = *rnode; 1642 1.1 brad sc = node.sysctl_data; 1643 1.1 brad 1644 1.1 brad mutex_enter(&sc->sc_action_mutex); 1645 1.1 brad 1646 1.1 brad error = umcpmio_get_sram(sc, &sram_res, false); 1647 1.1 brad if (error) 1648 1.1 brad goto out; 1649 1.1 brad 1650 1.1 brad if (sram_res.irq_adc_reference_voltage & MCP2221_SRAM_ADC_IS_VRM) { 1651 1.2 riastrad vrm = sram_res.irq_adc_reference_voltage & 1652 1.2 riastrad MCP2221_SRAM_ADC_VRM_MASK; 1653 1.1 brad switch (vrm) { 1654 1.1 brad case MCP2221_SRAM_ADC_VRM_4096V: 1655 1.1 brad strncpy(buf, "4.096V", UMCPMIO_VREF_NAME); 1656 1.1 brad break; 1657 1.1 brad case MCP2221_SRAM_ADC_VRM_2048V: 1658 1.1 brad strncpy(buf, "2.048V", UMCPMIO_VREF_NAME); 1659 1.1 brad break; 1660 1.1 brad case MCP2221_SRAM_ADC_VRM_1024V: 1661 1.1 brad strncpy(buf, "1.024V", UMCPMIO_VREF_NAME); 1662 1.1 brad break; 1663 1.1 brad case MCP2221_SRAM_ADC_VRM_OFF: 1664 1.1 brad default: 1665 1.1 brad strncpy(buf, "OFF", UMCPMIO_VREF_NAME); 1666 1.1 brad break; 1667 1.1 brad } 1668 1.1 brad } else { 1669 1.1 brad strncpy(buf, "VDD", UMCPMIO_VREF_NAME); 1670 1.1 brad } 1671 1.1 brad strncpy(cbuf, buf, UMCPMIO_VREF_NAME); 1672 1.1 brad node.sysctl_data = buf; 1673 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1674 1.1 brad if (error || newp == NULL) 1675 1.1 brad goto out; 1676 1.1 brad 1677 1.1 brad for (i = 0; i < __arraycount(umcpmio_vref_names); i++) { 1678 1.1 brad if (strncmp(node.sysctl_data, umcpmio_vref_names[i].text, 1679 1.1 brad UMCPMIO_VREF_NAME) == 0) { 1680 1.1 brad break; 1681 1.1 brad } 1682 1.1 brad } 1683 1.3 riastrad if (i == __arraycount(umcpmio_vref_names)) { 1684 1.1 brad error = EINVAL; 1685 1.3 riastrad goto out; 1686 1.3 riastrad } 1687 1.1 brad 1688 1.3 riastrad if (strncmp(cbuf, buf, UMCPMIO_VREF_NAME) == 0) { 1689 1.3 riastrad error = 0; 1690 1.3 riastrad goto out; 1691 1.1 brad } 1692 1.1 brad 1693 1.3 riastrad DPRINTF(("umcpmio_verify_adc_sysctl: setting ADC vref: %s\n", buf)); 1694 1.3 riastrad error = umcpmio_set_adc_vref_one(sc, buf, false); 1695 1.3 riastrad 1696 1.1 brad out: 1697 1.1 brad mutex_exit(&sc->sc_action_mutex); 1698 1.1 brad return error; 1699 1.1 brad } 1700 1.1 brad 1701 1.1 brad static struct umcpmio_sysctl_name umcpmio_dc_names[] = { 1702 1.1 brad { 1703 1.1 brad .text = "75%", 1704 1.1 brad }, 1705 1.1 brad { 1706 1.1 brad .text = "50%", 1707 1.1 brad }, 1708 1.1 brad { 1709 1.1 brad .text = "25%", 1710 1.1 brad }, 1711 1.1 brad { 1712 1.1 brad .text = "0%", 1713 1.1 brad } 1714 1.1 brad }; 1715 1.1 brad 1716 1.1 brad static int 1717 1.1 brad umcpmio_verify_gpioclock_dc_sysctl(SYSCTLFN_ARGS) 1718 1.1 brad { 1719 1.1 brad char buf[UMCPMIO_VREF_NAME]; 1720 1.1 brad char cbuf[UMCPMIO_VREF_NAME]; 1721 1.1 brad struct umcpmio_softc *sc; 1722 1.1 brad struct sysctlnode node; 1723 1.1 brad int error = 0; 1724 1.1 brad uint8_t duty_cycle; 1725 1.1 brad size_t i; 1726 1.1 brad struct mcp2221_get_sram_res sram_res; 1727 1.1 brad 1728 1.1 brad node = *rnode; 1729 1.1 brad sc = node.sysctl_data; 1730 1.1 brad 1731 1.1 brad mutex_enter(&sc->sc_action_mutex); 1732 1.1 brad 1733 1.1 brad error = umcpmio_get_sram(sc, &sram_res, false); 1734 1.1 brad if (error) 1735 1.1 brad goto out; 1736 1.1 brad 1737 1.1 brad duty_cycle = sram_res.clock_divider & MCP2221_SRAM_GPIO_CLOCK_DC_MASK; 1738 1.2 riastrad DPRINTF(("umcpmio_verify_gpioclock_dc_sysctl: current duty cycle:" 1739 1.2 riastrad " %02x\n", duty_cycle)); 1740 1.1 brad switch (duty_cycle) { 1741 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_DC_75: 1742 1.1 brad strncpy(buf, "75%", UMCPMIO_DC_NAME); 1743 1.1 brad break; 1744 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_DC_50: 1745 1.1 brad strncpy(buf, "50%", UMCPMIO_DC_NAME); 1746 1.1 brad break; 1747 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_DC_25: 1748 1.1 brad strncpy(buf, "25%", UMCPMIO_DC_NAME); 1749 1.1 brad break; 1750 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_DC_0: 1751 1.1 brad default: 1752 1.1 brad strncpy(buf, "0%", UMCPMIO_DC_NAME); 1753 1.1 brad break; 1754 1.1 brad } 1755 1.1 brad strncpy(cbuf, buf, UMCPMIO_VREF_NAME); 1756 1.1 brad node.sysctl_data = buf; 1757 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1758 1.1 brad if (error || newp == NULL) 1759 1.1 brad goto out; 1760 1.1 brad 1761 1.1 brad for (i = 0; i < __arraycount(umcpmio_dc_names); i++) { 1762 1.1 brad if (strncmp(node.sysctl_data, umcpmio_dc_names[i].text, 1763 1.1 brad UMCPMIO_VREF_NAME) == 0) { 1764 1.1 brad break; 1765 1.1 brad } 1766 1.1 brad } 1767 1.3 riastrad if (i == __arraycount(umcpmio_dc_names)) { 1768 1.1 brad error = EINVAL; 1769 1.3 riastrad goto out; 1770 1.3 riastrad } 1771 1.1 brad 1772 1.3 riastrad if (strncmp(cbuf, buf, UMCPMIO_VREF_NAME) == 0) { 1773 1.3 riastrad error = 0; 1774 1.3 riastrad goto out; 1775 1.1 brad } 1776 1.1 brad 1777 1.3 riastrad DPRINTF(("umcpmio_verify_gpioclock_dc_sysctl:" 1778 1.3 riastrad " setting GPIO clock duty cycle: %s\n", buf)); 1779 1.3 riastrad error = umcpmio_set_gpioclock_dc_one(sc, buf, false); 1780 1.3 riastrad 1781 1.1 brad out: 1782 1.1 brad mutex_exit(&sc->sc_action_mutex); 1783 1.1 brad return error; 1784 1.1 brad } 1785 1.1 brad 1786 1.1 brad static struct umcpmio_sysctl_name umcpmio_cd_names[] = { 1787 1.1 brad { 1788 1.1 brad .text = "375kHz", 1789 1.1 brad }, 1790 1.1 brad { 1791 1.1 brad .text = "750kHz", 1792 1.1 brad }, 1793 1.1 brad { 1794 1.1 brad .text = "1.5MHz", 1795 1.1 brad }, 1796 1.1 brad { 1797 1.1 brad .text = "3MHz", 1798 1.1 brad }, 1799 1.1 brad { 1800 1.1 brad .text = "6MHz", 1801 1.1 brad }, 1802 1.1 brad { 1803 1.1 brad .text = "12MHz", 1804 1.1 brad }, 1805 1.1 brad { 1806 1.1 brad .text = "24MHz", 1807 1.1 brad } 1808 1.1 brad }; 1809 1.1 brad 1810 1.1 brad static int 1811 1.1 brad umcpmio_verify_gpioclock_cd_sysctl(SYSCTLFN_ARGS) 1812 1.1 brad { 1813 1.1 brad char buf[UMCPMIO_CD_NAME]; 1814 1.1 brad char cbuf[UMCPMIO_CD_NAME]; 1815 1.1 brad struct umcpmio_softc *sc; 1816 1.1 brad struct sysctlnode node; 1817 1.1 brad int error = 0; 1818 1.1 brad uint8_t clock_divider; 1819 1.1 brad size_t i; 1820 1.1 brad struct mcp2221_get_sram_res sram_res; 1821 1.1 brad 1822 1.1 brad node = *rnode; 1823 1.1 brad sc = node.sysctl_data; 1824 1.1 brad 1825 1.1 brad mutex_enter(&sc->sc_action_mutex); 1826 1.1 brad 1827 1.1 brad error = umcpmio_get_sram(sc, &sram_res, false); 1828 1.1 brad if (error) 1829 1.1 brad goto out; 1830 1.1 brad 1831 1.2 riastrad clock_divider = sram_res.clock_divider & 1832 1.2 riastrad MCP2221_SRAM_GPIO_CLOCK_CD_MASK; 1833 1.2 riastrad DPRINTF(("umcpmio_verify_gpioclock_cd_sysctl: current clock divider:" 1834 1.2 riastrad " %02x\n", clock_divider)); 1835 1.1 brad switch (clock_divider) { 1836 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_375KHZ: 1837 1.1 brad strncpy(buf, "375kHz", UMCPMIO_CD_NAME); 1838 1.1 brad break; 1839 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_750KHZ: 1840 1.1 brad strncpy(buf, "750kHz", UMCPMIO_CD_NAME); 1841 1.1 brad break; 1842 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_1P5MHZ: 1843 1.1 brad strncpy(buf, "1.5MHz", UMCPMIO_CD_NAME); 1844 1.1 brad break; 1845 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_3MHZ: 1846 1.1 brad strncpy(buf, "3MHz", UMCPMIO_CD_NAME); 1847 1.1 brad break; 1848 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_6MHZ: 1849 1.1 brad strncpy(buf, "6MHz", UMCPMIO_CD_NAME); 1850 1.1 brad break; 1851 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_12MHZ: 1852 1.1 brad strncpy(buf, "12MHz", UMCPMIO_CD_NAME); 1853 1.1 brad break; 1854 1.1 brad case MCP2221_SRAM_GPIO_CLOCK_CD_24MHZ: 1855 1.1 brad strncpy(buf, "24MHz", UMCPMIO_CD_NAME); 1856 1.1 brad break; 1857 1.1 brad default: 1858 1.1 brad strncpy(buf, "12MHz", UMCPMIO_CD_NAME); 1859 1.1 brad break; 1860 1.1 brad } 1861 1.1 brad strncpy(cbuf, buf, UMCPMIO_CD_NAME); 1862 1.1 brad node.sysctl_data = buf; 1863 1.1 brad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1864 1.1 brad if (error || newp == NULL) 1865 1.1 brad goto out; 1866 1.1 brad 1867 1.1 brad for (i = 0; i < __arraycount(umcpmio_cd_names); i++) { 1868 1.1 brad if (strncmp(node.sysctl_data, umcpmio_cd_names[i].text, 1869 1.1 brad UMCPMIO_CD_NAME) == 0) { 1870 1.1 brad break; 1871 1.1 brad } 1872 1.1 brad } 1873 1.3 riastrad if (i == __arraycount(umcpmio_cd_names)) { 1874 1.1 brad error = EINVAL; 1875 1.3 riastrad goto out; 1876 1.3 riastrad } 1877 1.1 brad 1878 1.3 riastrad if (strncmp(cbuf, buf, UMCPMIO_CD_NAME) == 0) { 1879 1.3 riastrad error = 0; 1880 1.3 riastrad goto out; 1881 1.1 brad } 1882 1.1 brad 1883 1.3 riastrad DPRINTF(("umcpmio_verify_gpioclock_cd_sysctl:" 1884 1.3 riastrad " setting GPIO clock clock divider: %s\n", 1885 1.3 riastrad buf)); 1886 1.3 riastrad error = umcpmio_set_gpioclock_cd_one(sc, buf, false); 1887 1.3 riastrad 1888 1.1 brad out: 1889 1.1 brad mutex_exit(&sc->sc_action_mutex); 1890 1.1 brad return error; 1891 1.1 brad } 1892 1.1 brad 1893 1.1 brad static int 1894 1.1 brad umcpmio_sysctl_init(struct umcpmio_softc *sc) 1895 1.1 brad { 1896 1.1 brad int error; 1897 1.1 brad const struct sysctlnode *cnode; 1898 1.1 brad int sysctlroot_num, i2c_num, adc_dac_num, adc_num, dac_num, gpio_num; 1899 1.1 brad 1900 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1901 1.1 brad 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 1902 1.2 riastrad SYSCTL_DESCR("mcpmio controls"), 1903 1.2 riastrad NULL, 0, NULL, 0, 1904 1.2 riastrad CTL_HW, CTL_CREATE, CTL_EOL)) != 0) 1905 1.1 brad return error; 1906 1.1 brad 1907 1.1 brad sysctlroot_num = cnode->sysctl_num; 1908 1.1 brad 1909 1.1 brad #ifdef UMCPMIO_DEBUG 1910 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1911 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 1912 1.2 riastrad SYSCTL_DESCR("Debug level"), 1913 1.2 riastrad umcpmio_verify_sysctl, 0, &umcpmiodebug, 0, 1914 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1915 1.1 brad return error; 1916 1.1 brad 1917 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1918 1.1 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "dump_buffers", 1919 1.2 riastrad SYSCTL_DESCR("Dump buffer when debugging"), 1920 1.2 riastrad NULL, 0, &sc->sc_dumpbuffer, 0, 1921 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1922 1.1 brad return error; 1923 1.1 brad #endif 1924 1.1 brad 1925 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1926 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "response_wait", 1927 1.2 riastrad SYSCTL_DESCR("How long to wait in ms for a response" 1928 1.2 riastrad " for a HID report"), 1929 1.2 riastrad umcpmio_verify_sysctl, 0, &sc->sc_cv_wait, 0, 1930 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1931 1.1 brad return error; 1932 1.1 brad 1933 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1934 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "response_errcnt", 1935 1.1 brad SYSCTL_DESCR("How many errors to allow on a response"), 1936 1.2 riastrad umcpmio_verify_sysctl, 0, &sc->sc_response_errcnt, 0, 1937 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1938 1.1 brad return error; 1939 1.1 brad 1940 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1941 1.1 brad 0, CTLTYPE_NODE, "i2c", 1942 1.2 riastrad SYSCTL_DESCR("I2C controls"), 1943 1.2 riastrad NULL, 0, NULL, 0, 1944 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1945 1.1 brad return error; 1946 1.1 brad 1947 1.1 brad i2c_num = cnode->sysctl_num; 1948 1.1 brad 1949 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1950 1.1 brad 0, CTLTYPE_NODE, "adcdac", 1951 1.2 riastrad SYSCTL_DESCR("ADC and DAC controls"), 1952 1.2 riastrad NULL, 0, NULL, 0, 1953 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1954 1.1 brad return error; 1955 1.1 brad 1956 1.1 brad adc_dac_num = cnode->sysctl_num; 1957 1.1 brad 1958 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1959 1.1 brad 0, CTLTYPE_NODE, "adc", 1960 1.2 riastrad SYSCTL_DESCR("ADC controls"), 1961 1.2 riastrad NULL, 0, NULL, 0, 1962 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1963 1.1 brad return error; 1964 1.1 brad 1965 1.1 brad adc_num = cnode->sysctl_num; 1966 1.1 brad 1967 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1968 1.1 brad 0, CTLTYPE_NODE, "dac", 1969 1.2 riastrad SYSCTL_DESCR("DAC controls"), 1970 1.2 riastrad NULL, 0, NULL, 0, 1971 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1972 1.1 brad return error; 1973 1.1 brad 1974 1.1 brad dac_num = cnode->sysctl_num; 1975 1.1 brad 1976 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1977 1.1 brad 0, CTLTYPE_NODE, "gpio", 1978 1.2 riastrad SYSCTL_DESCR("GPIO controls"), 1979 1.2 riastrad NULL, 0, NULL, 0, 1980 1.2 riastrad CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 1981 1.1 brad return error; 1982 1.1 brad 1983 1.1 brad gpio_num = cnode->sysctl_num; 1984 1.1 brad 1985 1.1 brad /* I2C */ 1986 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1987 1.1 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "reportreadnostop", 1988 1.2 riastrad SYSCTL_DESCR("Report that a READ without STOP was attempted" 1989 1.2 riastrad " by a device"), 1990 1.2 riastrad NULL, 0, &sc->sc_reportreadnostop, 0, 1991 1.2 riastrad CTL_HW, sysctlroot_num, i2c_num, CTL_CREATE, CTL_EOL)) != 0) 1992 1.1 brad return error; 1993 1.1 brad 1994 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 1995 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "busy_delay", 1996 1.1 brad SYSCTL_DESCR("How long to wait in ms when the I2C engine is busy"), 1997 1.2 riastrad umcpmio_verify_sysctl, 0, &sc->sc_busy_delay, 0, 1998 1.2 riastrad CTL_HW, sysctlroot_num, i2c_num, CTL_CREATE, CTL_EOL)) != 0) 1999 1.1 brad return error; 2000 1.1 brad 2001 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2002 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "retry_busy_read", 2003 1.1 brad SYSCTL_DESCR("How many times to retry a busy I2C read"), 2004 1.2 riastrad umcpmio_verify_sysctl, 0, &sc->sc_retry_busy_read, 0, 2005 1.2 riastrad CTL_HW, sysctlroot_num, i2c_num, CTL_CREATE, CTL_EOL)) != 0) 2006 1.1 brad return error; 2007 1.1 brad 2008 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2009 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "retry_busy_write", 2010 1.1 brad SYSCTL_DESCR("How many times to retry a busy I2C write"), 2011 1.2 riastrad umcpmio_verify_sysctl, 0, &sc->sc_retry_busy_write, 0, 2012 1.2 riastrad CTL_HW, sysctlroot_num, i2c_num, CTL_CREATE, CTL_EOL)) != 0) 2013 1.1 brad return error; 2014 1.1 brad 2015 1.1 brad /* GPIO */ 2016 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2017 1.1 brad CTLFLAG_READWRITE, CTLTYPE_INT, "irq_poll", 2018 1.1 brad SYSCTL_DESCR("How often to poll for a IRQ change"), 2019 1.2 riastrad umcpmio_verify_sysctl, 0, &sc->sc_irq_poll, 0, 2020 1.2 riastrad CTL_HW, sysctlroot_num, gpio_num, CTL_CREATE, CTL_EOL)) != 0) 2021 1.1 brad return error; 2022 1.1 brad 2023 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2024 1.1 brad CTLFLAG_READONLY, CTLTYPE_STRING, "clock_duty_cycles", 2025 1.2 riastrad SYSCTL_DESCR("Valid duty cycles for GPIO clock on" 2026 1.2 riastrad " GP1 ALT3 duty cycle"), 2027 1.2 riastrad 0, 0, __UNCONST(umcpmio_valid_dcs), sizeof(umcpmio_valid_dcs) + 1, 2028 1.2 riastrad CTL_HW, sysctlroot_num, gpio_num, CTL_CREATE, CTL_EOL)) != 0) 2029 1.1 brad return error; 2030 1.1 brad 2031 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2032 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "clock_duty_cycle", 2033 1.1 brad SYSCTL_DESCR("GPIO clock on GP1 ALT3 duty cycle"), 2034 1.2 riastrad umcpmio_verify_gpioclock_dc_sysctl, 0, (void *)sc, UMCPMIO_DC_NAME, 2035 1.2 riastrad CTL_HW, sysctlroot_num, gpio_num, CTL_CREATE, CTL_EOL)) != 0) 2036 1.1 brad return error; 2037 1.1 brad 2038 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2039 1.1 brad CTLFLAG_READONLY, CTLTYPE_STRING, "clock_dividers", 2040 1.2 riastrad SYSCTL_DESCR("Valid clock dividers for GPIO clock on GP1" 2041 1.2 riastrad " with ALT3"), 2042 1.2 riastrad 0, 0, __UNCONST(umcpmio_valid_cds), sizeof(umcpmio_valid_cds) + 1, 2043 1.2 riastrad CTL_HW, sysctlroot_num, gpio_num, CTL_CREATE, CTL_EOL)) != 0) 2044 1.1 brad return error; 2045 1.1 brad 2046 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2047 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "clock_divider", 2048 1.1 brad SYSCTL_DESCR("GPIO clock on GP1 ALT3 clock divider"), 2049 1.2 riastrad umcpmio_verify_gpioclock_cd_sysctl, 0, (void *)sc, UMCPMIO_CD_NAME, 2050 1.2 riastrad CTL_HW, sysctlroot_num, gpio_num, CTL_CREATE, CTL_EOL)) != 0) 2051 1.1 brad return error; 2052 1.1 brad 2053 1.1 brad /* ADC and DAC */ 2054 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2055 1.1 brad CTLFLAG_READONLY, CTLTYPE_STRING, "vrefs", 2056 1.1 brad SYSCTL_DESCR("Valid vref values for ADC and DAC"), 2057 1.2 riastrad 0, 0, 2058 1.2 riastrad __UNCONST(umcpmio_valid_vrefs), sizeof(umcpmio_valid_vrefs) + 1, 2059 1.2 riastrad CTL_HW, sysctlroot_num, adc_dac_num, CTL_CREATE, CTL_EOL)) != 0) 2060 1.1 brad return error; 2061 1.1 brad 2062 1.1 brad /* ADC */ 2063 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2064 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "vref", 2065 1.1 brad SYSCTL_DESCR("ADC voltage reference"), 2066 1.2 riastrad umcpmio_verify_adc_sysctl, 0, (void *)sc, UMCPMIO_VREF_NAME, 2067 1.2 riastrad CTL_HW, sysctlroot_num, adc_num, CTL_CREATE, CTL_EOL)) != 0) 2068 1.1 brad return error; 2069 1.1 brad 2070 1.1 brad /* DAC */ 2071 1.1 brad if ((error = sysctl_createv(&sc->sc_umcpmiolog, 0, NULL, &cnode, 2072 1.1 brad CTLFLAG_READWRITE, CTLTYPE_STRING, "vref", 2073 1.1 brad SYSCTL_DESCR("DAC voltage reference"), 2074 1.2 riastrad umcpmio_verify_dac_sysctl, 0, (void *)sc, UMCPMIO_VREF_NAME, 2075 1.2 riastrad CTL_HW, sysctlroot_num, dac_num, CTL_CREATE, CTL_EOL)) != 0) 2076 1.1 brad return error; 2077 1.1 brad 2078 1.1 brad return 0; 2079 1.1 brad } 2080 1.1 brad 2081 1.1 brad static int 2082 1.1 brad umcpmio_match(device_t parent, cfdata_t match, void *aux) 2083 1.1 brad { 2084 1.1 brad struct uhidev_attach_arg *uha = aux; 2085 1.1 brad 2086 1.1 brad return umcpmio_lookup(uha->uiaa->uiaa_vendor, uha->uiaa->uiaa_product) 2087 1.1 brad != NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 2088 1.1 brad } 2089 1.1 brad 2090 1.2 riastrad /* 2091 1.2 riastrad * This driver could be extended to support the MCP-2210 which is MCP's 2092 1.2 riastrad * USB to SPI / gpio chip. It also appears to be a something like the 2093 1.2 riastrad * PIC16F1455 used in the MCP2221 / MCP2221A. It is likely that a lot 2094 1.2 riastrad * of this could use tables to drive behavior. 2095 1.1 brad */ 2096 1.1 brad 2097 1.1 brad static void 2098 1.1 brad umcpmio_attach(device_t parent, device_t self, void *aux) 2099 1.1 brad { 2100 1.1 brad struct umcpmio_softc *sc = device_private(self); 2101 1.1 brad struct uhidev_attach_arg *uha = aux; 2102 1.1 brad struct gpiobus_attach_args gba; 2103 1.3 riastrad struct mcp2221_status_res status_res; 2104 1.1 brad int err; 2105 1.1 brad 2106 1.1 brad sc->sc_dev = self; 2107 1.1 brad sc->sc_hdev = uha->parent; 2108 1.1 brad sc->sc_udev = uha->uiaa->uiaa_device; 2109 1.1 brad 2110 1.1 brad sc->sc_umcpmiolog = NULL; 2111 1.1 brad sc->sc_dumpbuffer = false; 2112 1.1 brad 2113 1.1 brad sc->sc_reportreadnostop = true; 2114 1.1 brad sc->sc_cv_wait = 2500; 2115 1.1 brad sc->sc_response_errcnt = 5; 2116 1.1 brad sc->sc_busy_delay = 1; 2117 1.1 brad sc->sc_retry_busy_read = 50; 2118 1.1 brad sc->sc_retry_busy_write = 50; 2119 1.1 brad sc->sc_irq_poll = 10; 2120 1.2 riastrad sc->sc_dev_open[CONTROL_DEV] = false; 2121 1.2 riastrad sc->sc_dev_open[GP1_DEV] = false; 2122 1.2 riastrad sc->sc_dev_open[GP2_DEV] = false; 2123 1.2 riastrad sc->sc_dev_open[GP3_DEV] = false; 2124 1.1 brad 2125 1.1 brad aprint_normal("\n"); 2126 1.1 brad 2127 1.1 brad if ((err = umcpmio_sysctl_init(sc)) != 0) { 2128 1.1 brad aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", err); 2129 1.1 brad return; 2130 1.1 brad } 2131 1.1 brad 2132 1.1 brad mutex_init(&sc->sc_action_mutex, MUTEX_DEFAULT, IPL_NONE); 2133 1.1 brad cv_init(&sc->sc_res_cv, "mcpres"); 2134 1.1 brad mutex_init(&sc->sc_res_mutex, MUTEX_DEFAULT, IPL_NONE); 2135 1.1 brad sc->sc_res_buffer = NULL; 2136 1.1 brad sc->sc_res_ready = false; 2137 1.1 brad 2138 1.1 brad err = uhidev_open(sc->sc_hdev, &umcpmio_uhidev_intr, sc); 2139 1.3 riastrad if (err) { 2140 1.3 riastrad aprint_error_dev(sc->sc_dev, "umcpmio_attach: " 2141 1.3 riastrad " uhidev_open: err=%d\n", err); 2142 1.3 riastrad return; 2143 1.3 riastrad } 2144 1.1 brad 2145 1.2 riastrad /* 2146 1.2 riastrad * It is not clear that this should be needed, but it was noted 2147 1.1 brad * that the device would sometimes not be ready if this delay 2148 1.2 riastrad * was not present. In fact, the attempts to set stuff a 2149 1.2 riastrad * little later would sometimes fail. 2150 1.1 brad */ 2151 1.1 brad 2152 1.1 brad delay(1000); 2153 1.1 brad 2154 1.3 riastrad err = umcpmio_get_status(sc, &status_res, true); 2155 1.2 riastrad if (err) { 2156 1.2 riastrad aprint_error_dev(sc->sc_dev, "umcpmio_attach: " 2157 1.3 riastrad " umcpmio_get_status: err=%d\n", err); 2158 1.3 riastrad return; 2159 1.2 riastrad } 2160 1.1 brad 2161 1.3 riastrad aprint_normal_dev(sc->sc_dev, 2162 1.3 riastrad "Hardware revision: %d.%d, Firmware revision: %d.%d\n", 2163 1.3 riastrad status_res.mcp2221_hardware_rev_major, 2164 1.3 riastrad status_res.mcp2221_hardware_rev_minor, 2165 1.3 riastrad status_res.mcp2221_firmware_rev_major, 2166 1.3 riastrad status_res.mcp2221_firmware_rev_minor); 2167 1.3 riastrad 2168 1.3 riastrad /* 2169 1.3 riastrad * The datasheet suggests that it is possble for this 2170 1.3 riastrad * to fail if the I2C port is currently being used. 2171 1.3 riastrad * However... since you just plugged in the chip, the 2172 1.3 riastrad * I2C port should not really be in use at that moment. 2173 1.3 riastrad * In any case, try hard to set this and don't make it 2174 1.3 riastrad * fatal if it did not get set. 2175 1.3 riastrad */ 2176 1.3 riastrad int i2cspeed; 2177 1.3 riastrad for (i2cspeed = 0; i2cspeed < 3; i2cspeed++) { 2178 1.3 riastrad err = umcpmio_set_i2c_speed_one(sc, I2C_SPEED_SM, true); 2179 1.3 riastrad if (err) { 2180 1.3 riastrad aprint_error_dev(sc->sc_dev, "umcpmio_attach:" 2181 1.3 riastrad " set I2C speed: err=%d\n", 2182 1.3 riastrad err); 2183 1.3 riastrad delay(300); 2184 1.3 riastrad } 2185 1.3 riastrad break; 2186 1.3 riastrad } 2187 1.1 brad 2188 1.3 riastrad struct mcp2221_get_sram_res get_sram_res; 2189 1.3 riastrad err = umcpmio_get_sram(sc, &get_sram_res, true); 2190 1.3 riastrad if (err) { 2191 1.3 riastrad aprint_error_dev(sc->sc_dev, "umcpmio_attach:" 2192 1.3 riastrad " get sram error: err=%d\n", 2193 1.3 riastrad err); 2194 1.3 riastrad return; 2195 1.3 riastrad } 2196 1.1 brad 2197 1.3 riastrad umcpmio_dump_buffer(sc->sc_dumpbuffer, 2198 1.3 riastrad (uint8_t *)&get_sram_res, MCP2221_RES_BUFFER_SIZE, 2199 1.3 riastrad "umcpmio_attach get sram buffer copy"); 2200 1.1 brad 2201 1.3 riastrad /* 2202 1.3 riastrad * There are only 4 pins right now, just unroll 2203 1.3 riastrad * any loops 2204 1.3 riastrad */ 2205 1.1 brad 2206 1.3 riastrad sc->sc_gpio_pins[0].pin_num = 0; 2207 1.3 riastrad sc->sc_gpio_pins[0].pin_caps = GPIO_PIN_INPUT; 2208 1.3 riastrad sc->sc_gpio_pins[0].pin_caps |= GPIO_PIN_OUTPUT; 2209 1.3 riastrad sc->sc_gpio_pins[0].pin_caps |= GPIO_PIN_ALT0; 2210 1.3 riastrad sc->sc_gpio_pins[0].pin_caps |= GPIO_PIN_ALT3; 2211 1.3 riastrad sc->sc_gpio_pins[0].pin_flags = 2212 1.3 riastrad umcpmio_sram_gpio_to_flags(get_sram_res.gp0_settings); 2213 1.3 riastrad sc->sc_gpio_pins[0].pin_intrcaps = 0; 2214 1.3 riastrad snprintf(sc->sc_gpio_pins[0].pin_defname, 4, "GP0"); 2215 1.3 riastrad 2216 1.3 riastrad sc->sc_gpio_pins[1].pin_num = 1; 2217 1.3 riastrad sc->sc_gpio_pins[1].pin_caps = GPIO_PIN_INPUT; 2218 1.3 riastrad sc->sc_gpio_pins[1].pin_caps |= GPIO_PIN_OUTPUT; 2219 1.3 riastrad sc->sc_gpio_pins[1].pin_caps |= GPIO_PIN_ALT0; 2220 1.3 riastrad sc->sc_gpio_pins[1].pin_caps |= GPIO_PIN_ALT1; 2221 1.3 riastrad sc->sc_gpio_pins[1].pin_caps |= GPIO_PIN_ALT2; 2222 1.3 riastrad sc->sc_gpio_pins[1].pin_caps |= GPIO_PIN_ALT3; 2223 1.3 riastrad sc->sc_gpio_pins[1].pin_flags = 2224 1.3 riastrad umcpmio_sram_gpio_to_flags(get_sram_res.gp1_settings); 2225 1.3 riastrad /* XXX - lets not advertise this right now... */ 2226 1.1 brad #if 0 2227 1.3 riastrad sc->sc_gpio_pins[1].pin_intrcaps = GPIO_INTR_POS_EDGE; 2228 1.3 riastrad sc->sc_gpio_pins[1].pin_intrcaps |= GPIO_INTR_NEG_EDGE; 2229 1.3 riastrad sc->sc_gpio_pins[1].pin_intrcaps |= GPIO_INTR_DOUBLE_EDGE; 2230 1.3 riastrad sc->sc_gpio_pins[1].pin_intrcaps |= GPIO_INTR_MPSAFE; 2231 1.1 brad #endif 2232 1.3 riastrad sc->sc_gpio_pins[1].pin_intrcaps = 0; 2233 1.3 riastrad snprintf(sc->sc_gpio_pins[1].pin_defname, 4, "GP1"); 2234 1.1 brad 2235 1.3 riastrad sc->sc_gpio_pins[2].pin_num = 2; 2236 1.3 riastrad sc->sc_gpio_pins[2].pin_caps = GPIO_PIN_INPUT; 2237 1.3 riastrad sc->sc_gpio_pins[2].pin_caps |= GPIO_PIN_OUTPUT; 2238 1.3 riastrad sc->sc_gpio_pins[2].pin_caps |= GPIO_PIN_ALT0; 2239 1.3 riastrad sc->sc_gpio_pins[2].pin_caps |= GPIO_PIN_ALT1; 2240 1.3 riastrad sc->sc_gpio_pins[2].pin_caps |= GPIO_PIN_ALT3; 2241 1.3 riastrad sc->sc_gpio_pins[2].pin_flags = 2242 1.3 riastrad umcpmio_sram_gpio_to_flags(get_sram_res.gp2_settings); 2243 1.3 riastrad sc->sc_gpio_pins[2].pin_intrcaps = 0; 2244 1.3 riastrad snprintf(sc->sc_gpio_pins[2].pin_defname, 4, "GP2"); 2245 1.3 riastrad 2246 1.3 riastrad sc->sc_gpio_pins[3].pin_num = 3; 2247 1.3 riastrad sc->sc_gpio_pins[3].pin_caps = GPIO_PIN_INPUT; 2248 1.3 riastrad sc->sc_gpio_pins[3].pin_caps |= GPIO_PIN_OUTPUT; 2249 1.3 riastrad sc->sc_gpio_pins[3].pin_caps |= GPIO_PIN_ALT0; 2250 1.3 riastrad sc->sc_gpio_pins[3].pin_caps |= GPIO_PIN_ALT1; 2251 1.3 riastrad sc->sc_gpio_pins[3].pin_caps |= GPIO_PIN_ALT3; 2252 1.3 riastrad sc->sc_gpio_pins[3].pin_flags = 2253 1.3 riastrad umcpmio_sram_gpio_to_flags(get_sram_res.gp3_settings); 2254 1.3 riastrad sc->sc_gpio_pins[3].pin_intrcaps = 0; 2255 1.3 riastrad snprintf(sc->sc_gpio_pins[3].pin_defname, 4, "GP3"); 2256 1.3 riastrad 2257 1.3 riastrad sc->sc_gpio_gc.gp_cookie = sc; 2258 1.3 riastrad sc->sc_gpio_gc.gp_pin_read = umcpmio_gpio_pin_read; 2259 1.3 riastrad sc->sc_gpio_gc.gp_pin_write = umcpmio_gpio_pin_write; 2260 1.3 riastrad sc->sc_gpio_gc.gp_pin_ctl = umcpmio_gpio_pin_ctl; 2261 1.3 riastrad 2262 1.3 riastrad sc->sc_gpio_gc.gp_intr_establish = umcpmio_gpio_intr_establish; 2263 1.3 riastrad sc->sc_gpio_gc.gp_intr_disestablish = umcpmio_gpio_intr_disestablish; 2264 1.3 riastrad sc->sc_gpio_gc.gp_intr_str = umcpmio_gpio_intrstr; 2265 1.3 riastrad 2266 1.3 riastrad gba.gba_gc = &sc->sc_gpio_gc; 2267 1.3 riastrad gba.gba_pins = sc->sc_gpio_pins; 2268 1.3 riastrad gba.gba_npins = MCP2221_NPINS; 2269 1.3 riastrad 2270 1.3 riastrad sc->sc_gpio_dev = config_found(self, &gba, gpiobus_print, 2271 1.3 riastrad CFARGS(.iattr = "gpiobus")); 2272 1.3 riastrad 2273 1.3 riastrad iic_tag_init(&sc->sc_i2c_tag); 2274 1.3 riastrad sc->sc_i2c_tag.ic_cookie = sc; 2275 1.3 riastrad sc->sc_i2c_tag.ic_acquire_bus = umcpmio_acquire_bus; 2276 1.3 riastrad sc->sc_i2c_tag.ic_release_bus = umcpmio_release_bus; 2277 1.3 riastrad sc->sc_i2c_tag.ic_exec = umcpmio_i2c_exec; 2278 1.3 riastrad 2279 1.7 thorpej sc->sc_i2c_dev = iicbus_attach(self, &sc->sc_i2c_tag); 2280 1.1 brad } 2281 1.1 brad 2282 1.1 brad static int 2283 1.1 brad umcpmio_detach(device_t self, int flags) 2284 1.1 brad { 2285 1.1 brad struct umcpmio_softc *sc = device_private(self); 2286 1.1 brad int err; 2287 1.1 brad 2288 1.1 brad DPRINTF(("umcpmio_detach: sc=%p flags=%d\n", sc, flags)); 2289 1.1 brad 2290 1.1 brad mutex_enter(&sc->sc_action_mutex); 2291 1.1 brad sc->sc_dying = 1; 2292 1.1 brad 2293 1.1 brad err = config_detach_children(self, flags); 2294 1.1 brad if (err) 2295 1.1 brad return err; 2296 1.1 brad 2297 1.1 brad uhidev_close(sc->sc_hdev); 2298 1.1 brad 2299 1.1 brad mutex_destroy(&sc->sc_res_mutex); 2300 1.1 brad cv_destroy(&sc->sc_res_cv); 2301 1.1 brad 2302 1.1 brad sysctl_teardown(&sc->sc_umcpmiolog); 2303 1.1 brad 2304 1.1 brad mutex_exit(&sc->sc_action_mutex); 2305 1.1 brad mutex_destroy(&sc->sc_action_mutex); 2306 1.1 brad 2307 1.1 brad return 0; 2308 1.1 brad } 2309 1.1 brad 2310 1.1 brad static int 2311 1.1 brad umcpmio_activate(device_t self, enum devact act) 2312 1.1 brad { 2313 1.1 brad struct umcpmio_softc *sc = device_private(self); 2314 1.1 brad 2315 1.2 riastrad DPRINTFN(5, ("umcpmio_activate: %d\n", act)); 2316 1.1 brad 2317 1.1 brad switch (act) { 2318 1.1 brad case DVACT_DEACTIVATE: 2319 1.1 brad sc->sc_dying = 1; 2320 1.1 brad return 0; 2321 1.1 brad default: 2322 1.1 brad return EOPNOTSUPP; 2323 1.1 brad } 2324 1.1 brad } 2325