Home | History | Annotate | Line # | Download | only in usb
      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