xref: /OK3568_Linux_fs/u-boot/examples/standalone/rkspi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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(&regs->ctrlr0));
49 	debug("ctrl1: \t\t0x%08x\n", readl(&regs->ctrlr1));
50 	debug("ssienr: \t\t0x%08x\n", readl(&regs->enr));
51 	debug("ser: \t\t0x%08x\n", readl(&regs->ser));
52 	debug("baudr: \t\t0x%08x\n", readl(&regs->baudr));
53 	debug("txftlr: \t\t0x%08x\n", readl(&regs->txftlr));
54 	debug("rxftlr: \t\t0x%08x\n", readl(&regs->rxftlr));
55 	debug("txflr: \t\t0x%08x\n", readl(&regs->txflr));
56 	debug("rxflr: \t\t0x%08x\n", readl(&regs->rxflr));
57 	debug("sr: \t\t0x%08x\n", readl(&regs->sr));
58 	debug("imr: \t\t0x%08x\n", readl(&regs->imr));
59 	debug("isr: \t\t0x%08x\n", readl(&regs->isr));
60 	debug("dmacr: \t\t0x%08x\n", readl(&regs->dmacr));
61 	debug("dmatdlr: \t0x%08x\n", readl(&regs->dmatdlr));
62 	debug("dmardlr: \t0x%08x\n", readl(&regs->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, &regs->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(&regs->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, &regs->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, &regs->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, &regs->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, &regs->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, &regs->ctrlr1);
255 		rkspi_enable_chip(regs, true);
256 
257 		toread = todo;
258 		towrite = todo;
259 		while (toread || towrite) {
260 			u32 status = readl(&regs->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