xref: /OK3568_Linux_fs/u-boot/examples/standalone/rkspi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2022 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <exports.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "rkspi.h"
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun /* Change to 1 to output registers at the start of each transaction */
13*4882a593Smuzhiyun #define DEBUG_RK_SPI	0
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct rockchip_spi_priv {
16*4882a593Smuzhiyun 	struct rockchip_spi *regs;
17*4882a593Smuzhiyun 	unsigned int mode;
18*4882a593Smuzhiyun 	u8 bits_per_word;		/* max 16 bits per word */
19*4882a593Smuzhiyun 	u8 n_bytes;
20*4882a593Smuzhiyun 	unsigned int clock_div;
21*4882a593Smuzhiyun 	uint cr0;
22*4882a593Smuzhiyun 	u32 rsd;			/* Rx sample delay cycles */
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define RK_SPI_BUS_MAX 5
26*4882a593Smuzhiyun static struct rockchip_spi_priv spi_bus[RK_SPI_BUS_MAX];
27*4882a593Smuzhiyun 
get_spi_bus(u8 bus)28*4882a593Smuzhiyun static inline struct rockchip_spi_priv *get_spi_bus(u8 bus)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun 	return &spi_bus[bus];
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define SPI_FIFO_DEPTH		32
34*4882a593Smuzhiyun #define SPI_CR0_RSD_MAX		0x3
35*4882a593Smuzhiyun 
writel(u32 val,void * addr)36*4882a593Smuzhiyun static inline void writel(u32 val, void *addr)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	*(volatile u32 *)addr = val;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
readl(void * addr)41*4882a593Smuzhiyun static inline u32 readl(void *addr)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	return *(volatile u32 *)addr;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
rkspi_dump_regs(struct rockchip_spi * regs)46*4882a593Smuzhiyun static void rkspi_dump_regs(struct rockchip_spi *regs)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	debug("ctrl0: \t\t0x%08x\n", readl(&regs->ctrlr0));
49*4882a593Smuzhiyun 	debug("ctrl1: \t\t0x%08x\n", readl(&regs->ctrlr1));
50*4882a593Smuzhiyun 	debug("ssienr: \t\t0x%08x\n", readl(&regs->enr));
51*4882a593Smuzhiyun 	debug("ser: \t\t0x%08x\n", readl(&regs->ser));
52*4882a593Smuzhiyun 	debug("baudr: \t\t0x%08x\n", readl(&regs->baudr));
53*4882a593Smuzhiyun 	debug("txftlr: \t\t0x%08x\n", readl(&regs->txftlr));
54*4882a593Smuzhiyun 	debug("rxftlr: \t\t0x%08x\n", readl(&regs->rxftlr));
55*4882a593Smuzhiyun 	debug("txflr: \t\t0x%08x\n", readl(&regs->txflr));
56*4882a593Smuzhiyun 	debug("rxflr: \t\t0x%08x\n", readl(&regs->rxflr));
57*4882a593Smuzhiyun 	debug("sr: \t\t0x%08x\n", readl(&regs->sr));
58*4882a593Smuzhiyun 	debug("imr: \t\t0x%08x\n", readl(&regs->imr));
59*4882a593Smuzhiyun 	debug("isr: \t\t0x%08x\n", readl(&regs->isr));
60*4882a593Smuzhiyun 	debug("dmacr: \t\t0x%08x\n", readl(&regs->dmacr));
61*4882a593Smuzhiyun 	debug("dmatdlr: \t0x%08x\n", readl(&regs->dmatdlr));
62*4882a593Smuzhiyun 	debug("dmardlr: \t0x%08x\n", readl(&regs->dmardlr));
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
rkspi_enable_chip(struct rockchip_spi * regs,bool enable)65*4882a593Smuzhiyun static void rkspi_enable_chip(struct rockchip_spi *regs, bool enable)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	writel(enable ? 1 : 0, &regs->enr);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
rkspi_set_baudr(struct rockchip_spi_priv * priv,uint clk_div)70*4882a593Smuzhiyun static void rkspi_set_baudr(struct rockchip_spi_priv *priv, uint clk_div)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	writel(clk_div, &priv->regs->baudr);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
rkspi_wait_till_not_busy(struct rockchip_spi * regs)75*4882a593Smuzhiyun static int rkspi_wait_till_not_busy(struct rockchip_spi *regs)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	unsigned long start;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	start = get_timer(0);
80*4882a593Smuzhiyun 	while (readl(&regs->sr) & SR_BUSY) {
81*4882a593Smuzhiyun 		if (get_timer(start) > ROCKCHIP_SPI_TIMEOUT_MS) {
82*4882a593Smuzhiyun 			debug("RK SPI: Status keeps busy for 1000us after a read/write!\n");
83*4882a593Smuzhiyun 			return -ETIMEDOUT;
84*4882a593Smuzhiyun 		}
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return 0;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
spi_cs_activate(u8 bus,u8 cs)90*4882a593Smuzhiyun static void spi_cs_activate(u8 bus, u8 cs)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	struct rockchip_spi_priv *priv = get_spi_bus(bus);
93*4882a593Smuzhiyun 	struct rockchip_spi *regs = priv->regs;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	debug("activate cs%u\n", cs);
96*4882a593Smuzhiyun 	writel(1 << cs, &regs->ser);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
spi_cs_deactivate(u8 bus,u8 cs)99*4882a593Smuzhiyun static void spi_cs_deactivate(u8 bus, u8 cs)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	struct rockchip_spi_priv *priv = get_spi_bus(bus);
102*4882a593Smuzhiyun 	struct rockchip_spi *regs = priv->regs;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	debug("deactivate cs%u\n", cs);
105*4882a593Smuzhiyun 	writel(0, &regs->ser);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
rockchip_spi_probe(u8 bus,uintptr_t base_addr,u32 rsd,u32 clock_div,u32 mode)108*4882a593Smuzhiyun int rockchip_spi_probe(u8 bus, uintptr_t base_addr, u32 rsd, u32 clock_div, u32 mode)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	struct rockchip_spi_priv *priv;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	if (bus >= RK_SPI_BUS_MAX) {
113*4882a593Smuzhiyun 		printf("%s bus %d is out of max num(%d)\n", __func__, bus, RK_SPI_BUS_MAX);
114*4882a593Smuzhiyun 		return -1;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	debug("%s: probe\n", __func__);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	priv = &spi_bus[bus];
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	priv->regs = (struct rockchip_spi *)base_addr;
122*4882a593Smuzhiyun 	priv->rsd = rsd;
123*4882a593Smuzhiyun 	priv->mode = mode;
124*4882a593Smuzhiyun 	if (clock_div % 2 || clock_div < 2) {
125*4882a593Smuzhiyun 		printf("%s div should be even num, and at least 2\n", __func__);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 		return -1;
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 	priv->clock_div = clock_div;
130*4882a593Smuzhiyun 	priv->bits_per_word = 8;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
rockchip_spi_claim_bus(u8 bus)135*4882a593Smuzhiyun int rockchip_spi_claim_bus(u8 bus)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	struct rockchip_spi_priv *priv = get_spi_bus(bus);
138*4882a593Smuzhiyun 	struct rockchip_spi *regs = priv->regs;
139*4882a593Smuzhiyun 	u8 spi_dfs, spi_tf;
140*4882a593Smuzhiyun 	uint ctrlr0;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	/* Disable the SPI hardware */
143*4882a593Smuzhiyun 	rkspi_enable_chip(regs, 0);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	switch (priv->bits_per_word) {
146*4882a593Smuzhiyun 	case 8:
147*4882a593Smuzhiyun 		priv->n_bytes = 1;
148*4882a593Smuzhiyun 		spi_dfs = DFS_8BIT;
149*4882a593Smuzhiyun 		spi_tf = HALF_WORD_OFF;
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 	case 16:
152*4882a593Smuzhiyun 		priv->n_bytes = 2;
153*4882a593Smuzhiyun 		spi_dfs = DFS_16BIT;
154*4882a593Smuzhiyun 		spi_tf = HALF_WORD_ON;
155*4882a593Smuzhiyun 		break;
156*4882a593Smuzhiyun 	default:
157*4882a593Smuzhiyun 		debug("%s: unsupported bits: %dbits\n", __func__,
158*4882a593Smuzhiyun 		      priv->bits_per_word);
159*4882a593Smuzhiyun 		return -EPROTONOSUPPORT;
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	rkspi_set_baudr(priv, priv->clock_div);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/* Operation Mode */
165*4882a593Smuzhiyun 	ctrlr0 = OMOD_MASTER << OMOD_SHIFT;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* Data Frame Size */
168*4882a593Smuzhiyun 	ctrlr0 |= spi_dfs << DFS_SHIFT;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* set SPI mode 0..3 */
171*4882a593Smuzhiyun 	if (priv->mode & SPI_CPOL)
172*4882a593Smuzhiyun 		ctrlr0 |= SCOL_HIGH << SCOL_SHIFT;
173*4882a593Smuzhiyun 	if (priv->mode & SPI_CPHA)
174*4882a593Smuzhiyun 		ctrlr0 |= SCPH_TOGSTA << SCPH_SHIFT;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/* Chip Select Mode */
177*4882a593Smuzhiyun 	ctrlr0 |= CSM_KEEP << CSM_SHIFT;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* SSN to Sclk_out delay */
180*4882a593Smuzhiyun 	ctrlr0 |= SSN_DELAY_ONE << SSN_DELAY_SHIFT;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	/* Serial Endian Mode */
183*4882a593Smuzhiyun 	ctrlr0 |= SEM_LITTLE << SEM_SHIFT;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* First Bit Mode */
186*4882a593Smuzhiyun 	ctrlr0 |= FBM_MSB << FBM_SHIFT;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* Byte and Halfword Transform */
189*4882a593Smuzhiyun 	ctrlr0 |= spi_tf << HALF_WORD_TX_SHIFT;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* Rxd Sample Delay */
192*4882a593Smuzhiyun 	ctrlr0 |= priv->rsd << RXDSD_SHIFT;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* Frame Format */
195*4882a593Smuzhiyun 	ctrlr0 |= FRF_SPI << FRF_SHIFT;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* Save static configuration */
198*4882a593Smuzhiyun 	priv->cr0 = ctrlr0;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	writel(ctrlr0, &regs->ctrlr0);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	return 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
rockchip_spi_config(struct rockchip_spi_priv * priv,const void * dout)205*4882a593Smuzhiyun int rockchip_spi_config(struct rockchip_spi_priv *priv, const void *dout)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	struct rockchip_spi *regs = priv->regs;
208*4882a593Smuzhiyun 	uint ctrlr0 = priv->cr0;
209*4882a593Smuzhiyun 	u32 tmod;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	if (dout)
212*4882a593Smuzhiyun 		tmod = TMOD_TR;
213*4882a593Smuzhiyun 	else
214*4882a593Smuzhiyun 		tmod = TMOD_RO;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	ctrlr0 |= (tmod & TMOD_MASK) << TMOD_SHIFT;
217*4882a593Smuzhiyun 	writel(ctrlr0, &regs->ctrlr0);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
rockchip_spi_release_bus(u8 bus)222*4882a593Smuzhiyun void rockchip_spi_release_bus(u8 bus)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct rockchip_spi_priv *priv = get_spi_bus(bus);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	rkspi_enable_chip(priv->regs, false);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
rockchip_spi_xfer(u8 bus,u8 cs,unsigned int bitlen,const void * dout,void * din,unsigned long flags)229*4882a593Smuzhiyun int rockchip_spi_xfer(u8 bus, u8 cs, unsigned int bitlen, const void *dout, void *din, unsigned long flags)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	struct rockchip_spi_priv *priv = get_spi_bus(bus);
232*4882a593Smuzhiyun 	struct rockchip_spi *regs = priv->regs;
233*4882a593Smuzhiyun 	int len = bitlen >> 3;
234*4882a593Smuzhiyun 	const u8 *out = dout;
235*4882a593Smuzhiyun 	u8 *in = din;
236*4882a593Smuzhiyun 	int toread, towrite;
237*4882a593Smuzhiyun 	int ret;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	rockchip_spi_config(priv, dout);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	debug("%s: dout=%p, din=%p, len=%x, flags=%lx\n", __func__, dout, din,
242*4882a593Smuzhiyun 	      len, flags);
243*4882a593Smuzhiyun 	if (DEBUG_RK_SPI)
244*4882a593Smuzhiyun 		rkspi_dump_regs(regs);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	/* Assert CS before transfer */
247*4882a593Smuzhiyun 	if (flags & SPI_XFER_BEGIN)
248*4882a593Smuzhiyun 		spi_cs_activate(bus, cs);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	while (len > 0) {
251*4882a593Smuzhiyun 		int todo = min(len, 0xffff);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 		rkspi_enable_chip(regs, false);
254*4882a593Smuzhiyun 		writel(todo - 1, &regs->ctrlr1);
255*4882a593Smuzhiyun 		rkspi_enable_chip(regs, true);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 		toread = todo;
258*4882a593Smuzhiyun 		towrite = todo;
259*4882a593Smuzhiyun 		while (toread || towrite) {
260*4882a593Smuzhiyun 			u32 status = readl(&regs->sr);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 			if (towrite && !(status & SR_TF_FULL)) {
263*4882a593Smuzhiyun 				if (out)
264*4882a593Smuzhiyun 					writel(out ? *out++ : 0, regs->txdr);
265*4882a593Smuzhiyun 				towrite--;
266*4882a593Smuzhiyun 			}
267*4882a593Smuzhiyun 			if (toread && !(status & SR_RF_EMPT)) {
268*4882a593Smuzhiyun 				u32 byte = readl(regs->rxdr);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 				if (in)
271*4882a593Smuzhiyun 					*in++ = byte;
272*4882a593Smuzhiyun 				toread--;
273*4882a593Smuzhiyun 			}
274*4882a593Smuzhiyun 		}
275*4882a593Smuzhiyun 		ret = rkspi_wait_till_not_busy(regs);
276*4882a593Smuzhiyun 		if (ret)
277*4882a593Smuzhiyun 			break;
278*4882a593Smuzhiyun 		len -= todo;
279*4882a593Smuzhiyun 	}
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	/* Deassert CS after transfer */
282*4882a593Smuzhiyun 	if (flags & SPI_XFER_END)
283*4882a593Smuzhiyun 		spi_cs_deactivate(bus, cs);
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	rkspi_enable_chip(regs, false);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	return ret;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun 
rockchip_spi_write_then_read(u8 bus,u8 cs,const u8 * opcode,size_t n_opcode,const u8 * txbuf,u8 * rxbuf,size_t n_buf)290*4882a593Smuzhiyun int rockchip_spi_write_then_read(u8 bus, u8 cs, const u8 *opcode,
291*4882a593Smuzhiyun 				 size_t n_opcode, const u8 *txbuf, u8 *rxbuf,
292*4882a593Smuzhiyun 			size_t n_buf)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun 	unsigned long flags = SPI_XFER_BEGIN;
295*4882a593Smuzhiyun 	int ret;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	if (n_buf == 0)
298*4882a593Smuzhiyun 		flags |= SPI_XFER_END;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	ret = rockchip_spi_xfer(bus, cs, n_opcode * 8, opcode, NULL, flags);
301*4882a593Smuzhiyun 	if (ret) {
302*4882a593Smuzhiyun 		debug("spi: failed to send command (%zu bytes): %d\n",
303*4882a593Smuzhiyun 		      n_opcode, ret);
304*4882a593Smuzhiyun 	} else if (n_buf != 0) {
305*4882a593Smuzhiyun 		ret = rockchip_spi_xfer(bus, cs, n_buf * 8, txbuf, rxbuf, SPI_XFER_END);
306*4882a593Smuzhiyun 		if (ret)
307*4882a593Smuzhiyun 			debug("spi: failed to transfer %zu bytes of data: %d\n",
308*4882a593Smuzhiyun 			      n_buf, ret);
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	return ret;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
dbg_print_hex(char * s,void * buf,u32 width,u32 len)314*4882a593Smuzhiyun void dbg_print_hex(char *s, void *buf, u32 width, u32 len)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	u32 i, j;
317*4882a593Smuzhiyun 	unsigned char *p8 = (unsigned char *)buf;
318*4882a593Smuzhiyun 	unsigned short *p16 = (unsigned short *)buf;
319*4882a593Smuzhiyun 	u32 *p32 = (u32 *)buf;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	j = 0;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
324*4882a593Smuzhiyun 		if (j == 0)
325*4882a593Smuzhiyun 			printf("%s %p + 0x%x:", s, buf, i * width);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		if (width == 4)
328*4882a593Smuzhiyun 			printf("0x%08x,", p32[i]);
329*4882a593Smuzhiyun 		else if (width == 2)
330*4882a593Smuzhiyun 			printf("0x%04x,", p16[i]);
331*4882a593Smuzhiyun 		else
332*4882a593Smuzhiyun 			printf("0x%02x,", p8[i]);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 		if (++j >= (16 / width)) {
335*4882a593Smuzhiyun 			j = 0;
336*4882a593Smuzhiyun 			printf("\n");
337*4882a593Smuzhiyun 		}
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	printf("\n");
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
spi_hw_init(void)343*4882a593Smuzhiyun static void spi_hw_init(void)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	/* Setting the clock and iomux */
346*4882a593Smuzhiyun 	/* todo */
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
main(int argc,char * const argv[])349*4882a593Smuzhiyun int main(int argc, char * const argv[])
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	int i;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	/* Print the ABI version */
354*4882a593Smuzhiyun 	app_startup(argv);
355*4882a593Smuzhiyun 	printf("Example expects ABI version %d\n", XF_VERSION);
356*4882a593Smuzhiyun 	printf("Actual U-Boot ABI version %d\n", (int)get_version());
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	printf("rk_spi standalone version\n");
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	printf("argc = %d\n", argc);
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	for (i = 0; i <= argc; ++i) {
363*4882a593Smuzhiyun 		printf("argv[%d] = \"%s\"\n",
364*4882a593Smuzhiyun 		       i,
365*4882a593Smuzhiyun 			argv[i] ? argv[i] : "<NULL>");
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	/*
369*4882a593Smuzhiyun 	 * spi test demo
370*4882a593Smuzhiyun 	 */
371*4882a593Smuzhiyun #if 1
372*4882a593Smuzhiyun 	u8 bus, cs;
373*4882a593Smuzhiyun 	unsigned char *pread, *pwrite;
374*4882a593Smuzhiyun 	u32 test_size = 0x100;
375*4882a593Smuzhiyun 	int ret;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	pread = malloc(test_size);
378*4882a593Smuzhiyun 	if (!pread)
379*4882a593Smuzhiyun 		printf("%s pread malloc fail\n", __func__);
380*4882a593Smuzhiyun 	pwrite = malloc(test_size);
381*4882a593Smuzhiyun 	if (!pwrite) {
382*4882a593Smuzhiyun 		printf("%s pwrite malloc fail\n", __func__);
383*4882a593Smuzhiyun 		free(pwrite);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 		return -1;
386*4882a593Smuzhiyun 	}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	for (i = 0; i < test_size; i++)
389*4882a593Smuzhiyun 		pwrite[i] = i;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	bus = 4;
392*4882a593Smuzhiyun 	cs = 0;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	spi_hw_init();
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	rockchip_spi_probe(bus, 0xfecb0000, 0, 20, SPI_MODE_3);
397*4882a593Smuzhiyun 	rockchip_spi_claim_bus(bus);
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	/*
400*4882a593Smuzhiyun 	 * SPI write
401*4882a593Smuzhiyun 	 */
402*4882a593Smuzhiyun 	ret = rockchip_spi_xfer(bus, cs, test_size * 8, pwrite, NULL, SPI_XFER_ONCE);
403*4882a593Smuzhiyun 	if (ret) {
404*4882a593Smuzhiyun 		printf("rockchip_spi_xfer fail ret=%d\n", ret);
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 		return ret;
407*4882a593Smuzhiyun 	}
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	/*
410*4882a593Smuzhiyun 	 * SPI read
411*4882a593Smuzhiyun 	 */
412*4882a593Smuzhiyun 	rockchip_spi_xfer(bus, cs, test_size * 8, NULL, pread, SPI_XFER_ONCE);
413*4882a593Smuzhiyun 	if (ret) {
414*4882a593Smuzhiyun 		printf("rockchip_spi_xfer fail ret=%d\n", ret);
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 		return ret;
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun 	dbg_print_hex("spi_read:", pread, 4, test_size / 4);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	/*
421*4882a593Smuzhiyun 	 * SPI duplex
422*4882a593Smuzhiyun 	 */
423*4882a593Smuzhiyun 	rockchip_spi_xfer(bus, cs, test_size * 8, pwrite, pread, SPI_XFER_ONCE);
424*4882a593Smuzhiyun 	if (ret) {
425*4882a593Smuzhiyun 		printf("rockchip_spi_xfer fail ret=%d\n", ret);
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 		return ret;
428*4882a593Smuzhiyun 	}
429*4882a593Smuzhiyun 	dbg_print_hex("spi_duplex:", pread, 4, test_size / 4);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	/*
432*4882a593Smuzhiyun 	 * SPI write then read
433*4882a593Smuzhiyun 	 */
434*4882a593Smuzhiyun 	rockchip_spi_write_then_read(bus, cs, pwrite, 1, NULL, pread, test_size);
435*4882a593Smuzhiyun 	if (ret) {
436*4882a593Smuzhiyun 		printf("rockchip_spi_xfer fail ret=%d\n", ret);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 		return ret;
439*4882a593Smuzhiyun 	}
440*4882a593Smuzhiyun 	dbg_print_hex("spi_write_then_read:", pread, 4, test_size / 4);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	rockchip_spi_release_bus(bus);
443*4882a593Smuzhiyun #endif
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	printf("Hit any key to exit ... ");
446*4882a593Smuzhiyun 	while (!tstc())
447*4882a593Smuzhiyun 		;
448*4882a593Smuzhiyun 	/* consume input */
449*4882a593Smuzhiyun 	(void)getc();
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	printf("\n\n");
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	return 0;
454*4882a593Smuzhiyun }
455