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