1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * 4 * (C) Copyright 2000-2003 5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 6 * 7 * Copyright (C) 2004-2009 Freescale Semiconductor, Inc. 8 * TsiChung Liew (Tsi-Chung.Liew@freescale.com) 9 */ 10 11 #include <common.h> 12 #include <spi.h> 13 #include <malloc.h> 14 #include <asm/immap.h> 15 16 struct cf_spi_slave { 17 struct spi_slave slave; 18 uint baudrate; 19 int charbit; 20 }; 21 22 extern void cfspi_port_conf(void); 23 extern int cfspi_claim_bus(uint bus, uint cs); 24 extern void cfspi_release_bus(uint bus, uint cs); 25 26 DECLARE_GLOBAL_DATA_PTR; 27 28 #ifndef CONFIG_SPI_IDLE_VAL 29 #if defined(CONFIG_SPI_MMC) 30 #define CONFIG_SPI_IDLE_VAL 0xFFFF 31 #else 32 #define CONFIG_SPI_IDLE_VAL 0x0 33 #endif 34 #endif 35 36 #if defined(CONFIG_CF_DSPI) 37 /* DSPI specific mode */ 38 #define SPI_MODE_MOD 0x00200000 39 #define SPI_DBLRATE 0x00100000 40 41 static inline struct cf_spi_slave *to_cf_spi_slave(struct spi_slave *slave) 42 { 43 return container_of(slave, struct cf_spi_slave, slave); 44 } 45 46 static void cfspi_init(void) 47 { 48 volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; 49 50 cfspi_port_conf(); /* port configuration */ 51 52 dspi->mcr = DSPI_MCR_MSTR | DSPI_MCR_CSIS7 | DSPI_MCR_CSIS6 | 53 DSPI_MCR_CSIS5 | DSPI_MCR_CSIS4 | DSPI_MCR_CSIS3 | 54 DSPI_MCR_CSIS2 | DSPI_MCR_CSIS1 | DSPI_MCR_CSIS0 | 55 DSPI_MCR_CRXF | DSPI_MCR_CTXF; 56 57 /* Default setting in platform configuration */ 58 #ifdef CONFIG_SYS_DSPI_CTAR0 59 dspi->ctar[0] = CONFIG_SYS_DSPI_CTAR0; 60 #endif 61 #ifdef CONFIG_SYS_DSPI_CTAR1 62 dspi->ctar[1] = CONFIG_SYS_DSPI_CTAR1; 63 #endif 64 #ifdef CONFIG_SYS_DSPI_CTAR2 65 dspi->ctar[2] = CONFIG_SYS_DSPI_CTAR2; 66 #endif 67 #ifdef CONFIG_SYS_DSPI_CTAR3 68 dspi->ctar[3] = CONFIG_SYS_DSPI_CTAR3; 69 #endif 70 #ifdef CONFIG_SYS_DSPI_CTAR4 71 dspi->ctar[4] = CONFIG_SYS_DSPI_CTAR4; 72 #endif 73 #ifdef CONFIG_SYS_DSPI_CTAR5 74 dspi->ctar[5] = CONFIG_SYS_DSPI_CTAR5; 75 #endif 76 #ifdef CONFIG_SYS_DSPI_CTAR6 77 dspi->ctar[6] = CONFIG_SYS_DSPI_CTAR6; 78 #endif 79 #ifdef CONFIG_SYS_DSPI_CTAR7 80 dspi->ctar[7] = CONFIG_SYS_DSPI_CTAR7; 81 #endif 82 } 83 84 static void cfspi_tx(u32 ctrl, u16 data) 85 { 86 volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; 87 88 while ((dspi->sr & 0x0000F000) >= 4) ; 89 90 dspi->tfr = (ctrl | data); 91 } 92 93 static u16 cfspi_rx(void) 94 { 95 volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; 96 97 while ((dspi->sr & 0x000000F0) == 0) ; 98 99 return (dspi->rfr & 0xFFFF); 100 } 101 102 static int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout, 103 void *din, ulong flags) 104 { 105 struct cf_spi_slave *cfslave = to_cf_spi_slave(slave); 106 u16 *spi_rd16 = NULL, *spi_wr16 = NULL; 107 u8 *spi_rd = NULL, *spi_wr = NULL; 108 static u32 ctrl = 0; 109 uint len = bitlen >> 3; 110 111 if (cfslave->charbit == 16) { 112 bitlen >>= 1; 113 spi_wr16 = (u16 *) dout; 114 spi_rd16 = (u16 *) din; 115 } else { 116 spi_wr = (u8 *) dout; 117 spi_rd = (u8 *) din; 118 } 119 120 if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN) 121 ctrl |= DSPI_TFR_CONT; 122 123 ctrl = (ctrl & 0xFF000000) | ((1 << slave->cs) << 16); 124 125 if (len > 1) { 126 int tmp_len = len - 1; 127 while (tmp_len--) { 128 if (dout != NULL) { 129 if (cfslave->charbit == 16) 130 cfspi_tx(ctrl, *spi_wr16++); 131 else 132 cfspi_tx(ctrl, *spi_wr++); 133 cfspi_rx(); 134 } 135 136 if (din != NULL) { 137 cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL); 138 if (cfslave->charbit == 16) 139 *spi_rd16++ = cfspi_rx(); 140 else 141 *spi_rd++ = cfspi_rx(); 142 } 143 } 144 145 len = 1; /* remaining byte */ 146 } 147 148 if ((flags & SPI_XFER_END) == SPI_XFER_END) 149 ctrl &= ~DSPI_TFR_CONT; 150 151 if (len) { 152 if (dout != NULL) { 153 if (cfslave->charbit == 16) 154 cfspi_tx(ctrl, *spi_wr16); 155 else 156 cfspi_tx(ctrl, *spi_wr); 157 cfspi_rx(); 158 } 159 160 if (din != NULL) { 161 cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL); 162 if (cfslave->charbit == 16) 163 *spi_rd16 = cfspi_rx(); 164 else 165 *spi_rd = cfspi_rx(); 166 } 167 } else { 168 /* dummy read */ 169 cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL); 170 cfspi_rx(); 171 } 172 173 return 0; 174 } 175 176 static struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, 177 uint mode) 178 { 179 /* 180 * bit definition for mode: 181 * bit 31 - 28: Transfer size 3 to 16 bits 182 * 27 - 26: PCS to SCK delay prescaler 183 * 25 - 24: After SCK delay prescaler 184 * 23 - 22: Delay after transfer prescaler 185 * 21 : Allow overwrite for bit 31-22 and bit 20-8 186 * 20 : Double baud rate 187 * 19 - 16: PCS to SCK delay scaler 188 * 15 - 12: After SCK delay scaler 189 * 11 - 8: Delay after transfer scaler 190 * 7 - 0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST 191 */ 192 volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; 193 int prescaler[] = { 2, 3, 5, 7 }; 194 int scaler[] = { 195 2, 4, 6, 8, 196 16, 32, 64, 128, 197 256, 512, 1024, 2048, 198 4096, 8192, 16384, 32768 199 }; 200 int i, j, pbrcnt, brcnt, diff, tmp, dbr = 0; 201 int best_i, best_j, bestmatch = 0x7FFFFFFF, baud_speed; 202 u32 bus_setup = 0; 203 204 tmp = (prescaler[3] * scaler[15]); 205 /* Maximum and minimum baudrate it can handle */ 206 if ((cfslave->baudrate > (gd->bus_clk >> 1)) || 207 (cfslave->baudrate < (gd->bus_clk / tmp))) { 208 printf("Exceed baudrate limitation: Max %d - Min %d\n", 209 (int)(gd->bus_clk >> 1), (int)(gd->bus_clk / tmp)); 210 return NULL; 211 } 212 213 /* Activate Double Baud when it exceed 1/4 the bus clk */ 214 if ((CONFIG_SYS_DSPI_CTAR0 & DSPI_CTAR_DBR) || 215 (cfslave->baudrate > (gd->bus_clk / (prescaler[0] * scaler[0])))) { 216 bus_setup |= DSPI_CTAR_DBR; 217 dbr = 1; 218 } 219 220 if (mode & SPI_CPOL) 221 bus_setup |= DSPI_CTAR_CPOL; 222 if (mode & SPI_CPHA) 223 bus_setup |= DSPI_CTAR_CPHA; 224 if (mode & SPI_LSB_FIRST) 225 bus_setup |= DSPI_CTAR_LSBFE; 226 227 /* Overwrite default value set in platform configuration file */ 228 if (mode & SPI_MODE_MOD) { 229 230 if ((mode & 0xF0000000) == 0) 231 bus_setup |= 232 dspi->ctar[cfslave->slave.bus] & 0x78000000; 233 else 234 bus_setup |= ((mode & 0xF0000000) >> 1); 235 236 /* 237 * Check to see if it is enabled by default in platform 238 * config, or manual setting passed by mode parameter 239 */ 240 if (mode & SPI_DBLRATE) { 241 bus_setup |= DSPI_CTAR_DBR; 242 dbr = 1; 243 } 244 bus_setup |= (mode & 0x0FC00000) >> 4; /* PSCSCK, PASC, PDT */ 245 bus_setup |= (mode & 0x000FFF00) >> 4; /* CSSCK, ASC, DT */ 246 } else 247 bus_setup |= (dspi->ctar[cfslave->slave.bus] & 0x78FCFFF0); 248 249 cfslave->charbit = 250 ((dspi->ctar[cfslave->slave.bus] & 0x78000000) == 251 0x78000000) ? 16 : 8; 252 253 pbrcnt = sizeof(prescaler) / sizeof(int); 254 brcnt = sizeof(scaler) / sizeof(int); 255 256 /* baudrate calculation - to closer value, may not be exact match */ 257 for (best_i = 0, best_j = 0, i = 0; i < pbrcnt; i++) { 258 baud_speed = gd->bus_clk / prescaler[i]; 259 for (j = 0; j < brcnt; j++) { 260 tmp = (baud_speed / scaler[j]) * (1 + dbr); 261 262 if (tmp > cfslave->baudrate) 263 diff = tmp - cfslave->baudrate; 264 else 265 diff = cfslave->baudrate - tmp; 266 267 if (diff < bestmatch) { 268 bestmatch = diff; 269 best_i = i; 270 best_j = j; 271 } 272 } 273 } 274 bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j)); 275 dspi->ctar[cfslave->slave.bus] = bus_setup; 276 277 return &cfslave->slave; 278 } 279 #endif /* CONFIG_CF_DSPI */ 280 281 #ifdef CONFIG_CMD_SPI 282 int spi_cs_is_valid(unsigned int bus, unsigned int cs) 283 { 284 if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8))) 285 return 1; 286 else 287 return 0; 288 } 289 290 void spi_init(void) 291 { 292 cfspi_init(); 293 } 294 295 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 296 unsigned int max_hz, unsigned int mode) 297 { 298 struct cf_spi_slave *cfslave; 299 300 if (!spi_cs_is_valid(bus, cs)) 301 return NULL; 302 303 cfslave = spi_alloc_slave(struct cf_spi_slave, bus, cs); 304 if (!cfslave) 305 return NULL; 306 307 cfslave->baudrate = max_hz; 308 309 /* specific setup */ 310 return cfspi_setup_slave(cfslave, mode); 311 } 312 313 void spi_free_slave(struct spi_slave *slave) 314 { 315 struct cf_spi_slave *cfslave = to_cf_spi_slave(slave); 316 317 free(cfslave); 318 } 319 320 int spi_claim_bus(struct spi_slave *slave) 321 { 322 return cfspi_claim_bus(slave->bus, slave->cs); 323 } 324 325 void spi_release_bus(struct spi_slave *slave) 326 { 327 cfspi_release_bus(slave->bus, slave->cs); 328 } 329 330 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 331 void *din, unsigned long flags) 332 { 333 return cfspi_xfer(slave, bitlen, dout, din, flags); 334 } 335 #endif /* CONFIG_CMD_SPI */ 336