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 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 36 static inline void writel(u32 val, void *addr) 37 { 38 *(volatile u32 *)addr = val; 39 } 40 41 static inline u32 readl(void *addr) 42 { 43 return *(volatile u32 *)addr; 44 } 45 46 static void rkspi_dump_regs(struct rockchip_spi *regs) 47 { 48 debug("ctrl0: \t\t0x%08x\n", readl(®s->ctrlr0)); 49 debug("ctrl1: \t\t0x%08x\n", readl(®s->ctrlr1)); 50 debug("ssienr: \t\t0x%08x\n", readl(®s->enr)); 51 debug("ser: \t\t0x%08x\n", readl(®s->ser)); 52 debug("baudr: \t\t0x%08x\n", readl(®s->baudr)); 53 debug("txftlr: \t\t0x%08x\n", readl(®s->txftlr)); 54 debug("rxftlr: \t\t0x%08x\n", readl(®s->rxftlr)); 55 debug("txflr: \t\t0x%08x\n", readl(®s->txflr)); 56 debug("rxflr: \t\t0x%08x\n", readl(®s->rxflr)); 57 debug("sr: \t\t0x%08x\n", readl(®s->sr)); 58 debug("imr: \t\t0x%08x\n", readl(®s->imr)); 59 debug("isr: \t\t0x%08x\n", readl(®s->isr)); 60 debug("dmacr: \t\t0x%08x\n", readl(®s->dmacr)); 61 debug("dmatdlr: \t0x%08x\n", readl(®s->dmatdlr)); 62 debug("dmardlr: \t0x%08x\n", readl(®s->dmardlr)); 63 } 64 65 static void rkspi_enable_chip(struct rockchip_spi *regs, bool enable) 66 { 67 writel(enable ? 1 : 0, ®s->enr); 68 } 69 70 static void rkspi_set_baudr(struct rockchip_spi_priv *priv, uint clk_div) 71 { 72 writel(clk_div, &priv->regs->baudr); 73 } 74 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(®s->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 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, ®s->ser); 97 } 98 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, ®s->ser); 106 } 107 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 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, ®s->ctrlr0); 201 202 return 0; 203 } 204 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, ®s->ctrlr0); 218 219 return 0; 220 } 221 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 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, ®s->ctrlr1); 255 rkspi_enable_chip(regs, true); 256 257 toread = todo; 258 towrite = todo; 259 while (toread || towrite) { 260 u32 status = readl(®s->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 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 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 343 static void spi_hw_init(void) 344 { 345 /* Setting the clock and iomux */ 346 /* todo */ 347 } 348 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