1*f88c431bSChristophe Leroy /* 2*f88c431bSChristophe Leroy * Copyright (c) 2001 Navin Boppuri / Prashant Patel 3*f88c431bSChristophe Leroy * <nboppuri@trinetcommunication.com>, 4*f88c431bSChristophe Leroy * <pmpatel@trinetcommunication.com> 5*f88c431bSChristophe Leroy * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de> 6*f88c431bSChristophe Leroy * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>. 7*f88c431bSChristophe Leroy * 8*f88c431bSChristophe Leroy * SPDX-License-Identifier: GPL-2.0+ 9*f88c431bSChristophe Leroy */ 10*f88c431bSChristophe Leroy 11*f88c431bSChristophe Leroy /* 12*f88c431bSChristophe Leroy * MPC8xx CPM SPI interface. 13*f88c431bSChristophe Leroy * 14*f88c431bSChristophe Leroy * Parts of this code are probably not portable and/or specific to 15*f88c431bSChristophe Leroy * the board which I used for the tests. Please send fixes/complaints 16*f88c431bSChristophe Leroy * to wd@denx.de 17*f88c431bSChristophe Leroy * 18*f88c431bSChristophe Leroy */ 19*f88c431bSChristophe Leroy 20*f88c431bSChristophe Leroy #include <common.h> 21*f88c431bSChristophe Leroy #include <mpc8xx.h> 22*f88c431bSChristophe Leroy #include <commproc.h> 23*f88c431bSChristophe Leroy #include <linux/ctype.h> 24*f88c431bSChristophe Leroy #include <malloc.h> 25*f88c431bSChristophe Leroy #include <post.h> 26*f88c431bSChristophe Leroy #include <serial.h> 27*f88c431bSChristophe Leroy 28*f88c431bSChristophe Leroy #define SPI_EEPROM_WREN 0x06 29*f88c431bSChristophe Leroy #define SPI_EEPROM_RDSR 0x05 30*f88c431bSChristophe Leroy #define SPI_EEPROM_READ 0x03 31*f88c431bSChristophe Leroy #define SPI_EEPROM_WRITE 0x02 32*f88c431bSChristophe Leroy 33*f88c431bSChristophe Leroy /* --------------------------------------------------------------- 34*f88c431bSChristophe Leroy * Offset for initial SPI buffers in DPRAM: 35*f88c431bSChristophe Leroy * We need a 520 byte scratch DPRAM area to use at an early stage. 36*f88c431bSChristophe Leroy * It is used between the two initialization calls (spi_init_f() 37*f88c431bSChristophe Leroy * and spi_init_r()). 38*f88c431bSChristophe Leroy * The value 0xb00 makes it far enough from the start of the data 39*f88c431bSChristophe Leroy * area (as well as from the stack pointer). 40*f88c431bSChristophe Leroy * --------------------------------------------------------------- */ 41*f88c431bSChristophe Leroy #ifndef CONFIG_SYS_SPI_INIT_OFFSET 42*f88c431bSChristophe Leroy #define CONFIG_SYS_SPI_INIT_OFFSET 0xB00 43*f88c431bSChristophe Leroy #endif 44*f88c431bSChristophe Leroy 45*f88c431bSChristophe Leroy #define CPM_SPI_BASE_RX CPM_SPI_BASE 46*f88c431bSChristophe Leroy #define CPM_SPI_BASE_TX (CPM_SPI_BASE + sizeof(cbd_t)) 47*f88c431bSChristophe Leroy 48*f88c431bSChristophe Leroy /* ------------------- 49*f88c431bSChristophe Leroy * Function prototypes 50*f88c431bSChristophe Leroy * ------------------- */ 51*f88c431bSChristophe Leroy ssize_t spi_xfer(size_t); 52*f88c431bSChristophe Leroy 53*f88c431bSChristophe Leroy /* ------------------- 54*f88c431bSChristophe Leroy * Variables 55*f88c431bSChristophe Leroy * ------------------- */ 56*f88c431bSChristophe Leroy 57*f88c431bSChristophe Leroy #define MAX_BUFFER 0x104 58*f88c431bSChristophe Leroy 59*f88c431bSChristophe Leroy /* ---------------------------------------------------------------------- 60*f88c431bSChristophe Leroy * Initially we place the RX and TX buffers at a fixed location in DPRAM! 61*f88c431bSChristophe Leroy * ---------------------------------------------------------------------- */ 62*f88c431bSChristophe Leroy static uchar *rxbuf = 63*f88c431bSChristophe Leroy (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem 64*f88c431bSChristophe Leroy [CONFIG_SYS_SPI_INIT_OFFSET]; 65*f88c431bSChristophe Leroy static uchar *txbuf = 66*f88c431bSChristophe Leroy (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem 67*f88c431bSChristophe Leroy [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER]; 68*f88c431bSChristophe Leroy 69*f88c431bSChristophe Leroy /* ************************************************************************** 70*f88c431bSChristophe Leroy * 71*f88c431bSChristophe Leroy * Function: spi_init_f 72*f88c431bSChristophe Leroy * 73*f88c431bSChristophe Leroy * Description: Init SPI-Controller (ROM part) 74*f88c431bSChristophe Leroy * 75*f88c431bSChristophe Leroy * return: --- 76*f88c431bSChristophe Leroy * 77*f88c431bSChristophe Leroy * *********************************************************************** */ 78*f88c431bSChristophe Leroy void spi_init_f(void) 79*f88c431bSChristophe Leroy { 80*f88c431bSChristophe Leroy immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; 81*f88c431bSChristophe Leroy cpm8xx_t __iomem *cp = &immr->im_cpm; 82*f88c431bSChristophe Leroy spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; 83*f88c431bSChristophe Leroy cbd_t __iomem *tbdf, *rbdf; 84*f88c431bSChristophe Leroy 85*f88c431bSChristophe Leroy /* Disable relocation */ 86*f88c431bSChristophe Leroy out_be16(&spi->spi_rpbase, 0); 87*f88c431bSChristophe Leroy 88*f88c431bSChristophe Leroy /* 1 */ 89*f88c431bSChristophe Leroy /* ------------------------------------------------ 90*f88c431bSChristophe Leroy * Initialize Port B SPI pins -> page 34-8 MPC860UM 91*f88c431bSChristophe Leroy * (we are only in Master Mode !) 92*f88c431bSChristophe Leroy * ------------------------------------------------ */ 93*f88c431bSChristophe Leroy 94*f88c431bSChristophe Leroy /* -------------------------------------------- 95*f88c431bSChristophe Leroy * GPIO or per. Function 96*f88c431bSChristophe Leroy * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO) 97*f88c431bSChristophe Leroy * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI) 98*f88c431bSChristophe Leroy * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK) 99*f88c431bSChristophe Leroy * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM) 100*f88c431bSChristophe Leroy * -------------------------------------------- */ 101*f88c431bSChristophe Leroy clrsetbits_be32(&cp->cp_pbpar, 0x00000001, 0x0000000E); /* set bits */ 102*f88c431bSChristophe Leroy 103*f88c431bSChristophe Leroy /* ---------------------------------------------- 104*f88c431bSChristophe Leroy * In/Out or per. Function 0/1 105*f88c431bSChristophe Leroy * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO 106*f88c431bSChristophe Leroy * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI 107*f88c431bSChristophe Leroy * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK 108*f88c431bSChristophe Leroy * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM 109*f88c431bSChristophe Leroy * ---------------------------------------------- */ 110*f88c431bSChristophe Leroy setbits_be32(&cp->cp_pbdir, 0x0000000F); 111*f88c431bSChristophe Leroy 112*f88c431bSChristophe Leroy /* ---------------------------------------------- 113*f88c431bSChristophe Leroy * open drain or active output 114*f88c431bSChristophe Leroy * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO 115*f88c431bSChristophe Leroy * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI 116*f88c431bSChristophe Leroy * PBODR[30] = 0 [0x00000002] -> active output: SPICLK 117*f88c431bSChristophe Leroy * PBODR[31] = 0 [0x00000001] -> active output GPIO OUT: CS for PCUE/CCM 118*f88c431bSChristophe Leroy * ---------------------------------------------- */ 119*f88c431bSChristophe Leroy 120*f88c431bSChristophe Leroy clrsetbits_be16(&cp->cp_pbodr, 0x00000007, 0x00000008); 121*f88c431bSChristophe Leroy 122*f88c431bSChristophe Leroy /* Initialize the parameter ram. 123*f88c431bSChristophe Leroy * We need to make sure many things are initialized to zero 124*f88c431bSChristophe Leroy */ 125*f88c431bSChristophe Leroy out_be32(&spi->spi_rstate, 0); 126*f88c431bSChristophe Leroy out_be32(&spi->spi_rdp, 0); 127*f88c431bSChristophe Leroy out_be16(&spi->spi_rbptr, 0); 128*f88c431bSChristophe Leroy out_be16(&spi->spi_rbc, 0); 129*f88c431bSChristophe Leroy out_be32(&spi->spi_rxtmp, 0); 130*f88c431bSChristophe Leroy out_be32(&spi->spi_tstate, 0); 131*f88c431bSChristophe Leroy out_be32(&spi->spi_tdp, 0); 132*f88c431bSChristophe Leroy out_be16(&spi->spi_tbptr, 0); 133*f88c431bSChristophe Leroy out_be16(&spi->spi_tbc, 0); 134*f88c431bSChristophe Leroy out_be32(&spi->spi_txtmp, 0); 135*f88c431bSChristophe Leroy 136*f88c431bSChristophe Leroy /* 3 */ 137*f88c431bSChristophe Leroy /* Set up the SPI parameters in the parameter ram */ 138*f88c431bSChristophe Leroy out_be16(&spi->spi_rbase, CPM_SPI_BASE_RX); 139*f88c431bSChristophe Leroy out_be16(&spi->spi_tbase, CPM_SPI_BASE_TX); 140*f88c431bSChristophe Leroy 141*f88c431bSChristophe Leroy /***********IMPORTANT******************/ 142*f88c431bSChristophe Leroy 143*f88c431bSChristophe Leroy /* 144*f88c431bSChristophe Leroy * Setting transmit and receive buffer descriptor pointers 145*f88c431bSChristophe Leroy * initially to rbase and tbase. Only the microcode patches 146*f88c431bSChristophe Leroy * documentation talks about initializing this pointer. This 147*f88c431bSChristophe Leroy * is missing from the sample I2C driver. If you dont 148*f88c431bSChristophe Leroy * initialize these pointers, the kernel hangs. 149*f88c431bSChristophe Leroy */ 150*f88c431bSChristophe Leroy out_be16(&spi->spi_rbptr, CPM_SPI_BASE_RX); 151*f88c431bSChristophe Leroy out_be16(&spi->spi_tbptr, CPM_SPI_BASE_TX); 152*f88c431bSChristophe Leroy 153*f88c431bSChristophe Leroy /* 4 */ 154*f88c431bSChristophe Leroy /* Init SPI Tx + Rx Parameters */ 155*f88c431bSChristophe Leroy while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) 156*f88c431bSChristophe Leroy ; 157*f88c431bSChristophe Leroy 158*f88c431bSChristophe Leroy out_be16(&cp->cp_cpcr, mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | 159*f88c431bSChristophe Leroy CPM_CR_FLG); 160*f88c431bSChristophe Leroy while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) 161*f88c431bSChristophe Leroy ; 162*f88c431bSChristophe Leroy 163*f88c431bSChristophe Leroy /* 5 */ 164*f88c431bSChristophe Leroy /* Set SDMA configuration register */ 165*f88c431bSChristophe Leroy out_be32(&immr->im_siu_conf.sc_sdcr, 0x0001); 166*f88c431bSChristophe Leroy 167*f88c431bSChristophe Leroy /* 6 */ 168*f88c431bSChristophe Leroy /* Set to big endian. */ 169*f88c431bSChristophe Leroy out_8(&spi->spi_tfcr, SMC_EB); 170*f88c431bSChristophe Leroy out_8(&spi->spi_rfcr, SMC_EB); 171*f88c431bSChristophe Leroy 172*f88c431bSChristophe Leroy /* 7 */ 173*f88c431bSChristophe Leroy /* Set maximum receive size. */ 174*f88c431bSChristophe Leroy out_be16(&spi->spi_mrblr, MAX_BUFFER); 175*f88c431bSChristophe Leroy 176*f88c431bSChristophe Leroy /* 8 + 9 */ 177*f88c431bSChristophe Leroy /* tx and rx buffer descriptors */ 178*f88c431bSChristophe Leroy tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; 179*f88c431bSChristophe Leroy rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX]; 180*f88c431bSChristophe Leroy 181*f88c431bSChristophe Leroy clrbits_be16(&tbdf->cbd_sc, BD_SC_READY); 182*f88c431bSChristophe Leroy clrbits_be16(&rbdf->cbd_sc, BD_SC_EMPTY); 183*f88c431bSChristophe Leroy 184*f88c431bSChristophe Leroy /* Set the bd's rx and tx buffer address pointers */ 185*f88c431bSChristophe Leroy out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf); 186*f88c431bSChristophe Leroy out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf); 187*f88c431bSChristophe Leroy 188*f88c431bSChristophe Leroy /* 10 + 11 */ 189*f88c431bSChristophe Leroy out_8(&cp->cp_spim, 0); /* Mask all SPI events */ 190*f88c431bSChristophe Leroy out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */ 191*f88c431bSChristophe Leroy 192*f88c431bSChristophe Leroy return; 193*f88c431bSChristophe Leroy } 194*f88c431bSChristophe Leroy 195*f88c431bSChristophe Leroy /* ************************************************************************** 196*f88c431bSChristophe Leroy * 197*f88c431bSChristophe Leroy * Function: spi_init_r 198*f88c431bSChristophe Leroy * 199*f88c431bSChristophe Leroy * Description: Init SPI-Controller (RAM part) - 200*f88c431bSChristophe Leroy * The malloc engine is ready and we can move our buffers to 201*f88c431bSChristophe Leroy * normal RAM 202*f88c431bSChristophe Leroy * 203*f88c431bSChristophe Leroy * return: --- 204*f88c431bSChristophe Leroy * 205*f88c431bSChristophe Leroy * *********************************************************************** */ 206*f88c431bSChristophe Leroy void spi_init_r(void) 207*f88c431bSChristophe Leroy { 208*f88c431bSChristophe Leroy immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; 209*f88c431bSChristophe Leroy cpm8xx_t __iomem *cp = &immr->im_cpm; 210*f88c431bSChristophe Leroy spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; 211*f88c431bSChristophe Leroy cbd_t __iomem *tbdf, *rbdf; 212*f88c431bSChristophe Leroy 213*f88c431bSChristophe Leroy /* Disable relocation */ 214*f88c431bSChristophe Leroy out_be16(&spi->spi_rpbase, 0); 215*f88c431bSChristophe Leroy 216*f88c431bSChristophe Leroy /* tx and rx buffer descriptors */ 217*f88c431bSChristophe Leroy tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; 218*f88c431bSChristophe Leroy rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX]; 219*f88c431bSChristophe Leroy 220*f88c431bSChristophe Leroy /* Allocate memory for RX and TX buffers */ 221*f88c431bSChristophe Leroy rxbuf = (uchar *)malloc(MAX_BUFFER); 222*f88c431bSChristophe Leroy txbuf = (uchar *)malloc(MAX_BUFFER); 223*f88c431bSChristophe Leroy 224*f88c431bSChristophe Leroy out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf); 225*f88c431bSChristophe Leroy out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf); 226*f88c431bSChristophe Leroy 227*f88c431bSChristophe Leroy return; 228*f88c431bSChristophe Leroy } 229*f88c431bSChristophe Leroy 230*f88c431bSChristophe Leroy /**************************************************************************** 231*f88c431bSChristophe Leroy * Function: spi_write 232*f88c431bSChristophe Leroy **************************************************************************** */ 233*f88c431bSChristophe Leroy ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len) 234*f88c431bSChristophe Leroy { 235*f88c431bSChristophe Leroy int i; 236*f88c431bSChristophe Leroy 237*f88c431bSChristophe Leroy memset(rxbuf, 0, MAX_BUFFER); 238*f88c431bSChristophe Leroy memset(txbuf, 0, MAX_BUFFER); 239*f88c431bSChristophe Leroy *txbuf = SPI_EEPROM_WREN; /* write enable */ 240*f88c431bSChristophe Leroy spi_xfer(1); 241*f88c431bSChristophe Leroy memcpy(txbuf, addr, alen); 242*f88c431bSChristophe Leroy *txbuf = SPI_EEPROM_WRITE; /* WRITE memory array */ 243*f88c431bSChristophe Leroy memcpy(alen + txbuf, buffer, len); 244*f88c431bSChristophe Leroy spi_xfer(alen + len); 245*f88c431bSChristophe Leroy /* ignore received data */ 246*f88c431bSChristophe Leroy for (i = 0; i < 1000; i++) { 247*f88c431bSChristophe Leroy *txbuf = SPI_EEPROM_RDSR; /* read status */ 248*f88c431bSChristophe Leroy txbuf[1] = 0; 249*f88c431bSChristophe Leroy spi_xfer(2); 250*f88c431bSChristophe Leroy if (!(rxbuf[1] & 1)) 251*f88c431bSChristophe Leroy break; 252*f88c431bSChristophe Leroy udelay(1000); 253*f88c431bSChristophe Leroy } 254*f88c431bSChristophe Leroy if (i >= 1000) 255*f88c431bSChristophe Leroy printf("*** spi_write: Time out while writing!\n"); 256*f88c431bSChristophe Leroy 257*f88c431bSChristophe Leroy return len; 258*f88c431bSChristophe Leroy } 259*f88c431bSChristophe Leroy 260*f88c431bSChristophe Leroy /**************************************************************************** 261*f88c431bSChristophe Leroy * Function: spi_read 262*f88c431bSChristophe Leroy **************************************************************************** */ 263*f88c431bSChristophe Leroy ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len) 264*f88c431bSChristophe Leroy { 265*f88c431bSChristophe Leroy memset(rxbuf, 0, MAX_BUFFER); 266*f88c431bSChristophe Leroy memset(txbuf, 0, MAX_BUFFER); 267*f88c431bSChristophe Leroy memcpy(txbuf, addr, alen); 268*f88c431bSChristophe Leroy *txbuf = SPI_EEPROM_READ; /* READ memory array */ 269*f88c431bSChristophe Leroy 270*f88c431bSChristophe Leroy /* 271*f88c431bSChristophe Leroy * There is a bug in 860T (?) that cuts the last byte of input 272*f88c431bSChristophe Leroy * if we're reading into DPRAM. The solution we choose here is 273*f88c431bSChristophe Leroy * to always read len+1 bytes (we have one extra byte at the 274*f88c431bSChristophe Leroy * end of the buffer). 275*f88c431bSChristophe Leroy */ 276*f88c431bSChristophe Leroy spi_xfer(alen + len + 1); 277*f88c431bSChristophe Leroy memcpy(buffer, alen + rxbuf, len); 278*f88c431bSChristophe Leroy 279*f88c431bSChristophe Leroy return len; 280*f88c431bSChristophe Leroy } 281*f88c431bSChristophe Leroy 282*f88c431bSChristophe Leroy /**************************************************************************** 283*f88c431bSChristophe Leroy * Function: spi_xfer 284*f88c431bSChristophe Leroy **************************************************************************** */ 285*f88c431bSChristophe Leroy ssize_t spi_xfer(size_t count) 286*f88c431bSChristophe Leroy { 287*f88c431bSChristophe Leroy immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; 288*f88c431bSChristophe Leroy cpm8xx_t __iomem *cp = &immr->im_cpm; 289*f88c431bSChristophe Leroy spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; 290*f88c431bSChristophe Leroy cbd_t __iomem *tbdf, *rbdf; 291*f88c431bSChristophe Leroy int tm; 292*f88c431bSChristophe Leroy 293*f88c431bSChristophe Leroy /* Disable relocation */ 294*f88c431bSChristophe Leroy out_be16(&spi->spi_rpbase, 0); 295*f88c431bSChristophe Leroy 296*f88c431bSChristophe Leroy tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; 297*f88c431bSChristophe Leroy rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX]; 298*f88c431bSChristophe Leroy 299*f88c431bSChristophe Leroy /* Set CS for device */ 300*f88c431bSChristophe Leroy clrbits_be32(&cp->cp_pbdat, 0x0001); 301*f88c431bSChristophe Leroy 302*f88c431bSChristophe Leroy /* Setting tx bd status and data length */ 303*f88c431bSChristophe Leroy out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP); 304*f88c431bSChristophe Leroy out_be16(&tbdf->cbd_datlen, count); 305*f88c431bSChristophe Leroy 306*f88c431bSChristophe Leroy /* Setting rx bd status and data length */ 307*f88c431bSChristophe Leroy out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); 308*f88c431bSChristophe Leroy out_be16(&rbdf->cbd_datlen, 0); /* rx length has no significance */ 309*f88c431bSChristophe Leroy 310*f88c431bSChristophe Leroy clrsetbits_be16(&cp->cp_spmode, ~SPMODE_LOOP, SPMODE_REV | SPMODE_MSTR | 311*f88c431bSChristophe Leroy SPMODE_EN | SPMODE_LEN(8) | SPMODE_PM(0x8)); 312*f88c431bSChristophe Leroy out_8(&cp->cp_spim, 0); /* Mask all SPI events */ 313*f88c431bSChristophe Leroy out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */ 314*f88c431bSChristophe Leroy 315*f88c431bSChristophe Leroy /* start spi transfer */ 316*f88c431bSChristophe Leroy setbits_8(&cp->cp_spcom, SPI_STR); /* Start transmit */ 317*f88c431bSChristophe Leroy 318*f88c431bSChristophe Leroy /* -------------------------------- 319*f88c431bSChristophe Leroy * Wait for SPI transmit to get out 320*f88c431bSChristophe Leroy * or time out (1 second = 1000 ms) 321*f88c431bSChristophe Leroy * -------------------------------- */ 322*f88c431bSChristophe Leroy for (tm = 0; tm < 1000; ++tm) { 323*f88c431bSChristophe Leroy if (in_8(&cp->cp_spie) & SPI_TXB) /* Tx Buffer Empty */ 324*f88c431bSChristophe Leroy break; 325*f88c431bSChristophe Leroy if ((in_be16(&tbdf->cbd_sc) & BD_SC_READY) == 0) 326*f88c431bSChristophe Leroy break; 327*f88c431bSChristophe Leroy udelay(1000); 328*f88c431bSChristophe Leroy } 329*f88c431bSChristophe Leroy if (tm >= 1000) 330*f88c431bSChristophe Leroy printf("*** spi_xfer: Time out while xferring to/from SPI!\n"); 331*f88c431bSChristophe Leroy 332*f88c431bSChristophe Leroy /* Clear CS for device */ 333*f88c431bSChristophe Leroy setbits_be32(&cp->cp_pbdat, 0x0001); 334*f88c431bSChristophe Leroy 335*f88c431bSChristophe Leroy return count; 336*f88c431bSChristophe Leroy } 337