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