1 /* $NetBSD: umcpmio_spi.c,v 1.2 2025/12/12 17:49:35 andvar Exp $ */ 2 3 /* 4 * Copyright (c) 2025 Brad Spencer <brad (at) anduin.eldar.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/cdefs.h> 20 __KERNEL_RCSID(0, "$NetBSD: umcpmio_spi.c,v 1.2 2025/12/12 17:49:35 andvar Exp $"); 21 22 #ifdef _KERNEL_OPT 23 #include "opt_usb.h" 24 #endif 25 26 #include <sys/param.h> 27 #include <sys/types.h> 28 29 #include <dev/spi/spivar.h> 30 31 #include <dev/usb/umcpmio.h> 32 #include <dev/usb/umcpmio_hid_reports.h> 33 #include <dev/usb/umcpmio_transport.h> 34 #include <dev/usb/umcpmio_spi.h> 35 #include <dev/usb/umcpmio_gpio.h> 36 #include <dev/usb/umcpmio_subr.h> 37 38 #define UMCPMIO_DEBUG 1 39 #ifdef UMCPMIO_DEBUG 40 #define DPRINTF(x) do { if (umcpmiodebug) printf x; } while (0) 41 #define DPRINTFN(n, x) do { if (umcpmiodebug > (n)) printf x; } while (0) 42 extern int umcpmiodebug; 43 #else 44 #define DPRINTF(x) __nothing 45 #define DPRINTFN(n, x) __nothing 46 #endif 47 48 /* Stuff required for the SPI part of the MCP2210 */ 49 50 static int 51 mcp2210_get_spi_sram(struct umcpmio_softc *sc, 52 struct mcp2210_get_spi_sram_res *res) 53 { 54 struct mcp2210_get_spi_sram_req req; 55 int err = 0; 56 57 memset(&req, 0, MCP2210_REQ_BUFFER_SIZE); 58 req.cmd = MCP2210_CMD_GET_SPI_SRAM; 59 60 umcpmio_dump_buffer(sc->sc_dumpbuffer, 61 (uint8_t *) & req, MCP2210_REQ_BUFFER_SIZE, 62 "mcp2210_get_spi_sram req"); 63 64 mutex_enter(&sc->sc_action_mutex); 65 err = umcpmio_send_report(sc, 66 (uint8_t *) & req, MCP2210_REQ_BUFFER_SIZE, 67 (uint8_t *) res, sc->sc_cv_wait); 68 mutex_exit(&sc->sc_action_mutex); 69 70 umcpmio_dump_buffer(sc->sc_dumpbuffer, 71 (uint8_t *) res, MCP2210_RES_BUFFER_SIZE, 72 "mcp2210_get_spi_sram res"); 73 74 err = mcp2210_decode_errors(req.cmd, err, res->completion); 75 76 return err; 77 } 78 79 static int 80 mcp2210_set_spi_sram(struct umcpmio_softc *sc, 81 struct mcp2210_set_spi_sram_req *req, struct mcp2210_set_spi_sram_res *res) 82 { 83 int err = 0; 84 85 req->cmd = MCP2210_CMD_SET_SPI_SRAM; 86 87 umcpmio_dump_buffer(sc->sc_dumpbuffer, 88 (uint8_t *) req, MCP2210_REQ_BUFFER_SIZE, 89 "mcp2210_set_spi_sram req"); 90 91 mutex_enter(&sc->sc_action_mutex); 92 err = umcpmio_send_report(sc, 93 (uint8_t *) req, MCP2210_REQ_BUFFER_SIZE, 94 (uint8_t *) res, sc->sc_cv_wait); 95 mutex_exit(&sc->sc_action_mutex); 96 97 umcpmio_dump_buffer(sc->sc_dumpbuffer, 98 (uint8_t *) res, MCP2210_RES_BUFFER_SIZE, 99 "mcp2210_set_spi_sram res"); 100 101 err = mcp2210_decode_errors(req->cmd, err, res->completion); 102 103 return err; 104 } 105 106 static int 107 mcp2210_do_spi_transfer(struct umcpmio_softc *sc, 108 struct mcp2210_spi_transfer_req *req, struct mcp2210_spi_transfer_res *res) 109 { 110 int err = 0; 111 112 req->cmd = MCP2210_CMD_SPI_TRANSFER; 113 114 umcpmio_dump_buffer(sc->sc_dumpbuffer, 115 (uint8_t *) req, MCP2210_REQ_BUFFER_SIZE, 116 "mcp2210_do_spi_transfer req"); 117 118 mutex_enter(&sc->sc_action_mutex); 119 err = umcpmio_send_report(sc, 120 (uint8_t *) req, MCP2210_REQ_BUFFER_SIZE, 121 (uint8_t *) res, sc->sc_cv_wait); 122 mutex_exit(&sc->sc_action_mutex); 123 124 umcpmio_dump_buffer(sc->sc_dumpbuffer, 125 (uint8_t *) res, MCP2210_RES_BUFFER_SIZE, 126 "mcp2210_do_spi_transfer res"); 127 128 err = mcp2210_decode_errors(req->cmd, err, res->completion); 129 130 return err; 131 } 132 133 /* Most configuration is deferred until a transfer actually happens. The 134 * exception is setting the pin that is to be used as a CS to ALT0. 135 * 136 * There is no attempt to reset the mode of the pin used for the CS, 137 * as there is no concept of a session with the SPI framework. That is, 138 * you would never know when to do it. Further, it will cause pin 139 * flapping of all of the other pins if the CS is set to INPUT 140 * or OUTPUT. Of course, that will happen when the CS mode (ALT0) 141 * is set, but only the first time the pin is used as a CS. 142 * 143 * It is advisable to make use of the NVRAM to set up the pin mode 144 * upon boot up of the chip. 145 * 146 */ 147 148 static int 149 mcp2210_spi_configure(void *cookie, int slave, int mode, int speed) 150 { 151 struct umcpmio_softc *sc = cookie; 152 uint8_t desired_mode = 0; 153 struct umcpmio_spi_received *r; 154 int err = 0; 155 156 if (slave >= sc->sc_spi.sct_nslaves) 157 return EINVAL; 158 159 /* The speed is in bps and the MCP2210 uses bps, but is not suppose to 160 * be able to go below 1500 bps. There is also an upper bound of 12Mbps, 161 * but the chip will not do anything wrong if you try to go faster as it 162 * will cap the speed. 163 */ 164 165 if (speed < 1500) { 166 aprint_error_dev(sc->sc_dev, 167 "Speed %d is too low and not supported.", speed); 168 return EINVAL; 169 } 170 mutex_enter(&sc->sc_spi_mutex); 171 172 umcpmio_gpio_pin_ctl(sc, slave, GPIO_PIN_ALT0); 173 174 switch (mode) { 175 case SPI_MODE_0: 176 desired_mode = MCP2210_SPI_MODE_0; 177 break; 178 case SPI_MODE_1: 179 desired_mode = MCP2210_SPI_MODE_1; 180 break; 181 case SPI_MODE_2: 182 desired_mode = MCP2210_SPI_MODE_2; 183 break; 184 case SPI_MODE_3: 185 desired_mode = MCP2210_SPI_MODE_3; 186 break; 187 default: 188 err = EINVAL; 189 } 190 191 192 /* Remove any queued up data. This is a choice, but it seems the 193 * right now. If you call configure() you are probably resetting 194 * the SPI port. 195 */ 196 197 if (!err) { 198 sc->sc_slave_configs[slave].bit_rate = (uint32_t) speed; 199 sc->sc_slave_configs[slave].mode = desired_mode; 200 201 if (!SIMPLEQ_EMPTY(&sc->sc_received[slave])) { 202 while ((r = SIMPLEQ_FIRST(&sc->sc_received[slave])) != NULL) { 203 SIMPLEQ_REMOVE_HEAD(&sc->sc_received[slave], umcpmio_spi_received_q); 204 kmem_free(r, sizeof(struct umcpmio_spi_received)); 205 } 206 } 207 } 208 209 mutex_exit(&sc->sc_spi_mutex); 210 211 return err; 212 } 213 214 /* Set all of the stuff about the slave device that is needed 215 * to do a transfer. 216 */ 217 218 static int 219 mcp2210_spi_set_slave_config(struct umcpmio_softc *sc, 220 uint16_t max_transfer_size, int slave) 221 { 222 struct mcp2210_get_spi_sram_res get_res; 223 struct mcp2210_set_spi_sram_req set_req; 224 struct mcp2210_set_spi_sram_res set_res; 225 uint16_t idle; 226 uint16_t active; 227 int err = 0; 228 229 err = mcp2210_get_spi_sram(sc, &get_res); 230 if (err) 231 goto out; 232 233 memset(&set_res, 0, MCP2210_RES_BUFFER_SIZE); 234 memcpy(&set_req, &get_res, MCP2210_REQ_BUFFER_SIZE); 235 236 /* The MCP2210 supports the notion of a high active for 237 * the CS, but spi(4) doesn't so, just use the normal 238 * low active behavior all of the time. 239 * 240 * The chip also appears to support more than one CS 241 * being active at the same time, but that is really 242 * an unusual desire to have. 243 */ 244 245 idle = 0xffff; 246 active = ~(1 << slave); 247 248 set_req.idle_cs_value_lsb = (uint8_t)(idle & 0xff); 249 set_req.idle_cs_value_msb = (uint8_t)(idle >> 8); 250 set_req.active_cs_value_lsb = (uint8_t)(active & 0xff); 251 set_req.active_cs_value_msb = (uint8_t)(active >> 8); 252 253 set_req.spi_mode = sc->sc_slave_configs[slave].mode; 254 255 uint32_t s = sc->sc_slave_configs[slave].bit_rate; 256 set_req.bit_rate_byte_3 = (0x000000ff & s); 257 set_req.bit_rate_byte_2 |= (0x000000ff & (s >> 8)); 258 set_req.bit_rate_byte_1 |= (0x000000ff & (s >> 16)); 259 set_req.bit_rate_byte_0 |= (0x000000ff & (s >> 24)); 260 261 /* The MCP2210 does best when the transfer size is set to the 262 * same max amount that a transfer incoming might have. 263 */ 264 265 set_req.bytes_per_spi_transaction_lsb = (uint8_t)(max_transfer_size & 0xff); 266 set_req.bytes_per_spi_transaction_msb = (uint8_t)(max_transfer_size >> 8); 267 268 err = mcp2210_set_spi_sram(sc, &set_req, &set_res); 269 270 out: 271 272 DPRINTF(("mcp2210_spi_set_slave exit: err=%d\n", err)); 273 274 return err; 275 } 276 277 /* Fill up the outgoing transfer buffers. It is generally assumed that the state 278 * of the req buffer is set coming into this function. It should either be 279 * zero filled or a repeat buffer in a retry situation. 280 */ 281 282 static void 283 mcp2210_spi_tx_fill(struct umcpmio_softc *sc, 284 struct mcp2210_spi_transfer_req *req) 285 { 286 struct spi_chunk *chunk = sc->sc_wchunk; 287 size_t len; 288 289 if (chunk == NULL) 290 return; 291 292 if (sc->sc_dying) 293 return; 294 295 len = MIN(MCP2210_MAX_SPI_BYTES, chunk->chunk_wresid); 296 DPRINTF(("mcp2210_spi_tx_fill: len=%zd; chunk_wresid=%d\n", 297 len, chunk->chunk_wresid)); 298 chunk->chunk_wresid -= len; 299 req->num_send_bytes += len; 300 if (chunk->chunk_wptr) 301 memcpy(&req->send_bytes[0], chunk->chunk_wptr, len); 302 DPRINTF(("mcp2210_spi_tx_fill: checking sending values.. req->num_send_bytes=%d, chunk_wresid=%d\n", 303 req->num_send_bytes, chunk->chunk_wresid)); 304 if (chunk->chunk_wresid == 0) { 305 DPRINTF(("mcp2210_spi_tx_fill: moving onto the next chunk\n")); 306 sc->sc_wchunk = sc->sc_wchunk->chunk_next; 307 if (sc->sc_wchunk) 308 DPRINTF(("mcp2210_spi_tx_fill: new chunk EXISTS\n")); 309 else 310 DPRINTF(("mcp2210_spi_tx_fill: new chunk does not EXIST, NULL\n")); 311 } 312 } 313 314 /* Drain the incoming buffer into the upstream structure. If there is no 315 * upstream to drain into, then queue up the result for later. 316 */ 317 318 static int 319 mcp2210_spi_rx_drain(struct umcpmio_softc *sc, int slave, 320 struct mcp2210_spi_transfer_res *res) 321 { 322 struct spi_chunk *chunk = sc->sc_rchunk; 323 size_t len; 324 struct umcpmio_spi_received *r; 325 int err = 0; 326 327 if (chunk == NULL) 328 return err; 329 330 if (sc->sc_dying) 331 return err; 332 333 len = MIN(res->num_receive_bytes, chunk->chunk_rresid); 334 chunk->chunk_rresid -= len; 335 DPRINTF(("mcp2210_spi_rx_drain: ENTER: len=%zd; res->num_receive_bytes=%d; chunk_rresid=%d\n", 336 len, res->num_receive_bytes, chunk->chunk_rresid)); 337 if (chunk->chunk_rptr) 338 memcpy(chunk->chunk_rptr, &res->receive_bytes[0], len); 339 if (chunk->chunk_rresid == 0) { 340 DPRINTF(("mcp2210_spi_rx_drain: moving onto the next chunk\n")); 341 sc->sc_rchunk = sc->sc_rchunk->chunk_next; 342 if (sc->sc_rchunk) 343 DPRINTF(("mcp2210_spi_rx_drain: new chunk EXISTS\n")); 344 else 345 DPRINTF(("mcp2210_spi_rx_drain: new chunk does not EXIST, NULL\n")); 346 } 347 DPRINTF(("mcp2210_spi_rx_drain: checking received values.. res->num_received_bytes=%d\n", 348 res->num_receive_bytes)); 349 if (len < res->num_receive_bytes) { 350 DPRINTF(("mcp2210_spi_rx_drain: did not consume all that was received, Q it up.... res->num_received_bytes=%d\n", 351 res->num_receive_bytes)); 352 r = kmem_alloc(sizeof(struct umcpmio_spi_received), KM_NOSLEEP); 353 if (r != NULL) { 354 memcpy(&r->receive_bytes[0], &res->receive_bytes[len], res->num_receive_bytes - len); 355 r->num_receive_bytes = res->num_receive_bytes - len; 356 SIMPLEQ_INSERT_HEAD(&sc->sc_received[slave], r, umcpmio_spi_received_q); 357 } else { 358 err = ENOMEM; 359 } 360 } 361 return err; 362 } 363 364 /* Very similar to receiving from the chip buffer, except from this 365 * is from the local queue. Requeue if needed. 366 */ 367 368 static int 369 mcp2210_spi_rx_q(struct umcpmio_softc *sc, int slave, 370 struct umcpmio_spi_received *r) 371 { 372 struct spi_chunk *chunk = sc->sc_rchunk; 373 size_t len; 374 struct umcpmio_spi_received *mr; 375 int err = 0; 376 377 if (chunk == NULL) 378 return err; 379 380 if (sc->sc_dying) 381 return err; 382 383 len = MIN(r->num_receive_bytes, chunk->chunk_rresid); 384 chunk->chunk_rresid -= len; 385 DPRINTF(("mcp2210_spi_rx_q: ENTER: len=%zd; r->num_receive_bytes=%d; chunk_rresid=%d\n", 386 len, r->num_receive_bytes, chunk->chunk_rresid)); 387 if (chunk->chunk_rptr) 388 memcpy(chunk->chunk_rptr, &r->receive_bytes[0], len); 389 if (chunk->chunk_rresid == 0) { 390 DPRINTF(("mcp2210_spi_rx_q: moving onto the next chunk\n")); 391 sc->sc_rchunk = sc->sc_rchunk->chunk_next; 392 if (sc->sc_rchunk) 393 DPRINTF(("mcp2210_spi_rx_q: new chunk EXISTS\n")); 394 else 395 DPRINTF(("mcp2210_spi_rx_q: new chunk does not EXIST, NULL\n")); 396 } 397 DPRINTF(("mcp2210_spi_rx_q: checking received values.. r->num_received_bytes=%d\n", 398 r->num_receive_bytes)); 399 if (len < r->num_receive_bytes) { 400 DPRINTF(("mcp2210_spi_rx_q: did not consume all that was received, Q it up... r->num_received_bytes=%d\n", 401 r->num_receive_bytes)); 402 mr = kmem_alloc(sizeof(struct umcpmio_spi_received), KM_NOSLEEP); 403 if (mr != NULL) { 404 memcpy(&mr->receive_bytes[0], &r->receive_bytes[len], r->num_receive_bytes - len); 405 mr->num_receive_bytes = r->num_receive_bytes - len; 406 SIMPLEQ_INSERT_HEAD(&sc->sc_received[slave], mr, umcpmio_spi_received_q); 407 } else { 408 err = ENOMEM; 409 } 410 } 411 return err; 412 } 413 414 /* Drain the chip buffers into the local queue. No upstream involved. */ 415 416 static int 417 mcp2210_spi_rx_drainchip(struct umcpmio_softc *sc, int slave, 418 struct mcp2210_spi_transfer_res *res) 419 { 420 int err = 0; 421 struct umcpmio_spi_received *r; 422 423 r = kmem_alloc(sizeof(struct umcpmio_spi_received), KM_NOSLEEP); 424 if (r == NULL) 425 return ENOMEM; 426 memcpy(&r->receive_bytes[0], &res->receive_bytes[0], res->num_receive_bytes); 427 r->num_receive_bytes = res->num_receive_bytes; 428 SIMPLEQ_INSERT_TAIL(&sc->sc_received[slave], r, umcpmio_spi_received_q); 429 430 return err; 431 } 432 433 /* Service a transfer. We do the local queue first if there is something, then 434 * send a transfer, with an optional amount of data, and then process any 435 * incoming chip data. 436 */ 437 438 static int 439 mcp2210_spi_txrx(struct umcpmio_softc *sc, int slave) 440 { 441 struct mcp2210_spi_transfer_req req; 442 struct mcp2210_spi_transfer_res res; 443 struct umcpmio_spi_received *r; 444 int err = 0; 445 int wretry = sc->sc_retry_busy_write; 446 447 DPRINTF(("mcp2210_spi_txrx: ENTER\n")); 448 449 if (sc->sc_dying) 450 return err; 451 452 /* There was local queue data and an upstream to receive it */ 453 454 if (!SIMPLEQ_EMPTY(&sc->sc_received[slave]) && 455 sc->sc_rchunk != NULL) { 456 DPRINTF(("mcp2210_spi_txrx: previous received bytes to send to upstream\n")); 457 while ((r = SIMPLEQ_FIRST(&sc->sc_received[slave])) != NULL) { 458 SIMPLEQ_REMOVE_HEAD(&sc->sc_received[slave], umcpmio_spi_received_q); 459 err = mcp2210_spi_rx_q(sc, slave, r); 460 kmem_free(r, sizeof(struct umcpmio_spi_received)); 461 if (err) 462 break; 463 } 464 465 goto out; 466 } 467 if (sc->sc_dying) 468 return err; 469 470 /* Set up a transfer and fill it once */ 471 472 memset(&req, 0, UMCPMIO_REQ_BUFFER_SIZE); 473 474 if (sc->sc_wchunk != NULL) 475 DPRINTF(("mcp2210_spi_txrx: filling up req for write transfer; chunk_wresid=%d\n", sc->sc_wchunk->chunk_wresid)); 476 else 477 DPRINTF(("mcp2210_spi_txrx: filling up req for write transfer; wchunk is NULL\n")); 478 mcp2210_spi_tx_fill(sc, &req); 479 480 retry: 481 482 memset(&res, 0, UMCPMIO_RES_BUFFER_SIZE); 483 484 if (sc->sc_dying) 485 return err; 486 487 err = mcp2210_do_spi_transfer(sc, &req, &res); 488 if (err) 489 if (err != EBUSY) 490 goto out; 491 492 DPRINTF(("mcp2210_spi_txrx: did transfer res.completion=%02x ;" 493 "res.spi_engine_status=%02x, res.num_receive_bytes=%d\n", 494 res.completion, res.spi_engine_status, res.num_receive_bytes)); 495 496 /* This error situation of MCP2210_SPI_STATUS_DATA (0x30) and 497 * zero received data means either the chip is stuck because 498 * upstream didn't send enough data, or the chip is working 499 * on receiving some data. We only let this condition go on 500 * a certain number of times before passing the error up. 501 */ 502 503 if (!err) { 504 if (res.spi_engine_status == MCP2210_SPI_STATUS_DATA && 505 res.num_receive_bytes == 0) { 506 err = ECANCELED; 507 } 508 } 509 510 /* A normal busy caused by the SPI bus being busy or the USB 511 * bus being busy. Try the whole transfer again. 512 */ 513 514 if (err == EBUSY) { 515 DPRINTF(("mcp2210_spi_txrx: transfer is busy\n")); 516 wretry--; 517 if (wretry > 0) { 518 WAITMS(sc->sc_busy_delay); 519 goto retry; 520 } else { 521 err = EIO; 522 goto out; 523 } 524 } 525 526 /* If the chip knows that there is data coming, but has not seen 527 * any yet you get this error. Retry the transfer with a zero 528 * length outgoing buffer. 529 */ 530 531 if (res.spi_engine_status == MCP2210_SPI_STATUS_NO_DATA_YET) { 532 DPRINTF(("mcp2210_spi_txrx: transfer is NO DATA YET\n")); 533 wretry--; 534 if (wretry > 0) { 535 WAITMS(sc->sc_busy_delay); 536 memset(&req, 0, UMCPMIO_REQ_BUFFER_SIZE); 537 goto retry; 538 } else { 539 err = EIO; 540 goto out; 541 } 542 } 543 DPRINTF(("mcp2210_spi_txrx: DOING RECEIVE: res.num_receive_bytes=%d\n", 544 res.num_receive_bytes)); 545 546 /* If we actually received some data, drain it somewhere */ 547 548 if (res.num_receive_bytes > 0) { 549 if (sc->sc_rchunk != NULL && 550 sc->sc_rchunk->chunk_rptr) { 551 DPRINTF(("mcp2210_spi_txrx: send data to upstream\n")); 552 err = mcp2210_spi_rx_drain(sc, slave, &res); 553 } else { 554 DPRINTF(("mcp2210_spi_txrx: drain chip, send data to Q\n")); 555 err = mcp2210_spi_rx_drainchip(sc, slave, &res); 556 } 557 } 558 out: 559 560 DPRINTF(("mcp2210_spi_txrx exit. err=%d\n", err)); 561 562 return err; 563 } 564 565 /* Cancel a SPI transfer that might be in progress, or at 566 * least the chip thinks is in progress. 567 */ 568 569 int 570 mcp2210_cancel_spi_transfer(struct umcpmio_softc *sc, 571 struct mcp2210_cancel_spi_res *res) 572 { 573 struct mcp2210_cancel_spi_req req; 574 int err = 0; 575 576 KASSERT(mutex_owned(&sc->sc_action_mutex)); 577 578 memset(&req, 0, MCP2210_REQ_BUFFER_SIZE); 579 req.cmd = MCP2210_CMD_SPI_CANCEL; 580 581 umcpmio_dump_buffer(sc->sc_dumpbuffer, 582 (uint8_t *) & req, MCP2210_REQ_BUFFER_SIZE, 583 "mcp2210_cancel_spi_transfer req"); 584 585 err = umcpmio_send_report(sc, 586 (uint8_t *) & req, MCP2210_REQ_BUFFER_SIZE, 587 (uint8_t *) res, sc->sc_cv_wait); 588 589 umcpmio_dump_buffer(sc->sc_dumpbuffer, 590 (uint8_t *) res, MCP2210_RES_BUFFER_SIZE, 591 "mcp2210_get_spi_sram res"); 592 593 err = mcp2210_decode_errors(req.cmd, err, res->completion); 594 595 return err; 596 } 597 598 /* As long as there are outgoing chunks to send, 599 * or incoming chunks to receive, poll the SPI port. 600 */ 601 602 static void 603 mcp2210_spi_poll(struct umcpmio_softc *sc, 604 int slave, int *stuckcount) 605 { 606 struct spi_transfer *st; 607 struct mcp2210_cancel_spi_res cancel_res; 608 int err = 0; 609 610 err = mcp2210_spi_txrx(sc, slave); 611 612 DPRINTF(("mcp2210_spi_poll: err from transfer: err=%d\n", err)); 613 614 /* Give up if we exceed the stuck count. It is ok for this to happen 615 * a couple of times during a transfer, but if it persists, something is 616 * going wrong. 617 */ 618 if (err == ECANCELED) { 619 int s; 620 621 s = *stuckcount; 622 s--; 623 DPRINTF(("mcp2210_spi_poll: STUCK s=%d\n", s)); 624 if (s > 0) 625 err = 0; 626 *stuckcount = s; 627 } 628 629 if (err) { 630 if (err == ECANCELED) { 631 if (sc->sc_spi_verbose) 632 device_printf(sc->sc_dev, "The SPI transfer may be stuck. Canceling.\n"); 633 mutex_enter(&sc->sc_action_mutex); 634 mcp2210_cancel_spi_transfer(sc, &cancel_res); 635 mutex_exit(&sc->sc_action_mutex); 636 } 637 sc->sc_rchunk = sc->sc_wchunk = NULL; 638 } 639 640 /* Finialize the transfer */ 641 642 if (sc->sc_rchunk == NULL && 643 sc->sc_wchunk == NULL) { 644 st = sc->sc_transfer; 645 sc->sc_transfer = NULL; 646 KASSERT(st != NULL); 647 spi_done(st, 0); 648 sc->sc_running = false; 649 } 650 return; 651 } 652 653 /* Start a SPI transfer up and running */ 654 655 static void 656 mcp2210_spi_start(struct umcpmio_softc *sc) 657 { 658 struct spi_transfer *st; 659 struct spi_chunk *chunk; 660 uint16_t max_transfer_size = 0; 661 int transfer_size = 0; 662 int err = 0; 663 int stuckcount = 4; /* XXX - maybe this should be a sysctl */ 664 struct mcp2210_cancel_spi_res cancel_res; 665 666 while ((st = spi_transq_first(&sc->sc_q)) != NULL) { 667 spi_transq_dequeue(&sc->sc_q); 668 KASSERT(sc->sc_transfer == NULL); 669 sc->sc_transfer = st; 670 sc->sc_rchunk = sc->sc_wchunk = st->st_chunks; 671 sc->sc_running = true; 672 673 KASSERT(st->st_slave < sc->sc_spi.sct_nslaves); 674 675 /* Figure out the maximum size for this transfer. 676 * It doesn't matter if it is an incoming or outgoing 677 * chunk. 678 */ 679 chunk = st->st_chunks; 680 while (chunk != NULL) { 681 if (chunk->chunk_wresid > transfer_size) 682 transfer_size = chunk->chunk_wresid; 683 if (chunk->chunk_rresid > transfer_size) 684 transfer_size = chunk->chunk_rresid; 685 chunk = chunk->chunk_next; 686 } 687 688 KASSERT(transfer_size > 0); 689 690 /* The chip can do up to 65535 bytes in a transfer. We subtract 691 * 1 so the slave device can send back an end byte. There is, 692 * apparently some way to do larger transfers, but I could 693 * not find documentation on how to do that. 694 */ 695 if (transfer_size > 65534) { 696 if (sc->sc_spi_verbose) 697 device_printf(sc->sc_dev, "Canceling transfer. " 698 "The size of the requested transfer is too big. " 699 "transfer_size=%d\n", 700 transfer_size); 701 702 st = sc->sc_transfer; 703 sc->sc_transfer = NULL; 704 spi_done(st, 0); 705 sc->sc_running = false; 706 707 return; 708 } 709 max_transfer_size = (uint16_t) transfer_size + 1; 710 711 DPRINTF(("mcp2210_spi_start: transfer_size=%d; max_transfer_size=%d\n", transfer_size, max_transfer_size)); 712 713 /* Set all of the deferred setting now that we are committed to trying 714 * to do the transfer. 715 */ 716 err = mcp2210_spi_set_slave_config(sc, max_transfer_size, st->st_slave); 717 /* If we get EBUSY here, then it probably means that there was a incomplete 718 * transfer. Cancel it, and try one more time. 719 */ 720 if (err == EBUSY) { 721 mutex_enter(&sc->sc_action_mutex); 722 mcp2210_cancel_spi_transfer(sc, &cancel_res); 723 mutex_exit(&sc->sc_action_mutex); 724 err = mcp2210_spi_set_slave_config(sc, max_transfer_size, st->st_slave); 725 } 726 if (err) { 727 if (sc->sc_spi_verbose) 728 device_printf(sc->sc_dev, "Canceling transfer. Error setting up slave config. error=%d\n", err); 729 730 st = sc->sc_transfer; 731 sc->sc_transfer = NULL; 732 spi_done(st, 0); 733 sc->sc_running = false; 734 735 return; 736 } 737 738 for (;;) { 739 mcp2210_spi_poll(sc, st->st_slave, &stuckcount); 740 if (ISSET(st->st_flags, SPI_F_DONE)) 741 break; 742 if (sc->sc_dying) 743 break; 744 } 745 } 746 sc->sc_running = false; 747 748 return; 749 } 750 751 static int 752 mcp2210_spi_transfer(void *cookie, struct spi_transfer *st) 753 { 754 struct umcpmio_softc *sc = cookie; 755 756 mutex_enter(&sc->sc_spi_mutex); 757 spi_transq_enqueue(&sc->sc_q, st); 758 if (sc->sc_running == false) { 759 mcp2210_spi_start(sc); 760 } 761 mutex_exit(&sc->sc_spi_mutex); 762 763 return 0; 764 } 765 766 int 767 umcpmio_spi_attach(struct umcpmio_softc *sc) 768 { 769 struct mcp2210_get_spi_sram_res get_res; 770 struct mcp2210_set_spi_sram_req set_req; 771 struct mcp2210_set_spi_sram_res set_res; 772 struct mcp2210_cancel_spi_res cancel_res; 773 int err = 0; 774 775 sc->sc_spi_verbose = true; 776 sc->sc_busy_delay = 0; 777 sc->sc_retry_busy_read = 50; 778 sc->sc_retry_busy_write = 50; 779 sc->sc_running = false; 780 781 DPRINTF(("umcpmio_spi_attach: sc->sc_chipinfo->num_spi_slaves=%d\n", sc->sc_chipinfo->num_spi_slaves)); 782 783 SIMPLEQ_INIT(&sc->sc_q); 784 785 for (int i = 0; i < sc->sc_chipinfo->num_spi_slaves; i++){ 786 SIMPLEQ_INIT(&sc->sc_received[i]); 787 sc->sc_slave_configs[i].bit_rate = (uint32_t) SPI_FREQ_MHz(1); 788 sc->sc_slave_configs[i].mode = MCP2210_SPI_MODE_0; 789 } 790 791 /* Set all of the active and idle CS directions here. */ 792 err = mcp2210_get_spi_sram(sc, &get_res); 793 if (err) { 794 aprint_error_dev(sc->sc_dev, 795 "%s: unable to read SPI sram: %d\n", 796 __func__, err); 797 goto out; 798 } 799 memset(&set_res, 0, MCP2210_RES_BUFFER_SIZE); 800 memcpy(&set_req, &get_res, MCP2210_REQ_BUFFER_SIZE); 801 802 set_req.idle_cs_value_lsb = set_req.idle_cs_value_msb = 0xff; 803 set_req.active_cs_value_lsb = set_req.active_cs_value_msb = 0x00; 804 805 err = mcp2210_set_spi_sram(sc, &set_req, &set_res); 806 /* If there is a EBUSY here, then a transfer was incomplete 807 * in the past. That can happen on attach if the chip stays 808 * powered up, but is removed from the USB port and 809 * reinserted. Cancel the transfer and try one more time. 810 */ 811 if (err == EBUSY) { 812 mutex_enter(&sc->sc_action_mutex); 813 mcp2210_cancel_spi_transfer(sc, &cancel_res); 814 mutex_exit(&sc->sc_action_mutex); 815 err = mcp2210_set_spi_sram(sc, &set_req, &set_res); 816 } 817 if (err) { 818 aprint_error_dev(sc->sc_dev, 819 "%s: unable to set SPI sram: %d\n", 820 __func__, err); 821 goto out; 822 } 823 sc->sc_spi.sct_cookie = sc; 824 sc->sc_spi.sct_configure = mcp2210_spi_configure; 825 sc->sc_spi.sct_transfer = mcp2210_spi_transfer; 826 sc->sc_spi.sct_nslaves = sc->sc_chipinfo->num_spi_slaves; 827 828 spibus_attach(sc->sc_dev, &sc->sc_spi); 829 830 out: 831 832 return err; 833 } 834