1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Andestech ATCSPI200 SPI controller driver. 4 * 5 * Copyright 2017 Andes Technology, Inc. 6 * Author: Rick Chen (rick@andestech.com) 7 */ 8 9 #include <clk.h> 10 #include <common.h> 11 #include <malloc.h> 12 #include <spi.h> 13 #include <asm/io.h> 14 #include <dm.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 #define MAX_TRANSFER_LEN 512 19 #define CHUNK_SIZE 1 20 #define SPI_TIMEOUT 0x100000 21 #define SPI0_BUS 0 22 #define SPI1_BUS 1 23 #define SPI0_BASE 0xf0b00000 24 #define SPI1_BASE 0xf0f00000 25 #define NSPI_MAX_CS_NUM 1 26 27 struct atcspi200_spi_regs { 28 u32 rev; 29 u32 reserve1[3]; 30 u32 format; /* 0x10 */ 31 #define DATA_LENGTH(x) ((x-1)<<8) 32 u32 pio; 33 u32 reserve2[2]; 34 u32 tctrl; /* 0x20 */ 35 #define TRAMODE_OFFSET 24 36 #define TRAMODE_MASK (0x0F<<TRAMODE_OFFSET) 37 #define TRAMODE_WR_SYNC (0<<TRAMODE_OFFSET) 38 #define TRAMODE_WO (1<<TRAMODE_OFFSET) 39 #define TRAMODE_RO (2<<TRAMODE_OFFSET) 40 #define TRAMODE_WR (3<<TRAMODE_OFFSET) 41 #define TRAMODE_RW (4<<TRAMODE_OFFSET) 42 #define TRAMODE_WDR (5<<TRAMODE_OFFSET) 43 #define TRAMODE_RDW (6<<TRAMODE_OFFSET) 44 #define TRAMODE_NONE (7<<TRAMODE_OFFSET) 45 #define TRAMODE_DW (8<<TRAMODE_OFFSET) 46 #define TRAMODE_DR (9<<TRAMODE_OFFSET) 47 #define WCNT_OFFSET 12 48 #define WCNT_MASK (0x1FF<<WCNT_OFFSET) 49 #define RCNT_OFFSET 0 50 #define RCNT_MASK (0x1FF<<RCNT_OFFSET) 51 u32 cmd; 52 u32 addr; 53 u32 data; 54 u32 ctrl; /* 0x30 */ 55 #define TXFTH_OFFSET 16 56 #define RXFTH_OFFSET 8 57 #define TXDMAEN (1<<4) 58 #define RXDMAEN (1<<3) 59 #define TXFRST (1<<2) 60 #define RXFRST (1<<1) 61 #define SPIRST (1<<0) 62 u32 status; 63 #define TXFFL (1<<23) 64 #define TXEPTY (1<<22) 65 #define TXFVE_MASK (0x1F<<16) 66 #define RXFEM (1<<14) 67 #define RXFVE_OFFSET (8) 68 #define RXFVE_MASK (0x1F<<RXFVE_OFFSET) 69 #define SPIBSY (1<<0) 70 u32 inten; 71 u32 intsta; 72 u32 timing; /* 0x40 */ 73 #define SCLK_DIV_MASK 0xFF 74 }; 75 76 struct nds_spi_slave { 77 volatile struct atcspi200_spi_regs *regs; 78 int to; 79 unsigned int freq; 80 ulong clock; 81 unsigned int mode; 82 u8 num_cs; 83 unsigned int mtiming; 84 size_t cmd_len; 85 u8 cmd_buf[16]; 86 size_t data_len; 87 size_t tran_len; 88 u8 *din; 89 u8 *dout; 90 unsigned int max_transfer_length; 91 }; 92 93 static int __atcspi200_spi_set_speed(struct nds_spi_slave *ns) 94 { 95 u32 tm; 96 u8 div; 97 tm = ns->regs->timing; 98 tm &= ~SCLK_DIV_MASK; 99 100 if(ns->freq >= ns->clock) 101 div =0xff; 102 else{ 103 for (div = 0; div < 0xff; div++) { 104 if (ns->freq >= ns->clock / (2 * (div + 1))) 105 break; 106 } 107 } 108 109 tm |= div; 110 ns->regs->timing = tm; 111 112 return 0; 113 114 } 115 116 static int __atcspi200_spi_claim_bus(struct nds_spi_slave *ns) 117 { 118 unsigned int format=0; 119 ns->regs->ctrl |= (TXFRST|RXFRST|SPIRST); 120 while((ns->regs->ctrl &(TXFRST|RXFRST|SPIRST))&&(ns->to--)) 121 if(!ns->to) 122 return -EINVAL; 123 124 ns->cmd_len = 0; 125 format = ns->mode|DATA_LENGTH(8); 126 ns->regs->format = format; 127 __atcspi200_spi_set_speed(ns); 128 129 return 0; 130 } 131 132 static int __atcspi200_spi_release_bus(struct nds_spi_slave *ns) 133 { 134 /* do nothing */ 135 return 0; 136 } 137 138 static int __atcspi200_spi_start(struct nds_spi_slave *ns) 139 { 140 int i,olen=0; 141 int tc = ns->regs->tctrl; 142 143 tc &= ~(WCNT_MASK|RCNT_MASK|TRAMODE_MASK); 144 if ((ns->din)&&(ns->cmd_len)) 145 tc |= TRAMODE_WR; 146 else if (ns->din) 147 tc |= TRAMODE_RO; 148 else 149 tc |= TRAMODE_WO; 150 151 if(ns->dout) 152 olen = ns->tran_len; 153 tc |= (ns->cmd_len+olen-1) << WCNT_OFFSET; 154 155 if(ns->din) 156 tc |= (ns->tran_len-1) << RCNT_OFFSET; 157 158 ns->regs->tctrl = tc; 159 ns->regs->cmd = 1; 160 161 for (i=0;i<ns->cmd_len;i++) 162 ns->regs->data = ns->cmd_buf[i]; 163 164 return 0; 165 } 166 167 static int __atcspi200_spi_stop(struct nds_spi_slave *ns) 168 { 169 ns->regs->timing = ns->mtiming; 170 while ((ns->regs->status & SPIBSY)&&(ns->to--)) 171 if (!ns->to) 172 return -EINVAL; 173 174 return 0; 175 } 176 177 static void __nspi_espi_tx(struct nds_spi_slave *ns, const void *dout) 178 { 179 ns->regs->data = *(u8 *)dout; 180 } 181 182 static int __nspi_espi_rx(struct nds_spi_slave *ns, void *din, unsigned int bytes) 183 { 184 *(u8 *)din = ns->regs->data; 185 return bytes; 186 } 187 188 189 static int __atcspi200_spi_xfer(struct nds_spi_slave *ns, 190 unsigned int bitlen, const void *data_out, void *data_in, 191 unsigned long flags) 192 { 193 unsigned int event, rx_bytes; 194 const void *dout = NULL; 195 void *din = NULL; 196 int num_blks, num_chunks, max_tran_len, tran_len; 197 int num_bytes; 198 u8 *cmd_buf = ns->cmd_buf; 199 size_t cmd_len = ns->cmd_len; 200 size_t data_len = bitlen / 8; 201 int rf_cnt; 202 int ret = 0; 203 204 max_tran_len = ns->max_transfer_length; 205 switch (flags) { 206 case SPI_XFER_BEGIN: 207 cmd_len = ns->cmd_len = data_len; 208 memcpy(cmd_buf, data_out, cmd_len); 209 return 0; 210 211 case 0: 212 case SPI_XFER_END: 213 if (bitlen == 0) { 214 return 0; 215 } 216 ns->data_len = data_len; 217 ns->din = (u8 *)data_in; 218 ns->dout = (u8 *)data_out; 219 break; 220 221 case SPI_XFER_BEGIN | SPI_XFER_END: 222 ns->data_len = 0; 223 ns->din = 0; 224 ns->dout = 0; 225 cmd_len = ns->cmd_len = data_len; 226 memcpy(cmd_buf, data_out, cmd_len); 227 data_out = 0; 228 data_len = 0; 229 __atcspi200_spi_start(ns); 230 break; 231 } 232 debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %u\n", 233 *(uint *)data_out, data_out, *(uint *)data_in, data_in, data_len); 234 num_chunks = DIV_ROUND_UP(data_len, max_tran_len); 235 din = data_in; 236 dout = data_out; 237 while (num_chunks--) { 238 tran_len = min(data_len, (size_t)max_tran_len); 239 ns->tran_len = tran_len; 240 num_blks = DIV_ROUND_UP(tran_len , CHUNK_SIZE); 241 num_bytes = (tran_len) % CHUNK_SIZE; 242 if(num_bytes == 0) 243 num_bytes = CHUNK_SIZE; 244 __atcspi200_spi_start(ns); 245 246 while (num_blks) { 247 event = in_le32(&ns->regs->status); 248 if ((event & TXEPTY) && (data_out)) { 249 __nspi_espi_tx(ns, dout); 250 num_blks -= CHUNK_SIZE; 251 dout += CHUNK_SIZE; 252 } 253 254 if ((event & RXFVE_MASK) && (data_in)) { 255 rf_cnt = ((event & RXFVE_MASK)>> RXFVE_OFFSET); 256 if (rf_cnt >= CHUNK_SIZE) 257 rx_bytes = CHUNK_SIZE; 258 else if (num_blks == 1 && rf_cnt == num_bytes) 259 rx_bytes = num_bytes; 260 else 261 continue; 262 263 if (__nspi_espi_rx(ns, din, rx_bytes) == rx_bytes) { 264 num_blks -= CHUNK_SIZE; 265 din = (unsigned char *)din + rx_bytes; 266 } 267 } 268 } 269 270 data_len -= tran_len; 271 if(data_len) 272 { 273 ns->cmd_buf[1] += ((tran_len>>16)&0xff); 274 ns->cmd_buf[2] += ((tran_len>>8)&0xff); 275 ns->cmd_buf[3] += ((tran_len)&0xff); 276 ns->data_len = data_len; 277 } 278 ret = __atcspi200_spi_stop(ns); 279 } 280 ret = __atcspi200_spi_stop(ns); 281 282 return ret; 283 } 284 285 static int atcspi200_spi_set_speed(struct udevice *bus, uint max_hz) 286 { 287 struct nds_spi_slave *ns = dev_get_priv(bus); 288 289 debug("%s speed %u\n", __func__, max_hz); 290 291 ns->freq = max_hz; 292 __atcspi200_spi_set_speed(ns); 293 294 return 0; 295 } 296 297 static int atcspi200_spi_set_mode(struct udevice *bus, uint mode) 298 { 299 struct nds_spi_slave *ns = dev_get_priv(bus); 300 301 debug("%s mode %u\n", __func__, mode); 302 ns->mode = mode; 303 304 return 0; 305 } 306 307 static int atcspi200_spi_claim_bus(struct udevice *dev) 308 { 309 struct dm_spi_slave_platdata *slave_plat = 310 dev_get_parent_platdata(dev); 311 struct udevice *bus = dev->parent; 312 struct nds_spi_slave *ns = dev_get_priv(bus); 313 314 if (slave_plat->cs >= ns->num_cs) { 315 printf("Invalid SPI chipselect\n"); 316 return -EINVAL; 317 } 318 319 return __atcspi200_spi_claim_bus(ns); 320 } 321 322 static int atcspi200_spi_release_bus(struct udevice *dev) 323 { 324 struct nds_spi_slave *ns = dev_get_priv(dev->parent); 325 326 return __atcspi200_spi_release_bus(ns); 327 } 328 329 static int atcspi200_spi_xfer(struct udevice *dev, unsigned int bitlen, 330 const void *dout, void *din, 331 unsigned long flags) 332 { 333 struct udevice *bus = dev->parent; 334 struct nds_spi_slave *ns = dev_get_priv(bus); 335 336 return __atcspi200_spi_xfer(ns, bitlen, dout, din, flags); 337 } 338 339 static int atcspi200_spi_get_clk(struct udevice *bus) 340 { 341 struct nds_spi_slave *ns = dev_get_priv(bus); 342 struct clk clk; 343 ulong clk_rate; 344 int ret; 345 346 ret = clk_get_by_index(bus, 0, &clk); 347 if (ret) 348 return -EINVAL; 349 350 clk_rate = clk_get_rate(&clk); 351 if (!clk_rate) 352 return -EINVAL; 353 354 ns->clock = clk_rate; 355 clk_free(&clk); 356 357 return 0; 358 } 359 360 static int atcspi200_spi_probe(struct udevice *bus) 361 { 362 struct nds_spi_slave *ns = dev_get_priv(bus); 363 364 ns->to = SPI_TIMEOUT; 365 ns->max_transfer_length = MAX_TRANSFER_LEN; 366 ns->mtiming = ns->regs->timing; 367 atcspi200_spi_get_clk(bus); 368 369 return 0; 370 } 371 372 static int atcspi200_ofdata_to_platadata(struct udevice *bus) 373 { 374 struct nds_spi_slave *ns = dev_get_priv(bus); 375 const void *blob = gd->fdt_blob; 376 int node = dev_of_offset(bus); 377 378 ns->regs = map_physmem(devfdt_get_addr(bus), 379 sizeof(struct atcspi200_spi_regs), 380 MAP_NOCACHE); 381 if (!ns->regs) { 382 printf("%s: could not map device address\n", __func__); 383 return -EINVAL; 384 } 385 ns->num_cs = fdtdec_get_int(blob, node, "num-cs", 4); 386 387 return 0; 388 } 389 390 static const struct dm_spi_ops atcspi200_spi_ops = { 391 .claim_bus = atcspi200_spi_claim_bus, 392 .release_bus = atcspi200_spi_release_bus, 393 .xfer = atcspi200_spi_xfer, 394 .set_speed = atcspi200_spi_set_speed, 395 .set_mode = atcspi200_spi_set_mode, 396 }; 397 398 static const struct udevice_id atcspi200_spi_ids[] = { 399 { .compatible = "andestech,atcspi200" }, 400 { } 401 }; 402 403 U_BOOT_DRIVER(atcspi200_spi) = { 404 .name = "atcspi200_spi", 405 .id = UCLASS_SPI, 406 .of_match = atcspi200_spi_ids, 407 .ops = &atcspi200_spi_ops, 408 .ofdata_to_platdata = atcspi200_ofdata_to_platadata, 409 .priv_auto_alloc_size = sizeof(struct nds_spi_slave), 410 .probe = atcspi200_spi_probe, 411 }; 412