xref: /optee_os/core/drivers/pl022_spi.c (revision a50cb361d9e5735f197ccc87beb0d24af8315369)
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 <gpio.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 enum pl022_data_size {
162 	PL022_DATA_SIZE4 = 0x3,
163 	PL022_DATA_SIZE5,
164 	PL022_DATA_SIZE6,
165 	PL022_DATA_SIZE7,
166 	PL022_DATA_SIZE8 = SSPCR0_DSS_8BIT,
167 	PL022_DATA_SIZE9,
168 	PL022_DATA_SIZE10,
169 	PL022_DATA_SIZE11,
170 	PL022_DATA_SIZE12,
171 	PL022_DATA_SIZE13,
172 	PL022_DATA_SIZE14,
173 	PL022_DATA_SIZE15,
174 	PL022_DATA_SIZE16 = SSPCR0_DSS_16BIT
175 };
176 
177 enum pl022_spi_mode {
178 	PL022_SPI_MODE0 = SSPCR0_SPO0 | SSPCR0_SPH0, /* 0x00 */
179 	PL022_SPI_MODE1 = SSPCR0_SPO0 | SSPCR0_SPH1, /* 0x80 */
180 	PL022_SPI_MODE2 = SSPCR0_SPO1 | SSPCR0_SPH0, /* 0x40 */
181 	PL022_SPI_MODE3 = SSPCR0_SPO1 | SSPCR0_SPH1  /* 0xC0 */
182 };
183 
184 static void pl022_txrx8(struct spi_chip *chip, uint8_t *wdat,
185 	uint8_t *rdat, size_t num_txpkts, size_t *num_rxpkts)
186 {
187 	size_t i = 0;
188 	size_t j = 0;
189 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
190 
191 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);
192 
193 	while (i < num_txpkts) {
194 		if (read8(pd->base + SSPSR) & SSPSR_TNF)
195 			/* tx 1 packet */
196 			write8(wdat[i++], pd->base + SSPDR);
197 	}
198 
199 	do {
200 		while ((read8(pd->base + SSPSR) & SSPSR_RNE) &&
201 			(j < *num_rxpkts))
202 			/* rx 1 packet */
203 			rdat[j++] = read8(pd->base + SSPDR);
204 	} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));
205 
206 	*num_rxpkts = j;
207 
208 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
209 }
210 
211 static void pl022_txrx16(struct spi_chip *chip, uint16_t *wdat,
212 	uint16_t *rdat, size_t num_txpkts, size_t *num_rxpkts)
213 {
214 	size_t i = 0;
215 	size_t j = 0;
216 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
217 
218 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);
219 
220 	while (i < num_txpkts) {
221 		if (read8(pd->base + SSPSR) & SSPSR_TNF)
222 			/* tx 1 packet */
223 			write16(wdat[i++], pd->base + SSPDR);
224 	}
225 
226 	do {
227 		while ((read8(pd->base + SSPSR) & SSPSR_RNE)
228 			&& (j < *num_rxpkts))
229 			/* rx 1 packet */
230 			rdat[j++] = read16(pd->base + SSPDR);
231 	} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));
232 
233 	*num_rxpkts = j;
234 
235 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
236 }
237 
238 static void pl022_tx8(struct spi_chip *chip, uint8_t *wdat,
239 	size_t num_txpkts)
240 {
241 	size_t i = 0;
242 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
243 
244 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);
245 
246 	while (i < num_txpkts) {
247 		if (read8(pd->base + SSPSR) & SSPSR_TNF)
248 			/* tx 1 packet */
249 			write8(wdat[i++], pd->base + SSPDR);
250 	}
251 
252 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
253 }
254 
255 static void pl022_tx16(struct spi_chip *chip, uint16_t *wdat,
256 	size_t num_txpkts)
257 {
258 	size_t i = 0;
259 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
260 
261 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);
262 
263 	while (i < num_txpkts) {
264 		if (read8(pd->base + SSPSR) & SSPSR_TNF)
265 			/* tx 1 packet */
266 			write16(wdat[i++], pd->base + SSPDR);
267 	}
268 
269 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
270 }
271 
272 static void pl022_rx8(struct spi_chip *chip, uint8_t *rdat,
273 	size_t *num_rxpkts)
274 {
275 	size_t j = 0;
276 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
277 
278 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);
279 
280 	do {
281 		while ((read8(pd->base + SSPSR) & SSPSR_RNE) &&
282 			(j < *num_rxpkts))
283 			/* rx 1 packet */
284 			rdat[j++] = read8(pd->base + SSPDR);
285 	} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));
286 
287 	*num_rxpkts = j;
288 
289 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
290 }
291 
292 static void pl022_rx16(struct spi_chip *chip, uint16_t *rdat,
293 	size_t *num_rxpkts)
294 {
295 	size_t j = 0;
296 	struct pl022_data *pd = container_of(chip, struct pl022_data, chip);
297 
298 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);
299 
300 	do {
301 		while ((read8(pd->base + SSPSR) & SSPSR_RNE) &&
302 			(j < *num_rxpkts))
303 			/* rx 1 packet */
304 			rdat[j++] = read16(pd->base + SSPDR);
305 	} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));
306 
307 	*num_rxpkts = j;
308 
309 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
310 }
311 
312 static void pl022_print_peri_id(struct pl022_data *pd __maybe_unused)
313 {
314 	DMSG("Expected: 0x 22 10 ?4 00");
315 	DMSG("Read: 0x %02x %02x %02x %02x",
316 		read32(pd->base + SSPPeriphID0),
317 		read32(pd->base + SSPPeriphID1),
318 		read32(pd->base + SSPPeriphID2),
319 		read32(pd->base + SSPPeriphID3));
320 }
321 
322 static void pl022_print_cell_id(struct pl022_data *pd __maybe_unused)
323 {
324 	DMSG("Expected: 0x 0d f0 05 b1");
325 	DMSG("Read: 0x %02x %02x %02x %02x",
326 		read32(pd->base + SSPPCellID0),
327 		read32(pd->base + SSPPCellID1),
328 		read32(pd->base + SSPPCellID2),
329 		read32(pd->base + SSPPCellID3));
330 }
331 
332 static void pl022_sanity_check(struct pl022_data *pd)
333 {
334 	assert(pd);
335 	assert(pd->chip.ops);
336 	assert(pd->gpio);
337 	assert(pd->gpio->ops);
338 	assert(pd->base);
339 	assert(pd->cs_gpio_base);
340 	assert(pd->clk_hz);
341 	assert(pd->speed_hz && pd->speed_hz <= pd->clk_hz/2);
342 	assert(pd->mode <= SPI_MODE3);
343 	assert(pd->data_size_bits == 8 || pd->data_size_bits == 16);
344 
345 	#ifdef PLATFORM_hikey
346 	DMSG("SSPB2BTRANS: Expected: 0x2. Read: 0x%x",
347 		read32(pd->base + SSPB2BTRANS));
348 	#endif
349 	pl022_print_peri_id(pd);
350 	pl022_print_cell_id(pd);
351 }
352 
353 static inline uint32_t pl022_calc_freq(struct pl022_data *pd,
354 	uint8_t cpsdvr, uint8_t scr)
355 {
356 	return pd->clk_hz / (cpsdvr * (1 + scr));
357 }
358 
359 static void pl022_calc_clk_divisors(struct pl022_data *pd,
360 	uint8_t *cpsdvr, uint8_t *scr)
361 {
362 	unsigned int freq1 = 0;
363 	unsigned int freq2 = 0;
364 	uint8_t tmp_cpsdvr1;
365 	uint8_t tmp_scr1;
366 	uint8_t tmp_cpsdvr2 = 0;
367 	uint8_t tmp_scr2 = 0;
368 
369 	for (tmp_scr1 = SSP_SCR_MIN; tmp_scr1 < SSP_SCR_MAX; tmp_scr1++) {
370 		for (tmp_cpsdvr1 = SSP_CPSDVR_MIN; tmp_cpsdvr1 < SSP_CPSDVR_MAX;
371 			tmp_cpsdvr1++) {
372 			freq1 = pl022_calc_freq(pd, tmp_cpsdvr1, tmp_scr1);
373 			if (freq1 == pd->speed_hz)
374 				goto done;
375 			else if (freq1 < pd->speed_hz)
376 				goto stage2;
377 		}
378 	}
379 
380 stage2:
381 	for (tmp_cpsdvr2 = SSP_CPSDVR_MIN; tmp_cpsdvr2 < SSP_CPSDVR_MAX;
382 		tmp_cpsdvr2++) {
383 		for (tmp_scr2 = SSP_SCR_MIN; tmp_scr2 < SSP_SCR_MAX;
384 			tmp_scr2++) {
385 			freq2 = pl022_calc_freq(pd, tmp_cpsdvr2, tmp_scr2);
386 			if (freq2 <= pd->speed_hz)
387 				goto done;
388 		}
389 	}
390 
391 done:
392 	if (freq1 >= freq2) {
393 		*cpsdvr = tmp_cpsdvr1;
394 		*scr = tmp_scr1;
395 		DMSG("speed: requested: %u, closest1: %u",
396 			pd->speed_hz, freq1);
397 	} else {
398 		*cpsdvr = tmp_cpsdvr2;
399 		*scr = tmp_scr2;
400 		DMSG("speed: requested: %u, closest2: %u",
401 			pd->speed_hz, freq2);
402 	}
403 	DMSG("CPSDVR: %u (0x%x), SCR: %u (0x%x)",
404 		*cpsdvr, *cpsdvr, *scr, *scr);
405 }
406 
407 static void pl022_flush_fifo(struct pl022_data *pd)
408 {
409 	uint32_t __maybe_unused rdat;
410 
411 	do {
412 		while (read32(pd->base + SSPSR) & SSPSR_RNE) {
413 			rdat = read32(pd->base + SSPDR);
414 			DMSG("rdat: 0x%x", rdat);
415 		}
416 	} while (read32(pd->base + SSPSR) & SSPSR_BSY);
417 }
418 
419 static const struct spi_ops pl022_ops = {
420 	.txrx8 = pl022_txrx8,
421 	.txrx16 = pl022_txrx16,
422 	.tx8 = pl022_tx8,
423 	.tx16 = pl022_tx16,
424 	.rx8 = pl022_rx8,
425 	.rx16 = pl022_rx16,
426 };
427 
428 void pl022_configure(struct pl022_data *pd)
429 {
430 	uint16_t mode;
431 	uint16_t data_size;
432 	uint8_t cpsdvr;
433 	uint8_t scr;
434 	uint8_t lbm;
435 
436 	pd->chip.ops = &pl022_ops;
437 	pl022_sanity_check(pd);
438 	pl022_calc_clk_divisors(pd, &cpsdvr, &scr);
439 
440 	/* configure ssp based on platform settings */
441 	switch (pd->mode) {
442 	case SPI_MODE0:
443 		DMSG("SPI_MODE0");
444 		mode = PL022_SPI_MODE0;
445 		break;
446 	case SPI_MODE1:
447 		DMSG("SPI_MODE1");
448 		mode = PL022_SPI_MODE1;
449 		break;
450 	case SPI_MODE2:
451 		DMSG("SPI_MODE2");
452 		mode = PL022_SPI_MODE2;
453 		break;
454 	case SPI_MODE3:
455 		DMSG("SPI_MODE3");
456 		mode = PL022_SPI_MODE3;
457 		break;
458 	default:
459 		EMSG("Invalid SPI mode: %u", pd->mode);
460 		panic();
461 	}
462 
463 	switch (pd->data_size_bits) {
464 	case 8:
465 		DMSG("Data size: 8");
466 		data_size = PL022_DATA_SIZE8;
467 		break;
468 	case 16:
469 		DMSG("Data size: 16");
470 		data_size = PL022_DATA_SIZE16;
471 		break;
472 	default:
473 		EMSG("Unsupported data size: %u bits", pd->data_size_bits);
474 		panic();
475 	}
476 
477 	if (pd->loopback) {
478 		DMSG("Starting in loopback mode!");
479 		lbm = SSPCR1_LBM_YES;
480 	} else {
481 		DMSG("Starting in regular (non-loopback) mode!");
482 		lbm = SSPCR1_LBM_NO;
483 	}
484 
485 	DMSG("set Serial Clock Rate (SCR), SPI mode (phase and clock)");
486 	DMSG("set frame format (SPI) and data size (8- or 16-bit)");
487 	io_mask16(pd->base + SSPCR0, SHIFT_U32(scr, 8) | mode | SSPCR0_FRF_SPI |
488 		data_size, MASK_16);
489 
490 	DMSG("set master mode, disable SSP, set loopback mode");
491 	io_mask8(pd->base + SSPCR1, SSPCR1_SOD_DISABLE | SSPCR1_MS_MASTER |
492 		SSPCR1_SSE_DISABLE | lbm, MASK_4);
493 
494 	DMSG("set clock prescale");
495 	io_mask8(pd->base + SSPCPSR, cpsdvr, SSPCPSR_CPSDVR);
496 
497 	DMSG("disable interrupts");
498 	io_mask8(pd->base + SSPIMSC, 0, MASK_4);
499 
500 	DMSG("set CS GPIO dir to out");
501 	pd->gpio->ops->set_direction(pd->cs_gpio_pin, GPIO_DIR_OUT);
502 
503 	DMSG("pull CS high");
504 	pd->gpio->ops->set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
505 }
506 
507 void pl022_start(struct pl022_data *pd)
508 {
509 	DMSG("empty FIFO before starting");
510 	pl022_flush_fifo(pd);
511 
512 	DMSG("enable SSP");
513 	io_mask8(pd->base + SSPCR1, SSPCR1_SSE_ENABLE, SSPCR1_SSE);
514 }
515 
516 void pl022_end(struct pl022_data *pd)
517 {
518 	/* disable ssp */
519 	io_mask8(pd->base + SSPCR1, SSPCR1_SSE_DISABLE, SSPCR1_SSE);
520 }
521 
522