1207753Smm/* $NetBSD: arspi.c,v 1.15 2021/08/07 16:18:58 thorpej Exp $ */ 2207753Smm 3207753Smm/*- 4207753Smm * Copyright (c) 2006 Urbana-Champaign Independent Media Center. 5207753Smm * Copyright (c) 2006 Garrett D'Amore. 6207753Smm * All rights reserved. 7207753Smm * 8207753Smm * Portions of this code were written by Garrett D'Amore for the 9207753Smm * Champaign-Urbana Community Wireless Network Project. 10207753Smm * 11207753Smm * Redistribution and use in source and binary forms, with or 12207753Smm * without modification, are permitted provided that the following 13207753Smm * conditions are met: 14207753Smm * 1. Redistributions of source code must retain the above copyright 15207753Smm * notice, this list of conditions and the following disclaimer. 16207753Smm * 2. Redistributions in binary form must reproduce the above 17207753Smm * copyright notice, this list of conditions and the following 18207753Smm * disclaimer in the documentation and/or other materials provided 19207753Smm * with the distribution. 20207753Smm * 3. All advertising materials mentioning features or use of this 21207753Smm * software must display the following acknowledgements: 22207753Smm * This product includes software developed by the Urbana-Champaign 23207753Smm * Independent Media Center. 24207753Smm * This product includes software developed by Garrett D'Amore. 25207753Smm * 4. Urbana-Champaign Independent Media Center's name and Garrett 26207753Smm * D'Amore's name may not be used to endorse or promote products 27207753Smm * derived from this software without specific prior written permission. 28207753Smm * 29207753Smm * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT 30207753Smm * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR 31207753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32207753Smm * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33207753Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT 34207753Smm * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT, 35207753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36207753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37207753Smm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38223935Smm * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39207753Smm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40207753Smm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41207753Smm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42207753Smm */ 43207753Smm 44207753Smm#include <sys/cdefs.h> 45207753Smm__KERNEL_RCSID(0, "$NetBSD: arspi.c,v 1.15 2021/08/07 16:18:58 thorpej Exp $"); 46207753Smm 47207753Smm#include "locators.h" 48207753Smm 49207753Smm#include <sys/param.h> 50207753Smm#include <sys/bus.h> 51207753Smm#include <sys/cpu.h> 52207753Smm#include <sys/device.h> 53207753Smm#include <sys/errno.h> 54207753Smm#include <sys/kernel.h> 55207753Smm#include <sys/kmem.h> 56207753Smm#include <sys/proc.h> 57207753Smm#include <sys/systm.h> 58207753Smm 59207753Smm#include <mips/atheros/include/ar5315reg.h> 60207753Smm#include <mips/atheros/include/arbusvar.h> 61207753Smm 62207753Smm#include <mips/atheros/dev/arspireg.h> 63207753Smm 64207753Smm#include <dev/spi/spiflash.h> 65207753Smm#include <dev/spi/spivar.h> 66207753Smm 67207753Smm/* 68207753Smm * This device is intended only to operate with specific SPI flash 69207753Smm * parts, and is not a general purpose SPI host. (Or at least if it 70207753Smm * is, the Linux and eCos sources do not show how to use it as such.) 71207753Smm * And lack of documentation on the Atheros SoCs is less than helpful. 72207753Smm * 73207753Smm * So for now we just "emulate" enough of the host bus framework to 74207753Smm * make the SPI flash drivers happy. 75207753Smm */ 76207753Smm 77207753Smmstruct arspi_job { 78207753Smm uint8_t job_opcode; 79213700Smm struct spi_chunk *job_chunk; 80207753Smm uint32_t job_flags; 81207753Smm uint32_t job_addr; 82207753Smm uint32_t job_data; 83207753Smm int job_rxcnt; 84207753Smm int job_txcnt; 85207753Smm int job_addrcnt; 86207753Smm int job_rresid; 87207753Smm int job_wresid; 88207753Smm}; 89207753Smm 90207753Smm#define JOB_READ 0x1 91207753Smm#define JOB_WRITE 0x2 92207753Smm#define JOB_LAST 0x4 93207753Smm#define JOB_WAIT 0x8 /* job must wait for WIP bits */ 94207753Smm#define JOB_WREN 0x10 /* WREN needed */ 95207753Smm 96207753Smmstruct arspi_softc { 97207753Smm struct spi_controller sc_spi; 98207753Smm void *sc_ih; 99207753Smm bool sc_interrupts; 100207753Smm 101207753Smm struct spi_transfer *sc_transfer; 102207753Smm struct spi_chunk *sc_wchunk; /* for partial writes */ 103207753Smm struct spi_transq sc_transq; 104207753Smm bus_space_tag_t sc_st; 105207753Smm bus_space_handle_t sc_sh; 106207753Smm bus_size_t sc_size; 107207753Smm}; 108207753Smm 109207753Smm#define STATIC 110207753Smm 111207753SmmSTATIC int arspi_match(device_t, cfdata_t, void *); 112207753SmmSTATIC void arspi_attach(device_t, device_t, void *); 113207753SmmSTATIC void arspi_interrupts(device_t); 114207753SmmSTATIC int arspi_intr(void *); 115207753Smm/* SPI service routines */ 116207753SmmSTATIC int arspi_configure(void *, int, int, int); 117207753SmmSTATIC int arspi_transfer(void *, struct spi_transfer *); 118207753Smm/* internal support */ 119207753SmmSTATIC void arspi_poll(struct arspi_softc *); 120207753SmmSTATIC void arspi_done(struct arspi_softc *, int); 121207753SmmSTATIC void arspi_sched(struct arspi_softc *); 122207753SmmSTATIC int arspi_get_byte(struct spi_chunk **, uint8_t *); 123207753SmmSTATIC int arspi_put_byte(struct spi_chunk **, uint8_t); 124207753SmmSTATIC int arspi_make_job(struct spi_transfer *); 125207753SmmSTATIC void arspi_update_job(struct spi_transfer *); 126207753SmmSTATIC void arspi_finish_job(struct spi_transfer *); 127207753Smm 128207753Smm 129207753SmmCFATTACH_DECL_NEW(arspi, sizeof(struct arspi_softc), 130207753Smm arspi_match, arspi_attach, NULL, NULL); 131207753Smm 132207753Smm#define GETREG(sc, o) bus_space_read_4(sc->sc_st, sc->sc_sh, o) 133207753Smm#define PUTREG(sc, o, v) bus_space_write_4(sc->sc_st, sc->sc_sh, o, v) 134207753Smm 135207753Smmint 136207753Smmarspi_match(device_t parent, cfdata_t cf, void *aux) 137207753Smm{ 138207753Smm struct arbus_attach_args *aa = aux; 139207753Smm 140207753Smm if (strcmp(aa->aa_name, cf->cf_name) != 0) 141207753Smm return 0; 142207753Smm return 1; 143207753Smm} 144207753Smm 145207753Smmvoid 146207753Smmarspi_attach(device_t parent, device_t self, void *aux) 147207753Smm{ 148207753Smm struct arspi_softc *sc = device_private(self); 149207753Smm struct spibus_attach_args sba; 150207753Smm struct arbus_attach_args *aa = aux; 151207753Smm 152207753Smm /* 153207753Smm * Map registers. 154207753Smm */ 155207753Smm sc->sc_st = aa->aa_bst; 156207753Smm sc->sc_size = aa->aa_size; 157207753Smm if (bus_space_map(sc->sc_st, aa->aa_addr, sc->sc_size, 0, 158207753Smm &sc->sc_sh) != 0) { 159207753Smm printf(": unable to map registers!\n"); 160207753Smm return; 161207753Smm } 162207753Smm 163207753Smm aprint_normal(": Atheros SPI controller\n"); 164207753Smm 165207753Smm /* 166207753Smm * Initialize SPI controller. 167207753Smm */ 168207753Smm sc->sc_spi.sct_cookie = sc; 169207753Smm sc->sc_spi.sct_configure = arspi_configure; 170207753Smm sc->sc_spi.sct_transfer = arspi_transfer; 171207753Smm sc->sc_spi.sct_nslaves = 1; 172207753Smm 173207753Smm 174207753Smm /* 175207753Smm * Initialize the queue. 176207753Smm */ 177207753Smm spi_transq_init(&sc->sc_transq); 178207753Smm 179207753Smm /* 180207753Smm * Enable device interrupts. 181207753Smm */ 182207753Smm sc->sc_ih = arbus_intr_establish(aa->aa_cirq, aa->aa_mirq, 183207753Smm arspi_intr, sc); 184207753Smm if (sc->sc_ih == NULL) { 185215187Smm aprint_error("%s: couldn't establish interrupt\n", 186215187Smm device_xname(self)); 187215187Smm /* just leave it in polled mode */ 188215187Smm } else 189215187Smm config_interrupts(self, arspi_interrupts); 190215187Smm 191215187Smm /* 192215187Smm * Initialize and attach bus attach. 193215187Smm */ 194215187Smm memset(&sba, 0, sizeof(sba)); 195215187Smm sba.sba_controller = &sc->sc_spi; 196215187Smm config_found(self, &sba, spibus_print, CFARGS_NONE); 197215187Smm} 198215187Smm 199207753Smmvoid 200207753Smmarspi_interrupts(device_t self) 201207753Smm{ 202207753Smm /* 203207753Smm * we never leave polling mode, because, apparently, we 204207753Smm * are missing some data about how to drive the SPI in interrupt 205207753Smm * mode. 206207753Smm */ 207207753Smm#if 0 208207753Smm struct arspi_softc *sc = device_private(self); 209207753Smm int s; 210207753Smm 211207753Smm s = splbio(); 212207753Smm sc->sc_interrupts = true; 213207753Smm splx(s); 214207753Smm#endif 215207753Smm} 216207753Smm 217207753Smmint 218207753Smmarspi_intr(void *arg) 219207753Smm{ 220207753Smm struct arspi_softc *sc = arg; 221207753Smm 222207753Smm while (GETREG(sc, ARSPI_REG_CTL) & ARSPI_CTL_BUSY); 223207753Smm 224207753Smm arspi_done(sc, 0); 225207753Smm 226207753Smm return 1; 227207753Smm} 228207753Smm 229207753Smmvoid 230207753Smmarspi_poll(struct arspi_softc *sc) 231207753Smm{ 232207753Smm 233207753Smm while (sc->sc_transfer) { 234207753Smm arspi_intr(sc); 235207753Smm } 236207753Smm} 237207753Smm 238207753Smmint 239207753Smmarspi_configure(void *cookie, int slave, int mode, int speed) 240207753Smm{ 241207753Smm 242207753Smm /* 243207753Smm * We don't support the full SPI protocol, and hopefully the 244207753Smm * firmware has programmed a reasonable mode already. So 245207753Smm * just a couple of quick sanity checks, then bail. 246207753Smm */ 247207753Smm if ((mode != 0) || (slave != 0)) 248207753Smm return EINVAL; 249207753Smm 250207753Smm return 0; 251207753Smm} 252207753Smm 253207753Smmint 254207753Smmarspi_transfer(void *cookie, struct spi_transfer *st) 255207753Smm{ 256207753Smm struct arspi_softc *sc = cookie; 257207753Smm int rv; 258207753Smm int s; 259207753Smm 260207753Smm st->st_busprivate = NULL; 261207753Smm if ((rv = arspi_make_job(st)) != 0) { 262207753Smm if (st->st_busprivate) { 263207753Smm struct arspi_job *job = st->st_busprivate; 264207753Smm st->st_busprivate = NULL; 265207753Smm kmem_free(job, sizeof(*job)); 266207753Smm } 267207753Smm spi_done(st, rv); 268207753Smm return rv; 269207753Smm } 270207753Smm 271207753Smm s = splbio(); 272207753Smm spi_transq_enqueue(&sc->sc_transq, st); 273207753Smm if (sc->sc_transfer == NULL) { 274207753Smm arspi_sched(sc); 275207753Smm if (!sc->sc_interrupts) 276207753Smm arspi_poll(sc); 277207753Smm } 278207753Smm splx(s); 279207753Smm return 0; 280207753Smm} 281207753Smm 282207753Smmvoid 283207753Smmarspi_sched(struct arspi_softc *sc) 284207753Smm{ 285207753Smm struct spi_transfer *st; 286207753Smm struct arspi_job *job; 287207753Smm uint32_t ctl, cnt; 288207753Smm 289207753Smm for (;;) { 290207753Smm if ((st = sc->sc_transfer) == NULL) { 291207753Smm if ((st = spi_transq_first(&sc->sc_transq)) == NULL) { 292207753Smm /* no work left to do */ 293207753Smm break; 294207753Smm } 295207753Smm spi_transq_dequeue(&sc->sc_transq); 296207753Smm sc->sc_transfer = st; 297207753Smm } 298207753Smm 299207753Smm arspi_update_job(st); 300207753Smm job = st->st_busprivate; 301207753Smm 302207753Smm /* there shouldn't be anything running, but ensure it */ 303207753Smm do { 304207753Smm ctl = GETREG(sc, ARSPI_REG_CTL); 305207753Smm } while (ctl & ARSPI_CTL_BUSY); 306207753Smm /* clear all of the tx and rx bits */ 307207753Smm ctl &= ~(ARSPI_CTL_TXCNT_MASK | ARSPI_CTL_RXCNT_MASK); 308207753Smm 309207753Smm if (job->job_flags & JOB_WAIT) { 310207753Smm PUTREG(sc, ARSPI_REG_OPCODE, SPIFLASH_CMD_RDSR); 311207753Smm /* only the opcode for tx */ 312207753Smm ctl |= (1 << ARSPI_CTL_TXCNT_SHIFT); 313207753Smm /* and one rx byte */ 314207753Smm ctl |= (1 << ARSPI_CTL_RXCNT_SHIFT); 315207753Smm } else if (job->job_flags & JOB_WREN) { 316207753Smm PUTREG(sc, ARSPI_REG_OPCODE, SPIFLASH_CMD_WREN); 317207753Smm /* just the opcode */ 318207753Smm ctl |= (1 << ARSPI_CTL_TXCNT_SHIFT); 319207753Smm /* no rx bytes */ 320207753Smm } else { 321207753Smm /* set the data */ 322207753Smm PUTREG(sc, ARSPI_REG_DATA, job->job_data); 323207753Smm 324207753Smm /* set the opcode and the address */ 325207753Smm PUTREG(sc, ARSPI_REG_OPCODE, job->job_opcode | 326207753Smm (job->job_addr << 8)); 327207753Smm 328207753Smm /* now set txcnt */ 329207753Smm cnt = 1; /* opcode */ 330207753Smm cnt += job->job_addrcnt + job->job_txcnt; 331207753Smm ctl |= (cnt << ARSPI_CTL_TXCNT_SHIFT); 332207753Smm 333207753Smm /* now set rxcnt */ 334207753Smm cnt = job->job_rxcnt; 335207753Smm ctl |= (cnt << ARSPI_CTL_RXCNT_SHIFT); 336207753Smm } 337207753Smm 338207753Smm /* set the start bit */ 339207753Smm ctl |= ARSPI_CTL_START; 340207753Smm 341207753Smm PUTREG(sc, ARSPI_REG_CTL, ctl); 342207753Smm break; 343207753Smm } 344207753Smm} 345207753Smm 346207753Smmvoid 347207753Smmarspi_done(struct arspi_softc *sc, int err) 348207753Smm{ 349207753Smm struct spi_transfer *st; 350207753Smm struct arspi_job *job; 351207753Smm 352207753Smm if ((st = sc->sc_transfer) != NULL) { 353207753Smm job = st->st_busprivate; 354207753Smm 355207753Smm if (job->job_flags & JOB_WAIT) { 356207753Smm if (err == 0) { 357207753Smm if ((GETREG(sc, ARSPI_REG_DATA) & 358207753Smm SPIFLASH_SR_BUSY) == 0) { 359207753Smm /* intermediate wait done */ 360207753Smm job->job_flags &= ~JOB_WAIT; 361207753Smm goto done; 362207753Smm } 363207753Smm } 364207753Smm } else if (job->job_flags & JOB_WREN) { 365207753Smm if (err == 0) { 366207753Smm job->job_flags &= ~JOB_WREN; 367207753Smm goto done; 368207753Smm } 369207753Smm } else if (err == 0) { 370207753Smm /* 371207753Smm * When breaking up write jobs, we have to wait until 372207753Smm * the WIP bit is clear, and we have to separately 373207753Smm * send WREN for each chunk. These flags facilitate 374207753Smm * that. 375207753Smm */ 376207753Smm if (job->job_flags & JOB_WRITE) 377207753Smm job->job_flags |= (JOB_WAIT | JOB_WREN); 378207753Smm job->job_data = GETREG(sc, ARSPI_REG_DATA); 379207753Smm arspi_finish_job(st); 380207753Smm } 381207753Smm 382207753Smm if (err || (job->job_flags & JOB_LAST)) { 383207753Smm sc->sc_transfer = NULL; 384207753Smm st->st_busprivate = NULL; 385207753Smm spi_done(st, err); 386207753Smm kmem_free(job, sizeof(*job)); 387207753Smm } 388207753Smm } 389done: 390 arspi_sched(sc); 391} 392 393int 394arspi_get_byte(struct spi_chunk **chunkp, uint8_t *bytep) 395{ 396 struct spi_chunk *chunk; 397 398 chunk = *chunkp; 399 400 /* skip leading empty (or already consumed) chunks */ 401 while (chunk && chunk->chunk_wresid == 0) 402 chunk = chunk->chunk_next; 403 404 if (chunk == NULL) { 405 return ENODATA; 406 } 407 408 /* 409 * chunk must be write only. SPI flash doesn't support 410 * any full duplex operations. 411 */ 412 if ((chunk->chunk_rptr) || !(chunk->chunk_wptr)) { 413 return EINVAL; 414 } 415 416 *bytep = *chunk->chunk_wptr; 417 chunk->chunk_wptr++; 418 chunk->chunk_wresid--; 419 chunk->chunk_rresid--; 420 /* clearing wptr and rptr makes sanity checks later easier */ 421 if (chunk->chunk_wresid == 0) 422 chunk->chunk_wptr = NULL; 423 if (chunk->chunk_rresid == 0) 424 chunk->chunk_rptr = NULL; 425 while (chunk && chunk->chunk_wresid == 0) 426 chunk = chunk->chunk_next; 427 428 *chunkp = chunk; 429 return 0; 430} 431 432int 433arspi_put_byte(struct spi_chunk **chunkp, uint8_t byte) 434{ 435 struct spi_chunk *chunk; 436 437 chunk = *chunkp; 438 439 /* skip leading empty (or already consumed) chunks */ 440 while (chunk && chunk->chunk_rresid == 0) 441 chunk = chunk->chunk_next; 442 443 if (chunk == NULL) { 444 return EOVERFLOW; 445 } 446 447 /* 448 * chunk must be read only. SPI flash doesn't support 449 * any full duplex operations. 450 */ 451 if ((chunk->chunk_wptr) || !(chunk->chunk_rptr)) { 452 return EINVAL; 453 } 454 455 *chunk->chunk_rptr = byte; 456 chunk->chunk_rptr++; 457 chunk->chunk_wresid--; /* technically this was done at send time */ 458 chunk->chunk_rresid--; 459 while (chunk && chunk->chunk_rresid == 0) 460 chunk = chunk->chunk_next; 461 462 *chunkp = chunk; 463 return 0; 464} 465 466int 467arspi_make_job(struct spi_transfer *st) 468{ 469 struct arspi_job *job; 470 struct spi_chunk *chunk; 471 uint8_t byte; 472 int i, rv; 473 474 job = kmem_zalloc(sizeof (struct arspi_job), KM_SLEEP); 475 476 st->st_busprivate = job; 477 478 /* skip any leading empty chunks (should not be any!) */ 479 chunk = st->st_chunks; 480 481 /* get transfer opcode */ 482 if ((rv = arspi_get_byte(&chunk, &byte)) != 0) 483 return rv; 484 485 job->job_opcode = byte; 486 switch (job->job_opcode) { 487 case SPIFLASH_CMD_WREN: 488 case SPIFLASH_CMD_WRDI: 489 case SPIFLASH_CMD_CHIPERASE: 490 break; 491 case SPIFLASH_CMD_RDJI: 492 job->job_rxcnt = 3; 493 break; 494 case SPIFLASH_CMD_RDSR: 495 job->job_rxcnt = 1; 496 break; 497 case SPIFLASH_CMD_WRSR: 498 /* 499 * is this in data, or in address? stick it in data 500 * for now. 501 */ 502 job->job_txcnt = 1; 503 break; 504 case SPIFLASH_CMD_RDID: 505 job->job_addrcnt = 3; /* 3 dummy bytes */ 506 job->job_rxcnt = 1; 507 break; 508 case SPIFLASH_CMD_ERASE: 509 job->job_addrcnt = 3; 510 break; 511 case SPIFLASH_CMD_READ: 512 job->job_addrcnt = 3; 513 job->job_flags |= JOB_READ; 514 break; 515 case SPIFLASH_CMD_PROGRAM: 516 job->job_addrcnt = 3; 517 job->job_flags |= JOB_WRITE; 518 break; 519 case SPIFLASH_CMD_READFAST: 520 /* 521 * This is a pain in the arse to support, so we will 522 * rewrite as an ordinary read. But later, after we 523 * obtain the address. 524 */ 525 job->job_addrcnt = 3; /* 3 address */ 526 job->job_flags |= JOB_READ; 527 break; 528 default: 529 return EINVAL; 530 } 531 532 for (i = 0; i < job->job_addrcnt; i++) { 533 if ((rv = arspi_get_byte(&chunk, &byte)) != 0) 534 return rv; 535 job->job_addr <<= 8; 536 job->job_addr |= byte; 537 } 538 539 540 if (job->job_opcode == SPIFLASH_CMD_READFAST) { 541 /* eat the dummy timing byte */ 542 if ((rv = arspi_get_byte(&chunk, &byte)) != 0) 543 return rv; 544 /* rewrite this as a read */ 545 job->job_opcode = SPIFLASH_CMD_READ; 546 } 547 548 job->job_chunk = chunk; 549 550 /* 551 * Now quickly check a few other things. Namely, we are not 552 * allowed to have both READ and WRITE. 553 */ 554 for (chunk = job->job_chunk; chunk; chunk = chunk->chunk_next) { 555 if (chunk->chunk_wptr) { 556 job->job_wresid += chunk->chunk_wresid; 557 } 558 if (chunk->chunk_rptr) { 559 job->job_rresid += chunk->chunk_rresid; 560 } 561 } 562 563 if (job->job_rresid && job->job_wresid) { 564 return EINVAL; 565 } 566 567 return 0; 568} 569 570/* 571 * NB: The Atheros SPI controller runs in little endian mode. So all 572 * data accesses must be swapped appropriately. 573 * 574 * The controller auto-swaps read accesses done through the mapped memory 575 * region, but when using SPI directly, we have to do the right thing to 576 * swap to or from little endian. 577 */ 578 579void 580arspi_update_job(struct spi_transfer *st) 581{ 582 struct arspi_job *job = st->st_busprivate; 583 uint8_t byte; 584 int i; 585 586 if (job->job_flags & (JOB_WAIT|JOB_WREN)) 587 return; 588 589 job->job_rxcnt = 0; 590 job->job_txcnt = 0; 591 job->job_data = 0; 592 593 job->job_txcnt = uimin(job->job_wresid, 4); 594 job->job_rxcnt = uimin(job->job_rresid, 4); 595 596 job->job_wresid -= job->job_txcnt; 597 job->job_rresid -= job->job_rxcnt; 598 599 for (i = 0; i < job->job_txcnt; i++) { 600 arspi_get_byte(&job->job_chunk, &byte); 601 job->job_data |= (byte << (i * 8)); 602 } 603 604 if ((!job->job_wresid) && (!job->job_rresid)) { 605 job->job_flags |= JOB_LAST; 606 } 607} 608 609void 610arspi_finish_job(struct spi_transfer *st) 611{ 612 struct arspi_job *job = st->st_busprivate; 613 uint8_t byte; 614 int i; 615 616 job->job_addr += job->job_rxcnt; 617 job->job_addr += job->job_txcnt; 618 for (i = 0; i < job->job_rxcnt; i++) { 619 byte = job->job_data & 0xff; 620 job->job_data >>= 8; 621 arspi_put_byte(&job->job_chunk, byte); 622 } 623} 624 625