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(®s->ctrlr0));
49*4882a593Smuzhiyun debug("ctrl1: \t\t0x%08x\n", readl(®s->ctrlr1));
50*4882a593Smuzhiyun debug("ssienr: \t\t0x%08x\n", readl(®s->enr));
51*4882a593Smuzhiyun debug("ser: \t\t0x%08x\n", readl(®s->ser));
52*4882a593Smuzhiyun debug("baudr: \t\t0x%08x\n", readl(®s->baudr));
53*4882a593Smuzhiyun debug("txftlr: \t\t0x%08x\n", readl(®s->txftlr));
54*4882a593Smuzhiyun debug("rxftlr: \t\t0x%08x\n", readl(®s->rxftlr));
55*4882a593Smuzhiyun debug("txflr: \t\t0x%08x\n", readl(®s->txflr));
56*4882a593Smuzhiyun debug("rxflr: \t\t0x%08x\n", readl(®s->rxflr));
57*4882a593Smuzhiyun debug("sr: \t\t0x%08x\n", readl(®s->sr));
58*4882a593Smuzhiyun debug("imr: \t\t0x%08x\n", readl(®s->imr));
59*4882a593Smuzhiyun debug("isr: \t\t0x%08x\n", readl(®s->isr));
60*4882a593Smuzhiyun debug("dmacr: \t\t0x%08x\n", readl(®s->dmacr));
61*4882a593Smuzhiyun debug("dmatdlr: \t0x%08x\n", readl(®s->dmatdlr));
62*4882a593Smuzhiyun debug("dmardlr: \t0x%08x\n", readl(®s->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, ®s->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(®s->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, ®s->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, ®s->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, ®s->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, ®s->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, ®s->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(®s->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