Home | History | Annotate | Line # | Download | only in marvell
mvspi.c revision 1.2.12.2
      1  1.2.12.2  yamt /*******************************************************************************
      2  1.2.12.2  yamt Copyright (C) Marvell International Ltd. and its affiliates
      3  1.2.12.2  yamt 
      4  1.2.12.2  yamt Developed by Semihalf
      5  1.2.12.2  yamt 
      6  1.2.12.2  yamt ********************************************************************************
      7  1.2.12.2  yamt Marvell BSD License
      8  1.2.12.2  yamt 
      9  1.2.12.2  yamt If you received this File from Marvell, you may opt to use, redistribute and/or
     10  1.2.12.2  yamt modify this File under the following licensing terms.
     11  1.2.12.2  yamt Redistribution and use in source and binary forms, with or without modification,
     12  1.2.12.2  yamt are permitted provided that the following conditions are met:
     13  1.2.12.2  yamt 
     14  1.2.12.2  yamt     *   Redistributions of source code must retain the above copyright notice,
     15  1.2.12.2  yamt             this list of conditions and the following disclaimer.
     16  1.2.12.2  yamt 
     17  1.2.12.2  yamt     *   Redistributions in binary form must reproduce the above copyright
     18  1.2.12.2  yamt         notice, this list of conditions and the following disclaimer in the
     19  1.2.12.2  yamt         documentation and/or other materials provided with the distribution.
     20  1.2.12.2  yamt 
     21  1.2.12.2  yamt     *   Neither the name of Marvell nor the names of its contributors may be
     22  1.2.12.2  yamt         used to endorse or promote products derived from this software without
     23  1.2.12.2  yamt         specific prior written permission.
     24  1.2.12.2  yamt 
     25  1.2.12.2  yamt THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     26  1.2.12.2  yamt ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     27  1.2.12.2  yamt WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     28  1.2.12.2  yamt DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     29  1.2.12.2  yamt ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     30  1.2.12.2  yamt (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     31  1.2.12.2  yamt LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     32  1.2.12.2  yamt ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     33  1.2.12.2  yamt (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34  1.2.12.2  yamt SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  1.2.12.2  yamt 
     36  1.2.12.2  yamt *******************************************************************************/
     37  1.2.12.2  yamt 
     38  1.2.12.2  yamt /*
     39  1.2.12.2  yamt  * Transfer mechanism extracted from arspi.c corresponding with the lines
     40  1.2.12.2  yamt  * 254-262 in this file.
     41  1.2.12.2  yamt  */
     42  1.2.12.2  yamt 
     43  1.2.12.2  yamt #include <sys/param.h>
     44  1.2.12.2  yamt #include <sys/device.h>
     45  1.2.12.2  yamt 
     46  1.2.12.2  yamt #include <dev/spi/spivar.h>
     47  1.2.12.2  yamt 
     48  1.2.12.2  yamt #include <dev/marvell/mvspireg.h>
     49  1.2.12.2  yamt #include <dev/marvell/marvellvar.h>
     50  1.2.12.2  yamt 
     51  1.2.12.2  yamt #include "locators.h"
     52  1.2.12.2  yamt 
     53  1.2.12.2  yamt extern uint32_t mvTclk;
     54  1.2.12.2  yamt 
     55  1.2.12.2  yamt struct mvspi_softc {
     56  1.2.12.2  yamt 	struct device		sc_dev;
     57  1.2.12.2  yamt 	struct spi_controller	sc_spi;
     58  1.2.12.2  yamt 	void			*sc_ih;
     59  1.2.12.2  yamt 	bool			sc_interrupts;
     60  1.2.12.2  yamt 
     61  1.2.12.2  yamt 	struct spi_transfer	*sc_transfer;
     62  1.2.12.2  yamt 	struct spi_chunk	*sc_wchunk;	/* For partial writes */
     63  1.2.12.2  yamt 	struct spi_transq	sc_transq;
     64  1.2.12.2  yamt 	bus_space_tag_t		sc_st;
     65  1.2.12.2  yamt 	bus_space_handle_t	sc_sh;
     66  1.2.12.2  yamt 	bus_size_t		sc_size;
     67  1.2.12.2  yamt };
     68  1.2.12.2  yamt 
     69  1.2.12.2  yamt int mvspi_match(struct device *, struct cfdata *, void *);
     70  1.2.12.2  yamt void mvspi_attach(struct device *, struct device *, void *);
     71  1.2.12.2  yamt /* SPI service routines */
     72  1.2.12.2  yamt int mvspi_configure(void *, int, int, int);
     73  1.2.12.2  yamt int mvspi_transfer(void *, struct spi_transfer *);
     74  1.2.12.2  yamt /* Internal support */
     75  1.2.12.2  yamt void mvspi_sched(struct mvspi_softc *);
     76  1.2.12.2  yamt void mvspi_assert(struct mvspi_softc *sc);
     77  1.2.12.2  yamt void mvspi_deassert(struct mvspi_softc *sc);
     78  1.2.12.2  yamt 
     79  1.2.12.2  yamt #define	GETREG(sc, x)					\
     80  1.2.12.2  yamt 	bus_space_read_4(sc->sc_st, sc->sc_sh, x)
     81  1.2.12.2  yamt #define	PUTREG(sc, x, v)				\
     82  1.2.12.2  yamt 	bus_space_write_4(sc->sc_st, sc->sc_sh, x, v)
     83  1.2.12.2  yamt 
     84  1.2.12.2  yamt /* Attach structure */
     85  1.2.12.2  yamt CFATTACH_DECL_NEW(mvspi_mbus, sizeof(struct mvspi_softc),
     86  1.2.12.2  yamt     mvspi_match, mvspi_attach, NULL, NULL);
     87  1.2.12.2  yamt 
     88  1.2.12.2  yamt int
     89  1.2.12.2  yamt mvspi_match(struct device *parent, struct cfdata *cf, void *aux)
     90  1.2.12.2  yamt {
     91  1.2.12.2  yamt 	struct marvell_attach_args *mva = aux;
     92  1.2.12.2  yamt 
     93  1.2.12.2  yamt 	if (strcmp(mva->mva_name, cf->cf_name) != 0)
     94  1.2.12.2  yamt 		return 0;
     95  1.2.12.2  yamt 	if (mva->mva_offset == MVA_OFFSET_DEFAULT ||
     96  1.2.12.2  yamt 	    mva->mva_irq == MVA_IRQ_DEFAULT)
     97  1.2.12.2  yamt 		return 0;
     98  1.2.12.2  yamt 
     99  1.2.12.2  yamt 	mva->mva_size = MVSPI_SIZE;
    100  1.2.12.2  yamt 	return 1;
    101  1.2.12.2  yamt }
    102  1.2.12.2  yamt 
    103  1.2.12.2  yamt void
    104  1.2.12.2  yamt mvspi_attach(struct device *parent, struct device *self, void *aux)
    105  1.2.12.2  yamt {
    106  1.2.12.2  yamt 	struct mvspi_softc *sc =  device_private(self);
    107  1.2.12.2  yamt   	struct marvell_attach_args *mva = aux;
    108  1.2.12.2  yamt 	struct spibus_attach_args sba;
    109  1.2.12.2  yamt 	int ctl;
    110  1.2.12.2  yamt 
    111  1.2.12.2  yamt 	aprint_normal(": Marvell SPI controller\n");
    112  1.2.12.2  yamt 
    113  1.2.12.2  yamt 	/*
    114  1.2.12.2  yamt 	 * Map registers.
    115  1.2.12.2  yamt 	 */
    116  1.2.12.2  yamt 	sc->sc_st = mva->mva_iot;
    117  1.2.12.2  yamt 	sc->sc_size = mva->mva_size;
    118  1.2.12.2  yamt 
    119  1.2.12.2  yamt 	if (bus_space_subregion(sc->sc_st, mva->mva_ioh, mva->mva_offset,
    120  1.2.12.2  yamt 	    mva->mva_size, &sc->sc_sh)) {
    121  1.2.12.2  yamt 		aprint_error_dev(self, "Cannot map registers\n");
    122  1.2.12.2  yamt 		return;
    123  1.2.12.2  yamt 	}
    124  1.2.12.2  yamt 
    125  1.2.12.2  yamt 	/*
    126  1.2.12.2  yamt 	 * Initialize hardware.
    127  1.2.12.2  yamt 	 */
    128  1.2.12.2  yamt 	ctl = GETREG(sc, MVSPI_INTCONF_REG);
    129  1.2.12.2  yamt 
    130  1.2.12.2  yamt 	ctl &= MVSPI_DIRHS_MASK;
    131  1.2.12.2  yamt 	ctl &= MVSPI_1BYTE_MASK;
    132  1.2.12.2  yamt 
    133  1.2.12.2  yamt 	PUTREG(sc, MVSPI_INTCONF_REG, ctl),
    134  1.2.12.2  yamt 
    135  1.2.12.2  yamt 	/*
    136  1.2.12.2  yamt 	 * Initialize SPI controller.
    137  1.2.12.2  yamt 	 */
    138  1.2.12.2  yamt 	sc->sc_spi.sct_cookie = sc;
    139  1.2.12.2  yamt 	sc->sc_spi.sct_configure = mvspi_configure;
    140  1.2.12.2  yamt 	sc->sc_spi.sct_transfer = mvspi_transfer;
    141  1.2.12.2  yamt 	sc->sc_spi.sct_nslaves = 1;
    142  1.2.12.2  yamt 
    143  1.2.12.2  yamt 	/*
    144  1.2.12.2  yamt 	 * Initialize the queue.
    145  1.2.12.2  yamt 	 */
    146  1.2.12.2  yamt 	spi_transq_init(&sc->sc_transq);
    147  1.2.12.2  yamt 
    148  1.2.12.2  yamt 	/*
    149  1.2.12.2  yamt 	 * Initialize and attach bus attach.
    150  1.2.12.2  yamt 	 */
    151  1.2.12.2  yamt 	sba.sba_controller = &sc->sc_spi;
    152  1.2.12.2  yamt 	(void) config_found_ia(self, "spibus", &sba, spibus_print);
    153  1.2.12.2  yamt }
    154  1.2.12.2  yamt 
    155  1.2.12.2  yamt int
    156  1.2.12.2  yamt mvspi_configure(void *cookie, int slave, int mode, int speed)
    157  1.2.12.2  yamt {
    158  1.2.12.2  yamt 	struct mvspi_softc *sc = cookie;
    159  1.2.12.2  yamt 	uint32_t ctl = 0, spr, sppr;
    160  1.2.12.2  yamt 	uint32_t divider;
    161  1.2.12.2  yamt 	uint32_t best_spr = 0, best_sppr = 0;
    162  1.2.12.2  yamt 	uint32_t best_sppr0, best_spprhi;
    163  1.2.12.2  yamt 	uint8_t exact_match = 0;
    164  1.2.12.2  yamt 	uint32_t min_baud_offset = 0xFFFFFFFF;
    165  1.2.12.2  yamt 
    166  1.2.12.2  yamt 	if (slave < 0 || slave > 7)
    167  1.2.12.2  yamt 		return EINVAL;
    168  1.2.12.2  yamt 
    169  1.2.12.2  yamt 	switch(mode) {
    170  1.2.12.2  yamt 		case SPI_MODE_0:
    171  1.2.12.2  yamt 			ctl &= ~(MVSPI_CPOL_MASK);
    172  1.2.12.2  yamt 			/* In boards documentation, CPHA is inverted */
    173  1.2.12.2  yamt 			ctl &= MVSPI_CPHA_MASK;
    174  1.2.12.2  yamt 			break;
    175  1.2.12.2  yamt 		case SPI_MODE_1:
    176  1.2.12.2  yamt 			ctl |= MVSPI_CPOL_MASK;
    177  1.2.12.2  yamt 			ctl &= MVSPI_CPHA_MASK;
    178  1.2.12.2  yamt 			break;
    179  1.2.12.2  yamt 		case SPI_MODE_2:
    180  1.2.12.2  yamt 			ctl &= ~(MVSPI_CPOL_MASK);
    181  1.2.12.2  yamt 			ctl |= ~(MVSPI_CPHA_MASK);
    182  1.2.12.2  yamt 			break;
    183  1.2.12.2  yamt 		case SPI_MODE_3:
    184  1.2.12.2  yamt 			ctl |= MVSPI_CPOL_MASK;
    185  1.2.12.2  yamt 			ctl |= ~(MVSPI_CPHA_MASK);
    186  1.2.12.2  yamt 			break;
    187  1.2.12.2  yamt 		default:
    188  1.2.12.2  yamt 			return EINVAL;
    189  1.2.12.2  yamt 	}
    190  1.2.12.2  yamt 
    191  1.2.12.2  yamt 	/* Find the best prescale configuration - less or equal:
    192  1.2.12.2  yamt 	 * SPI actual frecuency = core_clk / (SPR * (2 ^ SPPR))
    193  1.2.12.2  yamt 	 * Try to find the minimal SPR and SPPR values that offer
    194  1.2.12.2  yamt 	 * the best prescale config.
    195  1.2.12.2  yamt 	 *
    196  1.2.12.2  yamt 	 */
    197  1.2.12.2  yamt 	for (spr = 1; spr <= MVSPI_SPR_MAXVALUE; spr++) {
    198  1.2.12.2  yamt 		for (sppr = 0; sppr <= MVSPI_SPPR_MAXVALUE; sppr++) {
    199  1.2.12.2  yamt 			divider = spr * (1 << sppr);
    200  1.2.12.2  yamt 			/* Check for higher - irrelevant */
    201  1.2.12.2  yamt 			if ((mvTclk / divider) > speed)
    202  1.2.12.2  yamt 				continue;
    203  1.2.12.2  yamt 
    204  1.2.12.2  yamt 			/* Check for exact fit */
    205  1.2.12.2  yamt 			if ((mvTclk / divider) == speed) {
    206  1.2.12.2  yamt 				best_spr = spr;
    207  1.2.12.2  yamt 				best_sppr = sppr;
    208  1.2.12.2  yamt 				exact_match = 1;
    209  1.2.12.2  yamt 				break;
    210  1.2.12.2  yamt 			}
    211  1.2.12.2  yamt 
    212  1.2.12.2  yamt 			/* Check if this is better than the previous one */
    213  1.2.12.2  yamt 			if ((speed - (mvTclk / divider)) < min_baud_offset) {
    214  1.2.12.2  yamt 				min_baud_offset = (speed - (mvTclk / divider));
    215  1.2.12.2  yamt 				best_spr = spr;
    216  1.2.12.2  yamt 				best_sppr = sppr;
    217  1.2.12.2  yamt 			}
    218  1.2.12.2  yamt 		}
    219  1.2.12.2  yamt 
    220  1.2.12.2  yamt 		if (exact_match == 1)
    221  1.2.12.2  yamt 			break;
    222  1.2.12.2  yamt 	}
    223  1.2.12.2  yamt 
    224  1.2.12.2  yamt 	if (best_spr == 0) {
    225  1.2.12.2  yamt 		printf("%s ERROR: SPI baud rate prescale error!\n", __func__);
    226  1.2.12.2  yamt 		return -1;
    227  1.2.12.2  yamt 	}
    228  1.2.12.2  yamt 
    229  1.2.12.2  yamt 	ctl &= ~(MVSPI_SPR_MASK);
    230  1.2.12.2  yamt 	ctl &= ~(MVSPI_SPPR_MASK);
    231  1.2.12.2  yamt 	ctl |= best_spr;
    232  1.2.12.2  yamt 
    233  1.2.12.2  yamt 	best_spprhi = best_sppr & MVSPI_SPPRHI_MASK;
    234  1.2.12.2  yamt 	best_spprhi = best_spprhi << 5;
    235  1.2.12.2  yamt 
    236  1.2.12.2  yamt 	ctl |= best_spprhi;
    237  1.2.12.2  yamt 
    238  1.2.12.2  yamt 	best_sppr0 = best_sppr & MVSPI_SPPR0_MASK;
    239  1.2.12.2  yamt 	best_sppr0 = best_sppr0 << 4;
    240  1.2.12.2  yamt 
    241  1.2.12.2  yamt 	ctl |= best_sppr0;
    242  1.2.12.2  yamt 
    243  1.2.12.2  yamt 	PUTREG(sc, MVSPI_INTCONF_REG, ctl);
    244  1.2.12.2  yamt 
    245  1.2.12.2  yamt 	return 0;
    246  1.2.12.2  yamt }
    247  1.2.12.2  yamt 
    248  1.2.12.2  yamt int
    249  1.2.12.2  yamt mvspi_transfer(void *cookie, struct spi_transfer *st)
    250  1.2.12.2  yamt {
    251  1.2.12.2  yamt 	struct mvspi_softc *sc = cookie;
    252  1.2.12.2  yamt 	int s;
    253  1.2.12.2  yamt 
    254  1.2.12.2  yamt 	s = splbio();
    255  1.2.12.2  yamt 	spi_transq_enqueue(&sc->sc_transq, st);
    256  1.2.12.2  yamt 	if (sc->sc_transfer == NULL) {
    257  1.2.12.2  yamt 		mvspi_sched(sc);
    258  1.2.12.2  yamt 	}
    259  1.2.12.2  yamt 	splx(s);
    260  1.2.12.2  yamt 	return 0;
    261  1.2.12.2  yamt }
    262  1.2.12.2  yamt 
    263  1.2.12.2  yamt void
    264  1.2.12.2  yamt mvspi_assert(struct mvspi_softc *sc)
    265  1.2.12.2  yamt {
    266  1.2.12.2  yamt 	int ctl;
    267  1.2.12.2  yamt 
    268  1.2.12.2  yamt 	if (sc->sc_transfer->st_slave < 0 && sc->sc_transfer->st_slave > 7) {
    269  1.2.12.2  yamt 		printf("%s ERROR: Slave number %d not valid!\n",  __func__, sc->sc_transfer->st_slave);
    270  1.2.12.2  yamt 		return;
    271  1.2.12.2  yamt 	} else
    272  1.2.12.2  yamt 		/* Enable appropriate CSn according to its slave number */
    273  1.2.12.2  yamt 		PUTREG(sc, MVSPI_CTRL_REG, (sc->sc_transfer->st_slave << 2));
    274  1.2.12.2  yamt 
    275  1.2.12.2  yamt 	/* Enable CSnAct */
    276  1.2.12.2  yamt 	ctl = GETREG(sc, MVSPI_CTRL_REG);
    277  1.2.12.2  yamt 	ctl |= MVSPI_CSNACT_MASK;
    278  1.2.12.2  yamt 	PUTREG(sc, MVSPI_CTRL_REG, ctl);
    279  1.2.12.2  yamt }
    280  1.2.12.2  yamt 
    281  1.2.12.2  yamt void
    282  1.2.12.2  yamt mvspi_deassert(struct mvspi_softc *sc)
    283  1.2.12.2  yamt {
    284  1.2.12.2  yamt 	int ctl = GETREG(sc, MVSPI_CTRL_REG);
    285  1.2.12.2  yamt 	ctl &= ~(MVSPI_CSNACT_MASK);
    286  1.2.12.2  yamt 	PUTREG(sc, MVSPI_CTRL_REG, ctl);
    287  1.2.12.2  yamt }
    288  1.2.12.2  yamt 
    289  1.2.12.2  yamt void
    290  1.2.12.2  yamt mvspi_sched(struct mvspi_softc *sc)
    291  1.2.12.2  yamt {
    292  1.2.12.2  yamt 	struct spi_transfer *st;
    293  1.2.12.2  yamt 	struct spi_chunk *chunk;
    294  1.2.12.2  yamt 	int i, j, ctl;
    295  1.2.12.2  yamt 	uint8_t byte;
    296  1.2.12.2  yamt 	int ready = FALSE;
    297  1.2.12.2  yamt 
    298  1.2.12.2  yamt 	for (;;) {
    299  1.2.12.2  yamt 		if ((st = sc->sc_transfer) == NULL) {
    300  1.2.12.2  yamt 			if ((st = spi_transq_first(&sc->sc_transq)) == NULL) {
    301  1.2.12.2  yamt 				/* No work left to do */
    302  1.2.12.2  yamt 				break;
    303  1.2.12.2  yamt 			}
    304  1.2.12.2  yamt 			spi_transq_dequeue(&sc->sc_transq);
    305  1.2.12.2  yamt 			sc->sc_transfer = st;
    306  1.2.12.2  yamt 		}
    307  1.2.12.2  yamt 
    308  1.2.12.2  yamt 		chunk = st->st_chunks;
    309  1.2.12.2  yamt 
    310  1.2.12.2  yamt 		mvspi_assert(sc);
    311  1.2.12.2  yamt 
    312  1.2.12.2  yamt 		do {
    313  1.2.12.2  yamt 			for (i = chunk->chunk_wresid; i > 0; i--) {
    314  1.2.12.2  yamt 				/* First clear the ready bit */
    315  1.2.12.2  yamt 				ctl = GETREG(sc, MVSPI_CTRL_REG);
    316  1.2.12.2  yamt 				ctl &= ~(MVSPI_CR_SMEMRDY);
    317  1.2.12.2  yamt 				PUTREG(sc, MVSPI_CTRL_REG, ctl);
    318  1.2.12.2  yamt 
    319  1.2.12.2  yamt 				if (chunk->chunk_wptr){
    320  1.2.12.2  yamt 					byte = *chunk->chunk_wptr;
    321  1.2.12.2  yamt 					chunk->chunk_wptr++;
    322  1.2.12.2  yamt 				} else
    323  1.2.12.2  yamt 					byte = MVSPI_DUMMY_BYTE;
    324  1.2.12.2  yamt 
    325  1.2.12.2  yamt 				/* Transmit data */
    326  1.2.12.2  yamt 				PUTREG(sc, MVSPI_DATAOUT_REG, byte);
    327  1.2.12.2  yamt 
    328  1.2.12.2  yamt 				/* Wait with timeout for memory ready */
    329  1.2.12.2  yamt 				for (j = 0; j < MVSPI_WAIT_RDY_MAX_LOOP; j++) {
    330  1.2.12.2  yamt 					if (GETREG(sc, MVSPI_CTRL_REG) &
    331  1.2.12.2  yamt 						MVSPI_CR_SMEMRDY) {
    332  1.2.12.2  yamt 						ready = TRUE;
    333  1.2.12.2  yamt 						break;
    334  1.2.12.2  yamt 					}
    335  1.2.12.2  yamt 
    336  1.2.12.2  yamt 				}
    337  1.2.12.2  yamt 
    338  1.2.12.2  yamt 				if (!ready) {
    339  1.2.12.2  yamt 					mvspi_deassert(sc);
    340  1.2.12.2  yamt 					spi_done(st, EBUSY);
    341  1.2.12.2  yamt 					return;
    342  1.2.12.2  yamt 				}
    343  1.2.12.2  yamt 
    344  1.2.12.2  yamt 				/* Check that the RX data is needed */
    345  1.2.12.2  yamt 				if (chunk->chunk_rptr) {
    346  1.2.12.2  yamt 					*chunk->chunk_rptr =
    347  1.2.12.2  yamt 						GETREG(sc, MVSPI_DATAIN_REG);
    348  1.2.12.2  yamt 					chunk->chunk_rptr++;
    349  1.2.12.2  yamt 
    350  1.2.12.2  yamt 				}
    351  1.2.12.2  yamt 
    352  1.2.12.2  yamt 			}
    353  1.2.12.2  yamt 
    354  1.2.12.2  yamt 			chunk = chunk->chunk_next;
    355  1.2.12.2  yamt 
    356  1.2.12.2  yamt 		} while (chunk != NULL);
    357  1.2.12.2  yamt 
    358  1.2.12.2  yamt 		mvspi_deassert(sc);
    359  1.2.12.2  yamt 
    360  1.2.12.2  yamt 		spi_done(st, 0);
    361  1.2.12.2  yamt 		sc->sc_transfer = NULL;
    362  1.2.12.2  yamt 
    363  1.2.12.2  yamt 
    364  1.2.12.2  yamt 		break;
    365  1.2.12.2  yamt 	}
    366  1.2.12.2  yamt }
    367