xref: /openbmc/u-boot/drivers/spi/mpc8xx_spi.c (revision f88c431b8a264872e9391e039541792a13a5076a)
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