1 /* 2 * sfc driver for rockchip 3 * 4 * (C) Copyright 2008-2016 Rockchip Electronics 5 * Yifeng.zhao, Software Engineering, <zhao0116@gmail.com>. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <clk.h> 12 #include <dm.h> 13 #include <dt-structs.h> 14 #include <errno.h> 15 #include <spi.h> 16 #include <linux/errno.h> 17 #include <asm/io.h> 18 #include <asm/arch/clock.h> 19 #include <asm/arch/periph.h> 20 #include <dm/pinctrl.h> 21 #include "rockchip_sfc.h" 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 enum rockchip_sfc_if_type { 26 IF_TYPE_STD, 27 IF_TYPE_DUAL, 28 IF_TYPE_QUAD, 29 }; 30 31 struct rockchip_sfc_platdata { 32 s32 frequency; 33 fdt_addr_t base; 34 }; 35 36 struct rockchip_sfc { 37 struct rockchip_sfc_reg *regbase; 38 struct clk clk; 39 unsigned int max_freq; 40 unsigned int mode; 41 unsigned int speed_hz; 42 u32 cmd; 43 u32 addr; 44 u8 addr_bits; 45 u8 dummy_bits; 46 u8 rw; 47 u32 trb; 48 }; 49 50 static int rockchip_sfc_ofdata_to_platdata(struct udevice *bus) 51 { 52 struct rockchip_sfc_platdata *plat = dev_get_platdata(bus); 53 struct rockchip_sfc *sfc = dev_get_priv(bus); 54 const void *blob = gd->fdt_blob; 55 int node = dev_of_offset(bus); 56 int subnode; 57 int ret; 58 59 plat->base = devfdt_get_addr(bus); 60 61 ret = clk_get_by_index(bus, 0, &sfc->clk); 62 if (ret < 0) { 63 debug("Could not get clock for %s: %d\n", bus->name, ret); 64 return ret; 65 } 66 67 subnode = fdt_first_subnode(blob, node); 68 if (subnode < 0) { 69 debug("Error: subnode with SPI flash config missing!\n"); 70 return -ENODEV; 71 } 72 73 plat->frequency = fdtdec_get_int(blob, subnode, "spi-max-frequency", 74 100000000); 75 76 return 0; 77 } 78 79 static int rockchip_sfc_probe(struct udevice *bus) 80 { 81 struct rockchip_sfc_platdata *plat = dev_get_platdata(bus); 82 struct rockchip_sfc *sfc = dev_get_priv(bus); 83 int ret; 84 85 sfc->regbase = (struct rockchip_sfc_reg *)plat->base; 86 87 sfc->max_freq = plat->frequency; 88 89 ret = clk_set_rate(&sfc->clk, sfc->max_freq); 90 if (ret < 0) { 91 debug("%s: Failed to set clock: %d\n", __func__, ret); 92 return ret; 93 } 94 95 return 0; 96 } 97 98 static int rockchip_sfc_reset(struct rockchip_sfc *sfc) 99 { 100 struct rockchip_sfc_reg *regs = sfc->regbase; 101 int tbase = get_timer(0); 102 u32 rcvr; 103 int ret = 0; 104 105 writel(SFC_RESET, ®s->rcvr); 106 do { 107 rcvr = readl(®s->rcvr); 108 if (get_timer(tbase) > 1000) { 109 debug("sfc reset timeout\n"); 110 ret = -ETIMEDOUT; 111 break; 112 } 113 udelay(1); 114 } while (rcvr); 115 116 writel(0xFFFFFFFF, ®s->iclr); 117 118 debug("sfc reset\n"); 119 120 return ret; 121 } 122 123 /* The SFC_CTRL register is a global control register, 124 * when the controller is in busy state(SFC_SR), 125 * SFC_CTRL cannot be set. 126 */ 127 static int rockchip_sfc_wait_idle(struct rockchip_sfc *sfc, 128 u32 timeout_ms) 129 { 130 struct rockchip_sfc_reg *regs = sfc->regbase; 131 unsigned long tbase = get_timer(0); 132 u32 sr, fsr; 133 134 while (1) { 135 sr = readl(®s->sr); 136 fsr = readl(®s->fsr); 137 if ((fsr & SFC_TX_EMPTY) && (fsr & SFC_RX_EMPTY) && !(sr & SFC_BUSY)) 138 break; 139 if (get_timer(tbase) > timeout_ms) { 140 printf("waite sfc idle timeout(sr:0x%08x fsr:0x%08x)\n", 141 sr, fsr); 142 rockchip_sfc_reset(sfc); 143 return -ETIMEDOUT; 144 } 145 udelay(100); 146 } 147 148 return 0; 149 } 150 151 static u8 rockchip_sfc_get_if_type(struct rockchip_sfc *sfc) 152 { 153 int type = IF_TYPE_STD; 154 155 if (sfc->rw == SFC_WR) { 156 if (sfc->mode & SPI_TX_QUAD) 157 type = IF_TYPE_QUAD; 158 else if (sfc->mode & SPI_TX_DUAL) 159 type = IF_TYPE_DUAL; 160 else 161 type = IF_TYPE_STD; 162 } else { 163 if (sfc->mode & SPI_RX_QUAD) 164 type = IF_TYPE_QUAD; 165 else if (sfc->mode & SPI_RX_DUAL) 166 type = IF_TYPE_DUAL; 167 else 168 type = IF_TYPE_STD; 169 } 170 171 return type; 172 } 173 174 static void rockchip_sfc_setup_xfer(struct rockchip_sfc *sfc, u32 trb) 175 { 176 struct rockchip_sfc_reg *regs = sfc->regbase; 177 u32 val = 0x02; 178 u8 data_width = IF_TYPE_STD; 179 180 if (sfc->addr_bits & SFC_ADDR_XBITS) 181 data_width = rockchip_sfc_get_if_type(sfc); 182 183 val |= (data_width << SFC_DATA_WIDTH_SHIFT); 184 185 rockchip_sfc_wait_idle(sfc, 10); 186 187 writel(val, ®s->ctrl); 188 189 val = sfc->cmd; 190 val |= trb << SFC_TRB_SHIFT; 191 val |= sfc->rw << SFC_RW_SHIFT; 192 val |= sfc->addr_bits << SFC_ADDR_BITS_SHIFT; 193 val |= sfc->dummy_bits << SFC_DUMMY_BITS_SHIFT; 194 195 writel(val, ®s->cmd); 196 197 if (sfc->addr_bits & SFC_ADDR_XBITS) 198 writel(sfc->addr, ®s->addr); 199 } 200 201 static int rockchip_sfc_do_dma_xfer(struct rockchip_sfc *sfc, u32 *buffer, u32 trb) 202 { 203 struct rockchip_sfc_reg *regs = sfc->regbase; 204 int timeout = 1000; 205 int ret = 0; 206 int risr; 207 unsigned long tbase; 208 209 rockchip_sfc_setup_xfer(sfc, trb); 210 211 writel(0xFFFFFFFF, ®s->iclr); 212 writel((u32)buffer, ®s->dmaaddr); 213 writel(SFC_DMA_START, ®s->dmatr); 214 215 tbase = get_timer(0); 216 do { 217 udelay(1); 218 risr = readl(®s->risr); 219 if (get_timer(tbase) > timeout) { 220 debug("dma timeout\n"); 221 ret = -ETIMEDOUT; 222 break; 223 } 224 } while (!(risr & TRANS_FINISH_INT)); 225 226 writel(0xFFFFFFFF, ®s->iclr); 227 228 return ret; 229 } 230 231 static int rockchip_sfc_dma_xfer(struct rockchip_sfc *sfc, u32 *buf, u32 len) 232 { 233 u32 trb; 234 int ret = 0; 235 236 while (len) { 237 trb = min(len, (u32)SFC_MAX_TRB); 238 ret = rockchip_sfc_do_dma_xfer(sfc, buf, trb); 239 if (ret < 0) 240 break; 241 len -= trb; 242 sfc->addr += trb; 243 buf += (trb >> 2); 244 } 245 246 return ret; 247 } 248 249 static int rockchip_sfc_wait_fifo_ready(struct rockchip_sfc *sfc, int rw, 250 u32 timeout) 251 { 252 struct rockchip_sfc_reg *regs = sfc->regbase; 253 unsigned long tbase = get_timer(0); 254 u8 level; 255 u32 fsr; 256 257 do { 258 fsr = readl(®s->fsr); 259 if (rw == SFC_WR) 260 level = (fsr & SFC_TXLV_MASK) >> SFC_TXLV_SHIFT; 261 else 262 level = (fsr & SFC_RXLV_MASK) >> SFC_RXLV_SHIFT; 263 if (get_timer(tbase) > timeout) 264 return -ETIMEDOUT; 265 udelay(1); 266 } while (!level); 267 268 return level; 269 } 270 271 static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, u32 *buf, u32 len) 272 { 273 struct rockchip_sfc_reg *regs = sfc->regbase; 274 u32 bytes = len & 0x3; 275 u32 words = len >> 2; 276 int tx_level = 0; 277 u32 val = 0; 278 u8 count; 279 280 while (words) { 281 tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_WR, 1000); 282 if (tx_level <= 0) 283 return tx_level; 284 count = min(words, (u32)tx_level); 285 writesl(®s->data, buf, count); 286 buf += count; 287 words -= count; 288 } 289 290 /* handle the last non 4byte aligned bytes */ 291 if (bytes) { 292 tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_WR, 1000); 293 if (tx_level <= 0) 294 return tx_level; 295 memcpy(&val, buf, bytes); 296 writel(val, ®s->data); 297 } 298 299 return 0; 300 } 301 302 static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u32 *buf, u32 len) 303 { 304 struct rockchip_sfc_reg *regs = sfc->regbase; 305 u32 bytes = len & 0x3; 306 u32 words = len >> 2; 307 int rx_level = 0; 308 u32 count; 309 u32 val; 310 311 while (words) { 312 rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_RD, 1000); 313 if (rx_level <= 0) 314 return rx_level; 315 count = min(words, (u32)rx_level); 316 readsl(®s->data, buf, count); 317 buf += count; 318 words -= count; 319 } 320 321 /* handle the last non 4 bytes aligned bytes */ 322 if (bytes) { 323 rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_RD, 1000); 324 if (rx_level <= 0) 325 return rx_level; 326 val = readl(®s->data); 327 memcpy(buf, &val, bytes); 328 } 329 330 return 0; 331 } 332 333 static int rockchip_sfc_pio_xfer(struct rockchip_sfc *sfc, u32 *buf, u32 len) 334 { 335 int ret = 0; 336 337 rockchip_sfc_setup_xfer(sfc, len); 338 if (len) { 339 if (sfc->rw == SFC_WR) 340 ret = rockchip_sfc_write_fifo(sfc, buf, len); 341 else 342 ret = rockchip_sfc_read_fifo(sfc, buf, len); 343 } 344 345 return ret; 346 } 347 348 static int rockchip_sfc_do_xfer(struct rockchip_sfc *sfc, u32 *buf, u32 len) 349 { 350 int ret = 0; 351 u32 bytes = len & 0x3; 352 u32 dma_trans; 353 354 if (len >= SFC_MAX_TRB) { 355 dma_trans = len - bytes; 356 } else { 357 dma_trans = 0; 358 bytes = len; 359 } 360 361 if (dma_trans) { 362 ret = rockchip_sfc_dma_xfer(sfc, buf, dma_trans); 363 buf += (dma_trans >> 2); 364 } 365 366 /* 367 * transfer the last non 4 bytes anligned byte by pio mode 368 * there are also some commands like WREN(0x06) that execute 369 * whth no data, we also need to handle it here. 370 */ 371 if (bytes || (!bytes && !dma_trans)) 372 ret = rockchip_sfc_pio_xfer(sfc, buf, bytes); 373 374 return ret; 375 } 376 377 static int rockchip_sfc_xfer(struct udevice *dev, unsigned int bitlen, 378 const void *dout, void *din, unsigned long flags) 379 { 380 struct udevice *bus = dev->parent; 381 struct rockchip_sfc *sfc = dev_get_priv(bus); 382 int len = bitlen >> 3; 383 u8 *pcmd = (u8 *)dout; 384 int ret = 0; 385 386 if (flags & SPI_XFER_BEGIN) { 387 sfc->cmd = pcmd[0]; 388 if (len >= 4) { 389 sfc->addr_bits = SFC_ADDR_24BITS; 390 sfc->dummy_bits = (len - 4) << 3; 391 sfc->addr = pcmd[3] | (pcmd[2] << 8) | (pcmd[1] << 16); 392 } else { 393 sfc->addr_bits = 0; 394 sfc->dummy_bits = 0; 395 sfc->addr = 0; 396 } 397 } 398 399 if (flags == (SPI_XFER_BEGIN | SPI_XFER_END)) 400 len = 0; 401 402 if (flags & SPI_XFER_END) { 403 404 if (din) { 405 sfc->rw = SFC_RD; 406 ret = rockchip_sfc_do_xfer(sfc, (u32 *)din, len); 407 } else if (dout) { 408 sfc->rw = SFC_WR; 409 ret = rockchip_sfc_do_xfer(sfc, (u32 *)dout, len); 410 } 411 } 412 413 return ret; 414 } 415 416 static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) 417 { 418 struct rockchip_sfc *sfc = dev_get_priv(bus); 419 420 if (speed > sfc->max_freq) 421 speed = sfc->max_freq; 422 423 sfc->speed_hz = speed; 424 425 return 0; 426 } 427 428 static int rockchip_sfc_set_mode(struct udevice *bus, uint mode) 429 { 430 struct rockchip_sfc *sfc = dev_get_priv(bus); 431 432 sfc->mode = mode; 433 434 return 0; 435 } 436 437 static const struct dm_spi_ops rockchip_sfc_ops = { 438 .xfer = rockchip_sfc_xfer, 439 .set_speed = rockchip_sfc_set_speed, 440 .set_mode = rockchip_sfc_set_mode, 441 }; 442 443 static const struct udevice_id rockchip_sfc_ids[] = { 444 { .compatible = "rockchip,sfc" }, 445 { } 446 }; 447 448 U_BOOT_DRIVER(rockchip_sfc_driver) = { 449 .name = "rockchip_sfc", 450 .id = UCLASS_SPI, 451 .of_match = rockchip_sfc_ids, 452 .ops = &rockchip_sfc_ops, 453 .ofdata_to_platdata = rockchip_sfc_ofdata_to_platdata, 454 .platdata_auto_alloc_size = sizeof(struct rockchip_sfc_platdata), 455 .priv_auto_alloc_size = sizeof(struct rockchip_sfc), 456 .probe = rockchip_sfc_probe, 457 }; 458