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