1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/* SPI driver */ 14 15#include <autoconf.h> 16#include <platsupport/gen_config.h> 17#include <stdio.h> 18#include <stdint.h> 19#include <platsupport/spi.h> 20#include <platsupport/plat/mux.h> 21#include "../../services.h" 22 23//#define DEBUG_SPI 24#ifdef DEBUG_SPI 25#define DSPI(args...) \ 26 do { \ 27 printf("SPI %s(%d):", __func__, __LINE__); \ 28 printf(args); \ 29 printf("\n"); \ 30 } while(0) 31#else 32#define DSPI(...) do{}while(0) 33#endif 34 35/* SPI configuration */ 36#define CH_CFG_HIGH_SPEED_EN BIT(6) 37#define CH_CFG_SW_RST BIT(5) 38#define CH_CFG_SLAVE BIT(4) 39#define CH_CFG_CPOL BIT(3) 40#define CH_CFG_CPHA BIT(2) 41#define CH_CFG_RX_CH_ON BIT(1) 42#define CH_CFG_TX_CH_ON BIT(0) 43 44/* FIFO control */ 45#define FIFO_SIZE 64 46#define MODE_CFG_CH_WIDTH_SHF (29) 47#define MODE_CFG_TRAILING_CNT_SHF (19) 48#define MODE_CFG_BUS_WIDTH_SHF (17) 49#define MODE_CFG_RX_RDY_LVL_SHF (11) 50#define MODE_CFG_TX_RDY_LVL_SHF (5) 51#define MODE_CFG_RX_DMA_SW BIT(2) 52#define MODE_CFG_TX_DMA_SW BIT(1) 53#define MODE_CFG_DMA_TYPE BIT(0) 54 55/* Slave selection control */ 56#define CS_REG_NCS_TIME_COUNT_SHF (4) 57#define CS_REG_AUTO_N_MANUAL BIT(1) 58#define CS_REG_NSSOUT BIT(0) 59 60/* Interrupt enable */ 61#define INT_EN_TRAILING BIT(6) 62#define INT_EN_RX_OVERRUN BIT(5) 63#define INT_EN_RX_UNDERRUN BIT(4) 64#define INT_EN_TX_OVERRUN BIT(3) 65#define INT_EN_TX_UNDERRUN BIT(2) 66#define INT_EN_RX_FIFO_RDY BIT(1) 67#define INT_EN_TX_FIFO_RDY BIT(0) 68 69/* SPI status */ 70#define STATUS_TX_DONE BIT(25) 71#define STATUS_TRAILING_BYTE BIT(24) 72#define STATUS_RX_FIFO_LVL_SHF (15) 73#define STATUS_TX_FIFO_LVL_SHF (6) 74#define STATUS_RX_OVERRUN BIT(5) 75#define STATUS_RX_UNDERRUN BIT(4) 76#define STATUS_TX_OVERRUN BIT(3) 77#define STATUS_TX_UNDERRUN BIT(2) 78#define STATUS_RX_FIFO_RDY BIT(1) 79#define STATUS_TX_FIFO_RDY BIT(0) 80 81/* Packet count */ 82#define PACKET_CNT_EN BIT(16) 83#define PACKET_CNT_VALUE_SHF BIT(0) 84 85/* Interrupt pending clear */ 86#define PENDING_CLR_TX_UNDERRUN BIT(4) 87#define PENDING_CLR_TX_OVERRUN BIT(3) 88#define PENDING_CLR_RX_UNDERRUN BIT(2) 89#define PENDING_CLR_RX_OVERRUN BIT(1) 90#define PENDING_CLR_TRAILING BIT(0) 91 92/* Swap configuration */ 93#define SWAP_CFG_RX_HWORD BIT(7) 94#define SWAP_CFG_RX_BYTE BIT(6) 95#define SWAP_CFG_RX_BIT BIT(5) 96#define SWAP_CFG_RX_EN BIT(4) 97#define SWAP_CFG_TX_HWORD BIT(3) 98#define SWAP_CFG_TX_BYTE BIT(2) 99#define SWAP_CFG_TX_BIT BIT(1) 100#define SWAP_CFG_TX_EN BIT(0) 101 102/* Feedback clock selection */ 103#define FB_CLK_SEL_SHF (0) 104 105struct spi_regs { 106 uint32_t ch_cfg; 107 uint32_t res; 108 uint32_t mode_cfg; 109 uint32_t cs_reg; 110 uint32_t int_en; 111 uint32_t status; 112 uint32_t tx_data; 113 uint32_t rx_data; 114 uint32_t packet_cnt; 115 uint32_t pending_clr; 116 uint32_t swap_cfg; 117 uint32_t fb_clk_sel; 118}; 119 120enum spi_mode { 121 MASTER_MODE = 0, 122 SLAVE_MODE 123}; 124 125struct spi_bus { 126 volatile struct spi_regs* regs; 127 enum mux_feature mux; 128 enum clk_id clkid; 129 int mode: 1; //0 -- Master, 1 -- Slave 130 int high_speed: 1; //High speed operation in slave mode. 131 int cs_auto: 1; //Auto chip selection. 132 clk_t *clk; //Clock for changing the bus speed. 133 134 /* Transfer management */ 135 const char *txbuf; 136 char *rxbuf; 137 size_t txcnt, rxcnt; 138 size_t txsize, rxsize; 139 spi_callback_fn cb; 140 void* token; 141}; 142 143static spi_bus_t _spi[NSPI] = { 144 { .regs = NULL, .mux = MUX_SPI0, .clkid = CLK_SPI0 }, 145 { .regs = NULL, .mux = MUX_SPI1, .clkid = CLK_SPI1 }, 146 { .regs = NULL, .mux = MUX_SPI2, .clkid = CLK_SPI2 }, 147#if defined(CONFIG_PLAT_EXYNOS5) 148 { .regs = NULL, .mux = MUX_SPI0_ISP, .clkid = CLK_SPI0_ISP }, 149 { .regs = NULL, .mux = MUX_SPI1_ISP, .clkid = CLK_SPI1_ISP }, 150#endif /* EXYNOSX */ 151}; 152 153static void 154spi_reset(spi_bus_t *spi_bus) 155{ 156 uint32_t v; 157 158 /* Turn off the channel */ 159 v = spi_bus->regs->ch_cfg; 160 v &= ~(CH_CFG_RX_CH_ON | CH_CFG_TX_CH_ON); 161 spi_bus->regs->ch_cfg = v; 162 163 /* Write to reset bit */ 164 v = spi_bus->regs->ch_cfg; 165 v |= CH_CFG_SW_RST; 166 spi_bus->regs->ch_cfg = v; 167 168 /* Clear reset bit */ 169 v = spi_bus->regs->ch_cfg; 170 v &= ~CH_CFG_SW_RST; 171 spi_bus->regs->ch_cfg = v; 172 173 /* Turn on the channel */ 174 v = spi_bus->regs->ch_cfg; 175 v |= (CH_CFG_RX_CH_ON | CH_CFG_TX_CH_ON); 176 spi_bus->regs->ch_cfg = v; 177} 178 179static void 180spi_config(spi_bus_t *spi_bus) 181{ 182 uint32_t v; 183 184 /* Step1: SPI configuration */ 185 v = 0; 186 /* Master/Slave mode */ 187 if (spi_bus->mode == SLAVE_MODE) { 188 v |= CH_CFG_SLAVE; 189 190 /* High speed mode is slave mode only */ 191 if (spi_bus->high_speed) { 192 v |= CH_CFG_HIGH_SPEED_EN; 193 v &= ~CH_CFG_CPHA; 194 } 195 } 196 spi_bus->regs->ch_cfg = v; 197 198 /* 199 * Step2: Feedback clock 200 * The default clock is 33MHz, so we use a 180 degree phase feedback. 201 * The feedback clock only works in the master mode. 202 */ 203 if (spi_bus->mode == MASTER_MODE) { 204 v = (0x2 << FB_CLK_SEL_SHF); 205 spi_bus->regs->fb_clk_sel = v; 206 } 207 208 /* 209 * Step3: FIFO control 210 * Channel width to Byte, No DMA, only need to set trigger level. 211 */ 212 v = (0x20 << MODE_CFG_RX_RDY_LVL_SHF) | (0x20 << MODE_CFG_TX_RDY_LVL_SHF); 213 spi_bus->regs->mode_cfg = v; 214 215 /* Step4: Interrupts */ 216 spi_bus->regs->int_en = 0x0; 217 spi_bus->regs->pending_clr = 0xff; 218 219 /* Step5: Packet control */ 220 spi_bus->regs->packet_cnt = 0; 221 222 /* Step6: Turn on the channel */ 223 v = spi_bus->regs->ch_cfg; 224 v |= (CH_CFG_RX_CH_ON | CH_CFG_TX_CH_ON); 225 spi_bus->regs->ch_cfg = v; 226 227 /* Step7: Chip selection */ 228 v = (0x0 << CS_REG_NCS_TIME_COUNT_SHF); 229 if (spi_bus->cs_auto) { 230 v |= CS_REG_AUTO_N_MANUAL; 231 } else { 232 v |= CS_REG_NSSOUT; 233 } 234 spi_bus->regs->cs_reg = v; 235} 236 237static void 238spi_cs(spi_bus_t* spi_bus, enum spi_cs_state state) 239{ 240 if (!spi_bus->cs_auto) { 241 uint32_t v; 242 v = spi_bus->regs->cs_reg; 243 if (state == SPI_CS_ASSERT) { 244 v &= ~CS_REG_NSSOUT; 245 } else { 246 v |= CS_REG_NSSOUT; 247 } 248 spi_bus->regs->cs_reg = v; 249 } 250} 251 252static int 253spi_init_common(spi_bus_t* spi_bus, mux_sys_t* mux_sys, clock_sys_t* clock_sys) 254{ 255 if (mux_sys && mux_sys_valid(mux_sys)) { 256 mux_feature_enable(mux_sys, spi_bus->mux, MUX_DIR_NOT_A_GPIO); 257 } else { 258// LOG_INFO("SPI: Skipping MUX initialisation as no mux subsystem was provided\n"); 259 } 260 261 if (clock_sys && clock_sys_valid(clock_sys)) { 262 spi_bus->clk = clk_get_clock(clock_sys, spi_bus->clkid); 263 } else { 264// LOG_INFO("SPI: Assuming default clock frequency as no clock subsystem was provided\n"); 265 spi_bus->clk = NULL; 266 } 267 268 spi_bus->mode = 0; 269 spi_bus->high_speed = 0; 270 spi_bus->cs_auto = 0; 271 272 spi_reset(spi_bus); 273 spi_config(spi_bus); 274 return 0; 275} 276 277int 278transfer_data(spi_bus_t* spi_bus) 279{ 280 int rxfifo_cnt, txfifo_cnt, txfifo_space; 281 uint32_t stat; 282 stat = spi_bus->regs->status; 283 rxfifo_cnt = (stat >> STATUS_RX_FIFO_LVL_SHF) & 0x1FF; 284 txfifo_cnt = (stat >> STATUS_TX_FIFO_LVL_SHF) & 0x1FF; 285 txfifo_space = FIFO_SIZE - txfifo_cnt - 1; 286 287 /* Check for fatal events */ 288 if (stat & STATUS_RX_OVERRUN) { 289 printf("SPI RX overrun\n"); 290 } 291 if (stat & STATUS_RX_UNDERRUN) { 292 printf("SPI RX underrun\n"); 293 } 294 if (stat & STATUS_TX_OVERRUN) { 295 printf("SPI TX overrun\n"); 296 } 297 if (stat & STATUS_TX_UNDERRUN) { 298 printf("SPI TX underrun\n"); 299 } 300 301 /* Drain the RX FIFO */ 302 while (rxfifo_cnt--) { 303 uint32_t d; 304 d = spi_bus->regs->rx_data; 305 /* Store the data only if we are in RX phase */ 306 if (spi_bus->rxcnt >= spi_bus->txsize) { 307 assert(spi_bus->rxcnt - spi_bus->txsize < spi_bus->rxsize); 308 } 309 *spi_bus->rxbuf++ = d; 310 spi_bus->rxcnt++; 311 } 312 313 /* Fill the TX FIFO */ 314 if (txfifo_space > spi_bus->txsize + spi_bus->rxsize - spi_bus->rxcnt) { 315 txfifo_space = spi_bus->txsize + spi_bus->rxsize - spi_bus->txcnt; 316 } 317 while (txfifo_space--) { 318 uint32_t d; 319 if (spi_bus->txcnt < spi_bus->txsize) { 320 d = *spi_bus->txbuf++; 321 } else { 322 d = 0; 323 } 324 spi_bus->regs->tx_data = d; 325 spi_bus->txcnt++; 326 } 327 328 /* Check for completion */ 329 if ((stat & STATUS_TX_DONE) && spi_bus->rxcnt == spi_bus->rxsize + spi_bus->txsize) { 330 spi_bus->regs->int_en = 0; 331 spi_cs(spi_bus, SPI_CS_RELAX); 332 if (spi_bus->cb) { 333 spi_bus->cb(spi_bus, spi_bus->txcnt, spi_bus->token); 334 } 335 336 return 0; 337 } 338 339 return 1; 340} 341 342void 343spi_handle_irq(spi_bus_t* spi_bus) 344{ 345 transfer_data(spi_bus); 346} 347 348int 349spi_xfer(spi_bus_t* spi_bus, const void* txdata, size_t txcnt, 350 void* rxdata, size_t rxcnt, spi_callback_fn cb, void* token) 351{ 352 spi_bus->txbuf = (const char*)txdata; 353 spi_bus->rxbuf = (char*)rxdata; 354 spi_bus->rxsize = rxcnt; 355 spi_bus->txsize = txcnt; 356 spi_bus->rxcnt = 0; 357 spi_bus->txcnt = 0; 358 359 DSPI("Starting transfer: TX: from 0x%x, %d bytes. RX to 0x%x, %d bytes\n", 360 (uint32_t)txdata, txcnt, (uint32_t)rxdata, rxcnt); 361 362 transfer_data(spi_bus); 363 spi_cs(spi_bus, SPI_CS_ASSERT); 364 if (cb == NULL) { 365 while (transfer_data(spi_bus)); 366 } else { 367 uint32_t v; 368 spi_bus->cb = cb; 369 spi_bus->token = token; 370 v = INT_EN_RX_OVERRUN | INT_EN_RX_UNDERRUN 371 | INT_EN_TX_OVERRUN | INT_EN_TX_UNDERRUN 372 | INT_EN_RX_FIFO_RDY | INT_EN_TX_FIFO_RDY 373 | INT_EN_TRAILING; 374 spi_bus->regs->pending_clr = 0xFFFFFFFF; 375 spi_bus->regs->int_en = v; 376 } 377 378 return spi_bus->rxcnt; 379} 380 381long 382spi_set_speed(spi_bus_t* spi_bus, long bps) 383{ 384 return 0; 385} 386 387void 388spi_prepare_transfer(spi_bus_t* spi_bus, const spi_slave_config_t* cfg) 389{ 390 if (spi_bus->clk && clk_get_freq(spi_bus->clk) != cfg->speed_hz) { 391 clk_set_freq(spi_bus->clk, cfg->speed_hz); 392 } 393 394 /* Set feedback clock, only when SPI runs at a high frequency */ 395 if (cfg->speed_hz >= 1 * MHZ) { 396 spi_bus->regs->fb_clk_sel = (cfg->fb_delay << FB_CLK_SEL_SHF); 397 } 398} 399 400int 401exynos_spi_init(enum spi_id id, void* base, 402 mux_sys_t* mux_sys, clock_sys_t* clock_sys, 403 spi_bus_t** ret_spi_bus) 404{ 405 if (id >= 0 && id < NSPI) { 406 spi_bus_t* spi_bus = _spi + id; 407 *ret_spi_bus = spi_bus; 408 spi_bus->regs = base; 409 return spi_init_common(spi_bus, mux_sys, clock_sys); 410 } else { 411 return -1; 412 } 413} 414 415int 416spi_init(enum spi_id id, ps_io_ops_t* io_ops, spi_bus_t** ret_spi_bus) 417{ 418 spi_bus_t* spi_bus = _spi + id; 419 *ret_spi_bus = spi_bus; 420 /* Map memory */ 421 DSPI("Mapping spi %d\n", id); 422 switch (id) { 423 case SPI0: 424 MAP_IF_NULL(io_ops, EXYNOS_SPI0, spi_bus->regs); 425 break; 426 case SPI1: 427 MAP_IF_NULL(io_ops, EXYNOS_SPI1, spi_bus->regs); 428 break; 429 case SPI2: 430 MAP_IF_NULL(io_ops, EXYNOS_SPI2, spi_bus->regs); 431 break; 432#ifdef CONFIG_PLAT_EXYNOS5 433 case SPI0_ISP: 434 MAP_IF_NULL(io_ops, EXYNOS_SPI0_ISP, spi_bus->regs); 435 break; 436 case SPI1_ISP: 437 MAP_IF_NULL(io_ops, EXYNOS_SPI1_ISP, spi_bus->regs); 438 break; 439#endif 440 default: 441 return -1; 442 } 443 444 return spi_init_common(spi_bus, &io_ops->mux_sys, &io_ops->clock_sys); 445} 446