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