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 unsigned long 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 if (data_out) 233 debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %lu\n", 234 *(uint *)data_out, data_out, *(uint *)data_in, 235 data_in, data_len); 236 num_chunks = DIV_ROUND_UP(data_len, max_tran_len); 237 din = data_in; 238 dout = data_out; 239 while (num_chunks--) { 240 tran_len = min((size_t)data_len, (size_t)max_tran_len); 241 ns->tran_len = tran_len; 242 num_blks = DIV_ROUND_UP(tran_len , CHUNK_SIZE); 243 num_bytes = (tran_len) % CHUNK_SIZE; 244 if(num_bytes == 0) 245 num_bytes = CHUNK_SIZE; 246 __atcspi200_spi_start(ns); 247 248 while (num_blks) { 249 event = in_le32(&ns->regs->status); 250 if ((event & TXEPTY) && (data_out)) { 251 __nspi_espi_tx(ns, dout); 252 num_blks -= CHUNK_SIZE; 253 dout += CHUNK_SIZE; 254 } 255 256 if ((event & RXFVE_MASK) && (data_in)) { 257 rf_cnt = ((event & RXFVE_MASK)>> RXFVE_OFFSET); 258 if (rf_cnt >= CHUNK_SIZE) 259 rx_bytes = CHUNK_SIZE; 260 else if (num_blks == 1 && rf_cnt == num_bytes) 261 rx_bytes = num_bytes; 262 else 263 continue; 264 265 if (__nspi_espi_rx(ns, din, rx_bytes) == rx_bytes) { 266 num_blks -= CHUNK_SIZE; 267 din = (unsigned char *)din + rx_bytes; 268 } 269 } 270 } 271 272 data_len -= tran_len; 273 if(data_len) 274 { 275 ns->cmd_buf[1] += ((tran_len>>16)&0xff); 276 ns->cmd_buf[2] += ((tran_len>>8)&0xff); 277 ns->cmd_buf[3] += ((tran_len)&0xff); 278 ns->data_len = data_len; 279 } 280 ret = __atcspi200_spi_stop(ns); 281 } 282 ret = __atcspi200_spi_stop(ns); 283 284 return ret; 285 } 286 287 static int atcspi200_spi_set_speed(struct udevice *bus, uint max_hz) 288 { 289 struct nds_spi_slave *ns = dev_get_priv(bus); 290 291 debug("%s speed %u\n", __func__, max_hz); 292 293 ns->freq = max_hz; 294 __atcspi200_spi_set_speed(ns); 295 296 return 0; 297 } 298 299 static int atcspi200_spi_set_mode(struct udevice *bus, uint mode) 300 { 301 struct nds_spi_slave *ns = dev_get_priv(bus); 302 303 debug("%s mode %u\n", __func__, mode); 304 ns->mode = mode; 305 306 return 0; 307 } 308 309 static int atcspi200_spi_claim_bus(struct udevice *dev) 310 { 311 struct dm_spi_slave_platdata *slave_plat = 312 dev_get_parent_platdata(dev); 313 struct udevice *bus = dev->parent; 314 struct nds_spi_slave *ns = dev_get_priv(bus); 315 316 if (slave_plat->cs >= ns->num_cs) { 317 printf("Invalid SPI chipselect\n"); 318 return -EINVAL; 319 } 320 321 return __atcspi200_spi_claim_bus(ns); 322 } 323 324 static int atcspi200_spi_release_bus(struct udevice *dev) 325 { 326 struct nds_spi_slave *ns = dev_get_priv(dev->parent); 327 328 return __atcspi200_spi_release_bus(ns); 329 } 330 331 static int atcspi200_spi_xfer(struct udevice *dev, unsigned int bitlen, 332 const void *dout, void *din, 333 unsigned long flags) 334 { 335 struct udevice *bus = dev->parent; 336 struct nds_spi_slave *ns = dev_get_priv(bus); 337 338 return __atcspi200_spi_xfer(ns, bitlen, dout, din, flags); 339 } 340 341 static int atcspi200_spi_get_clk(struct udevice *bus) 342 { 343 struct nds_spi_slave *ns = dev_get_priv(bus); 344 struct clk clk; 345 ulong clk_rate; 346 int ret; 347 348 ret = clk_get_by_index(bus, 0, &clk); 349 if (ret) 350 return -EINVAL; 351 352 clk_rate = clk_get_rate(&clk); 353 if (!clk_rate) 354 return -EINVAL; 355 356 ns->clock = clk_rate; 357 clk_free(&clk); 358 359 return 0; 360 } 361 362 static int atcspi200_spi_probe(struct udevice *bus) 363 { 364 struct nds_spi_slave *ns = dev_get_priv(bus); 365 366 ns->to = SPI_TIMEOUT; 367 ns->max_transfer_length = MAX_TRANSFER_LEN; 368 ns->mtiming = ns->regs->timing; 369 atcspi200_spi_get_clk(bus); 370 371 return 0; 372 } 373 374 static int atcspi200_ofdata_to_platadata(struct udevice *bus) 375 { 376 struct nds_spi_slave *ns = dev_get_priv(bus); 377 const void *blob = gd->fdt_blob; 378 int node = dev_of_offset(bus); 379 380 ns->regs = map_physmem(devfdt_get_addr(bus), 381 sizeof(struct atcspi200_spi_regs), 382 MAP_NOCACHE); 383 if (!ns->regs) { 384 printf("%s: could not map device address\n", __func__); 385 return -EINVAL; 386 } 387 ns->num_cs = fdtdec_get_int(blob, node, "num-cs", 4); 388 389 return 0; 390 } 391 392 static const struct dm_spi_ops atcspi200_spi_ops = { 393 .claim_bus = atcspi200_spi_claim_bus, 394 .release_bus = atcspi200_spi_release_bus, 395 .xfer = atcspi200_spi_xfer, 396 .set_speed = atcspi200_spi_set_speed, 397 .set_mode = atcspi200_spi_set_mode, 398 }; 399 400 static const struct udevice_id atcspi200_spi_ids[] = { 401 { .compatible = "andestech,atcspi200" }, 402 { } 403 }; 404 405 U_BOOT_DRIVER(atcspi200_spi) = { 406 .name = "atcspi200_spi", 407 .id = UCLASS_SPI, 408 .of_match = atcspi200_spi_ids, 409 .ops = &atcspi200_spi_ops, 410 .ofdata_to_platdata = atcspi200_ofdata_to_platadata, 411 .priv_auto_alloc_size = sizeof(struct nds_spi_slave), 412 .probe = atcspi200_spi_probe, 413 }; 414