xref: /optee_os/core/drivers/pl022_spi.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2016, Linaro Limited
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #include <assert.h>
31 #include <drivers/pl022_spi.h>
32 #include <initcall.h>
33 #include <io.h>
34 #include <kernel/panic.h>
35 #include <kernel/tee_time.h>
36 #include <platform_config.h>
37 #include <trace.h>
38 #include <util.h>
39 
40 /* SPI register offsets */
41 #define SSPCR0		0x000
42 #define SSPCR1		0x004
43 #define SSPDR		0x008
44 #define SSPSR		0x00C
45 #define SSPCPSR		0x010
46 #define SSPIMSC		0x014
47 #define SSPRIS		0x018
48 #define SSPMIS		0x01C
49 #define SSPICR		0x020
50 #define SSPDMACR	0x024
51 
52 #ifdef PLATFORM_hikey
53 /* HiKey extensions */
54 #define SSPTXFIFOCR	0x028
55 #define SSPRXFIFOCR	0x02C
56 #define SSPB2BTRANS	0x030
57 #endif
58 
59 /* test registers */
60 #define SSPTCR		0x080
61 #define SSPITIP		0x084
62 #define SSPITOP		0x088
63 #define SSPTDR		0x08C
64 
65 #define SSPPeriphID0	0xFE0
66 #define SSPPeriphID1	0xFE4
67 #define SSPPeriphID2	0xFE8
68 #define SSPPeriphID3	0xFEC
69 
70 #define SSPPCellID0	0xFF0
71 #define SSPPCellID1	0xFF4
72 #define SSPPCellID2	0xFF8
73 #define SSPPCellID3	0xFFC
74 
75 /* SPI register masks */
76 #define SSPCR0_SCR		SHIFT_U32(0xFF, 8)
77 #define SSPCR0_SPH		SHIFT_U32(1, 7)
78 #define SSPCR0_SPH1		SHIFT_U32(1, 7)
79 #define SSPCR0_SPH0		SHIFT_U32(0, 7)
80 #define SSPCR0_SPO		SHIFT_U32(1, 6)
81 #define SSPCR0_SPO1		SHIFT_U32(1, 6)
82 #define SSPCR0_SPO0		SHIFT_U32(0, 6)
83 #define SSPCR0_FRF		SHIFT_U32(3, 4)
84 #define SSPCR0_FRF_SPI		SHIFT_U32(0, 4)
85 #define SSPCR0_DSS		SHIFT_U32(0xFF, 0)
86 #define SSPCR0_DSS_16BIT	SHIFT_U32(0xF, 0)
87 #define SSPCR0_DSS_8BIT		SHIFT_U32(7, 0)
88 
89 #define SSPCR1_SOD		SHIFT_U32(1, 3)
90 #define SSPCR1_SOD_ENABLE	SHIFT_U32(1, 3)
91 #define SSPCR1_SOD_DISABLE	SHIFT_U32(0, 3)
92 #define SSPCR1_MS		SHIFT_U32(1, 2)
93 #define SSPCR1_MS_SLAVE		SHIFT_U32(1, 2)
94 #define SSPCR1_MS_MASTER	SHIFT_U32(0, 2)
95 #define SSPCR1_SSE		SHIFT_U32(1, 1)
96 #define SSPCR1_SSE_ENABLE	SHIFT_U32(1, 1)
97 #define SSPCR1_SSE_DISABLE	SHIFT_U32(0, 1)
98 #define SSPCR1_LBM		SHIFT_U32(1, 0)
99 #define SSPCR1_LBM_YES		SHIFT_U32(1, 0)
100 #define SSPCR1_LBM_NO		SHIFT_U32(0, 0)
101 
102 #define SSPDR_DATA	SHIFT_U32(0xFFFF, 0)
103 
104 #define SSPSR_BSY	SHIFT_U32(1, 4)
105 #define SSPSR_RNF	SHIFT_U32(1, 3)
106 #define SSPSR_RNE	SHIFT_U32(1, 2)
107 #define SSPSR_TNF	SHIFT_U32(1, 1)
108 #define SSPSR_TFE	SHIFT_U32(1, 0)
109 
110 #define SSPCPSR_CPSDVR	SHIFT_U32(0xFF, 0)
111 
112 #define SSPIMSC_TXIM	SHIFT_U32(1, 3)
113 #define SSPIMSC_RXIM	SHIFT_U32(1, 2)
114 #define SSPIMSC_RTIM	SHIFT_U32(1, 1)
115 #define SSPIMSC_RORIM	SHIFT_U32(1, 0)
116 
117 #define SSPRIS_TXRIS	SHIFT_U32(1, 3)
118 #define SSPRIS_RXRIS	SHIFT_U32(1, 2)
119 #define SSPRIS_RTRIS	SHIFT_U32(1, 1)
120 #define SSPRIS_RORRIS	SHIFT_U32(1, 0)
121 
122 #define SSPMIS_TXMIS	SHIFT_U32(1, 3)
123 #define SSPMIS_RXMIS	SHIFT_U32(1, 2)
124 #define SSPMIS_RTMIS	SHIFT_U32(1, 1)
125 #define SSPMIS_RORMIS	SHIFT_U32(1, 0)
126 
127 #define SSPICR_RTIC		SHIFT_U32(1, 1)
128 #define SSPICR_RORIC		SHIFT_U32(1, 0)
129 
130 #define SSPDMACR_TXDMAE	SHIFT_U32(1, 1)
131 #define SSPDMACR_RXDMAE	SHIFT_U32(1, 0)
132 
133 #define SSPPeriphID0_PartNumber0	SHIFT_U32(0xFF, 0) /* 0x22 */
134 #define SSPPeriphID1_Designer0		SHIFT_U32(0xF, 4) /* 0x1 */
135 #define SSPPeriphID1_PartNumber1	SHIFT_U32(0xF, 0) /* 0x0 */
136 #define SSPPeriphID2_Revision		SHIFT_U32(0xF, 4)
137 #define SSPPeriphID2_Designer1		SHIFT_U32(0xF, 0) /* 0x4 */
138 #define SSPPeriphID3_Configuration	SHIFT_U32(0xFF, 0) /* 0x00 */
139 
140 #define SSPPCellID_0	SHIFT_U32(0xFF, 0) /* 0x0D */
141 #define SSPPCellID_1	SHIFT_U32(0xFF, 0) /* 0xF0 */
142 #define SSPPPCellID_2	SHIFT_U32(0xFF, 0) /* 0x05 */
143 #define SSPPPCellID_3	SHIFT_U32(0xFF, 0) /* 0xB1 */
144 
145 #define MASK_32 0xFFFFFFFF
146 #define MASK_28 0xFFFFFFF
147 #define MASK_24 0xFFFFFF
148 #define MASK_20 0xFFFFF
149 #define MASK_16 0xFFFF
150 #define MASK_12 0xFFF
151 #define MASK_8 0xFF
152 #define MASK_4 0xF
153 /* SPI register masks */
154 
155 #define SSP_CPSDVR_MAX		254
156 #define SSP_CPSDVR_MIN		2
157 #define SSP_SCR_MAX		255
158 #define SSP_SCR_MIN		0
159 #define SSP_DATASIZE_MAX	16
160 
161 static enum spi_result pl022_txrx8(struct spi_chip *chip, uint8_t *wdat,
162 	uint8_t *rdat, size_t num_pkts)
163 {
164 	size_t i = 0;
165 	size_t j = 0;
166 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
167 
168 
169 	if (pd->data_size_bits != 8) {
170 		EMSG("data_size_bits should be 8, not %u",
171 			pd->data_size_bits);
172 		return SPI_ERR_CFG;
173 	}
174 
175 	if (wdat)
176 		while (i < num_pkts) {
177 			if (read8(pd->base + SSPSR) & SSPSR_TNF) {
178 				/* tx 1 packet */
179 				write8(wdat[i++], pd->base + SSPDR);
180 			}
181 
182 			if (rdat)
183 				if (read8(pd->base + SSPSR) & SSPSR_RNE) {
184 					/* rx 1 packet */
185 					rdat[j++] = read8(pd->base + SSPDR);
186 				}
187 		}
188 
189 	/* Capture remaining rdat not read above */
190 	if (rdat) {
191 		while ((j < num_pkts) &&
192 			(read8(pd->base + SSPSR) & SSPSR_BSY))
193 			if (read8(pd->base + SSPSR) & SSPSR_RNE) {
194 				/* rx 1 packet */
195 				rdat[j++] = read8(pd->base + SSPDR);
196 			}
197 
198 		if (j < num_pkts) {
199 			EMSG("Packets requested %zu, received %zu",
200 				num_pkts, j);
201 			return SPI_ERR_PKTCNT;
202 		}
203 	}
204 
205 	return SPI_OK;
206 }
207 
208 static enum spi_result pl022_txrx16(struct spi_chip *chip, uint16_t *wdat,
209 	uint16_t *rdat, size_t num_pkts)
210 {
211 	size_t i = 0;
212 	size_t j = 0;
213 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
214 
215 	if (pd->data_size_bits != 16) {
216 		EMSG("data_size_bits should be 16, not %u",
217 			pd->data_size_bits);
218 		return SPI_ERR_CFG;
219 	}
220 
221 	if (wdat)
222 		while (i < num_pkts) {
223 			if (read8(pd->base + SSPSR) & SSPSR_TNF) {
224 				/* tx 1 packet */
225 				write16(wdat[i++], pd->base + SSPDR);
226 			}
227 
228 			if (rdat)
229 				if (read8(pd->base + SSPSR) & SSPSR_RNE) {
230 					/* rx 1 packet */
231 					rdat[j++] = read16(pd->base + SSPDR);
232 				}
233 		}
234 
235 	/* Capture remaining rdat not read above */
236 	if (rdat) {
237 		while ((j < num_pkts) &&
238 			(read8(pd->base + SSPSR) & SSPSR_BSY))
239 			if (read8(pd->base + SSPSR) & SSPSR_RNE) {
240 				/* rx 1 packet */
241 				rdat[j++] = read16(pd->base + SSPDR);
242 			}
243 
244 		if (j < num_pkts) {
245 			EMSG("Packets requested %zu, received %zu",
246 				num_pkts, j);
247 			return SPI_ERR_PKTCNT;
248 		}
249 	}
250 
251 	return SPI_OK;
252 }
253 
254 static void pl022_print_peri_id(struct pl022_data *pd __maybe_unused)
255 {
256 	DMSG("Expected: 0x 22 10 ?4 00");
257 	DMSG("Read: 0x %02x %02x %02x %02x",
258 		read32(pd->base + SSPPeriphID0),
259 		read32(pd->base + SSPPeriphID1),
260 		read32(pd->base + SSPPeriphID2),
261 		read32(pd->base + SSPPeriphID3));
262 }
263 
264 static void pl022_print_cell_id(struct pl022_data *pd __maybe_unused)
265 {
266 	DMSG("Expected: 0x 0d f0 05 b1");
267 	DMSG("Read: 0x %02x %02x %02x %02x",
268 		read32(pd->base + SSPPCellID0),
269 		read32(pd->base + SSPPCellID1),
270 		read32(pd->base + SSPPCellID2),
271 		read32(pd->base + SSPPCellID3));
272 }
273 
274 static void pl022_sanity_check(struct pl022_data *pd)
275 {
276 	assert(pd);
277 	assert(pd->chip.ops);
278 	assert(pd->cs_control <= PL022_CS_CTRL_MANUAL);
279 	switch (pd->cs_control) {
280 	case PL022_CS_CTRL_AUTO_GPIO:
281 		assert(pd->cs_data.gpio_data.chip);
282 		assert(pd->cs_data.gpio_data.chip->ops);
283 		break;
284 	case PL022_CS_CTRL_CB:
285 		assert(pd->cs_data.cs_cb);
286 		break;
287 	default:
288 		break;
289 	}
290 	assert(pd->clk_hz);
291 	assert(pd->speed_hz && pd->speed_hz <= pd->clk_hz/2);
292 	assert(pd->mode <= SPI_MODE3);
293 	assert(pd->data_size_bits == 8 || pd->data_size_bits == 16);
294 
295 	#ifdef PLATFORM_hikey
296 	DMSG("SSPB2BTRANS: Expected: 0x2. Read: 0x%x",
297 		read32(pd->base + SSPB2BTRANS));
298 	#endif
299 	pl022_print_peri_id(pd);
300 	pl022_print_cell_id(pd);
301 }
302 
303 static inline uint32_t pl022_calc_freq(struct pl022_data *pd,
304 	uint8_t cpsdvr, uint8_t scr)
305 {
306 	return pd->clk_hz / (cpsdvr * (1 + scr));
307 }
308 
309 static void pl022_control_cs(struct spi_chip *chip, enum gpio_level value)
310 {
311 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
312 
313 	switch (pd->cs_control) {
314 	case PL022_CS_CTRL_AUTO_GPIO:
315 		if (read8(pd->base + SSPSR) & SSPSR_BSY)
316 			DMSG("pl022 busy - do NOT set CS!");
317 		while (read8(pd->base + SSPSR) & SSPSR_BSY)
318 			;
319 		DMSG("pl022 done - set CS!");
320 
321 		pd->cs_data.gpio_data.chip->ops->set_value(
322 			pd->cs_data.gpio_data.pin_num, value);
323 		break;
324 	case PL022_CS_CTRL_CB:
325 		pd->cs_data.cs_cb(value);
326 		break;
327 	default:
328 		break;
329 	}
330 }
331 
332 static void pl022_calc_clk_divisors(struct pl022_data *pd,
333 	uint8_t *cpsdvr, uint8_t *scr)
334 {
335 	unsigned int freq1 = 0;
336 	unsigned int freq2 = 0;
337 	uint8_t tmp_cpsdvr1;
338 	uint8_t tmp_scr1;
339 	uint8_t tmp_cpsdvr2 = 0;
340 	uint8_t tmp_scr2 = 0;
341 
342 	for (tmp_scr1 = SSP_SCR_MIN; tmp_scr1 < SSP_SCR_MAX; tmp_scr1++) {
343 		for (tmp_cpsdvr1 = SSP_CPSDVR_MIN; tmp_cpsdvr1 < SSP_CPSDVR_MAX;
344 			tmp_cpsdvr1++) {
345 			freq1 = pl022_calc_freq(pd, tmp_cpsdvr1, tmp_scr1);
346 			if (freq1 == pd->speed_hz)
347 				goto done;
348 			else if (freq1 < pd->speed_hz)
349 				goto stage2;
350 		}
351 	}
352 
353 stage2:
354 	for (tmp_cpsdvr2 = SSP_CPSDVR_MIN; tmp_cpsdvr2 < SSP_CPSDVR_MAX;
355 		tmp_cpsdvr2++) {
356 		for (tmp_scr2 = SSP_SCR_MIN; tmp_scr2 < SSP_SCR_MAX;
357 			tmp_scr2++) {
358 			freq2 = pl022_calc_freq(pd, tmp_cpsdvr2, tmp_scr2);
359 			if (freq2 <= pd->speed_hz)
360 				goto done;
361 		}
362 	}
363 
364 done:
365 	if (freq1 >= freq2) {
366 		*cpsdvr = tmp_cpsdvr1;
367 		*scr = tmp_scr1;
368 		DMSG("speed: requested: %u, closest1: %u",
369 			pd->speed_hz, freq1);
370 	} else {
371 		*cpsdvr = tmp_cpsdvr2;
372 		*scr = tmp_scr2;
373 		DMSG("speed: requested: %u, closest2: %u",
374 			pd->speed_hz, freq2);
375 	}
376 	DMSG("CPSDVR: %u (0x%x), SCR: %u (0x%x)",
377 		*cpsdvr, *cpsdvr, *scr, *scr);
378 }
379 
380 static void pl022_flush_fifo(struct pl022_data *pd)
381 {
382 	uint32_t __maybe_unused rdat;
383 
384 	do {
385 		while (read32(pd->base + SSPSR) & SSPSR_RNE) {
386 			rdat = read32(pd->base + SSPDR);
387 			DMSG("rdat: 0x%x", rdat);
388 		}
389 	} while (read32(pd->base + SSPSR) & SSPSR_BSY);
390 }
391 
392 static void pl022_configure(struct spi_chip *chip)
393 {
394 	uint16_t mode;
395 	uint16_t data_size;
396 	uint8_t cpsdvr;
397 	uint8_t scr;
398 	uint8_t lbm;
399 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
400 
401 	pl022_sanity_check(pd);
402 
403 	switch (pd->cs_control) {
404 	case PL022_CS_CTRL_AUTO_GPIO:
405 		DMSG("Use auto GPIO CS control");
406 		DMSG("Mask/disable interrupt for CS GPIO");
407 		pd->cs_data.gpio_data.chip->ops->set_interrupt(
408 			pd->cs_data.gpio_data.pin_num,
409 			GPIO_INTERRUPT_DISABLE);
410 		DMSG("Set CS GPIO dir to out");
411 		pd->cs_data.gpio_data.chip->ops->set_direction(
412 			pd->cs_data.gpio_data.pin_num,
413 			GPIO_DIR_OUT);
414 		break;
415 	case PL022_CS_CTRL_CB:
416 		DMSG("Use registered CS callback");
417 		break;
418 	case PL022_CS_CTRL_MANUAL:
419 		DMSG("Use manual CS control");
420 		break;
421 	default:
422 		EMSG("Invalid CS control type: %d", pd->cs_control);
423 		panic();
424 	}
425 
426 	DMSG("Pull CS high");
427 	pl022_control_cs(chip, GPIO_LEVEL_HIGH);
428 
429 	pl022_calc_clk_divisors(pd, &cpsdvr, &scr);
430 
431 	/* configure ssp based on platform settings */
432 	switch (pd->mode) {
433 	case SPI_MODE0:
434 		DMSG("SPI mode 0");
435 		mode = SSPCR0_SPO0 | SSPCR0_SPH0;
436 		break;
437 	case SPI_MODE1:
438 		DMSG("SPI mode 1");
439 		mode = SSPCR0_SPO0 | SSPCR0_SPH1;
440 		break;
441 	case SPI_MODE2:
442 		DMSG("SPI mode 2");
443 		mode = SSPCR0_SPO1 | SSPCR0_SPH0;
444 		break;
445 	case SPI_MODE3:
446 		DMSG("SPI mode 3");
447 		mode = SSPCR0_SPO1 | SSPCR0_SPH1;
448 		break;
449 	default:
450 		EMSG("Invalid SPI mode: %u", pd->mode);
451 		panic();
452 	}
453 
454 	switch (pd->data_size_bits) {
455 	case 8:
456 		DMSG("Data size: 8");
457 		data_size = SSPCR0_DSS_8BIT;
458 		break;
459 	case 16:
460 		DMSG("Data size: 16");
461 		data_size = SSPCR0_DSS_16BIT;
462 		break;
463 	default:
464 		EMSG("Unsupported data size: %u bits", pd->data_size_bits);
465 		panic();
466 	}
467 
468 	if (pd->loopback) {
469 		DMSG("Starting in loopback mode!");
470 		lbm = SSPCR1_LBM_YES;
471 	} else {
472 		DMSG("Starting in regular (non-loopback) mode!");
473 		lbm = SSPCR1_LBM_NO;
474 	}
475 
476 	DMSG("Set Serial Clock Rate (SCR), SPI mode (phase and clock)");
477 	DMSG("Set frame format (SPI) and data size (8- or 16-bit)");
478 	io_mask16(pd->base + SSPCR0, SHIFT_U32(scr, 8) | mode | SSPCR0_FRF_SPI |
479 		data_size, MASK_16);
480 
481 	DMSG("Set master mode, disable SSP, set loopback mode");
482 	io_mask8(pd->base + SSPCR1, SSPCR1_SOD_DISABLE | SSPCR1_MS_MASTER |
483 		SSPCR1_SSE_DISABLE | lbm, MASK_4);
484 
485 	DMSG("Set clock prescale");
486 	io_mask8(pd->base + SSPCPSR, cpsdvr, SSPCPSR_CPSDVR);
487 
488 	DMSG("Disable interrupts");
489 	io_mask8(pd->base + SSPIMSC, 0, MASK_4);
490 
491 	DMSG("Clear interrupts");
492 	io_mask8(pd->base + SSPICR, SSPICR_RORIC | SSPICR_RTIC,
493 		SSPICR_RORIC | SSPICR_RTIC);
494 
495 	DMSG("Empty FIFO before starting");
496 	pl022_flush_fifo(pd);
497 }
498 
499 static void pl022_start(struct spi_chip *chip)
500 {
501 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
502 
503 	DMSG("Enable SSP");
504 	io_mask8(pd->base + SSPCR1, SSPCR1_SSE_ENABLE, SSPCR1_SSE);
505 
506 	pl022_control_cs(chip, GPIO_LEVEL_LOW);
507 }
508 
509 static void pl022_end(struct spi_chip *chip)
510 {
511 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
512 
513 	pl022_control_cs(chip, GPIO_LEVEL_HIGH);
514 
515 	DMSG("Disable SSP");
516 	io_mask8(pd->base + SSPCR1, SSPCR1_SSE_DISABLE, SSPCR1_SSE);
517 }
518 
519 static const struct spi_ops pl022_ops = {
520 	.configure = pl022_configure,
521 	.start = pl022_start,
522 	.txrx8 = pl022_txrx8,
523 	.txrx16 = pl022_txrx16,
524 	.end = pl022_end,
525 };
526 
527 void pl022_init(struct pl022_data *pd)
528 {
529 	assert(pd);
530 	pd->chip.ops = &pl022_ops;
531 }
532