1 /* 2 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 3 * 4 * Derived from linux/drivers/spi/spi-bcm63xx.c: 5 * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org> 6 * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <clk.h> 13 #include <dm.h> 14 #include <spi.h> 15 #include <reset.h> 16 #include <wait_bit.h> 17 #include <asm/io.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 /* BCM6348 SPI core */ 22 #define SPI_6348_CLK 0x06 23 #define SPI_6348_CMD 0x00 24 #define SPI_6348_CTL 0x40 25 #define SPI_6348_CTL_SHIFT 6 26 #define SPI_6348_FILL 0x07 27 #define SPI_6348_IR_MASK 0x04 28 #define SPI_6348_IR_STAT 0x02 29 #define SPI_6348_RX 0x80 30 #define SPI_6348_RX_SIZE 0x3f 31 #define SPI_6348_TX 0x41 32 #define SPI_6348_TX_SIZE 0x3f 33 34 /* BCM6358 SPI core */ 35 #define SPI_6358_CLK 0x706 36 #define SPI_6358_CMD 0x700 37 #define SPI_6358_CTL 0x000 38 #define SPI_6358_CTL_SHIFT 14 39 #define SPI_6358_FILL 0x707 40 #define SPI_6358_IR_MASK 0x702 41 #define SPI_6358_IR_STAT 0x704 42 #define SPI_6358_RX 0x400 43 #define SPI_6358_RX_SIZE 0x220 44 #define SPI_6358_TX 0x002 45 #define SPI_6358_TX_SIZE 0x21e 46 47 /* SPI Clock register */ 48 #define SPI_CLK_SHIFT 0 49 #define SPI_CLK_20MHZ (0 << SPI_CLK_SHIFT) 50 #define SPI_CLK_0_391MHZ (1 << SPI_CLK_SHIFT) 51 #define SPI_CLK_0_781MHZ (2 << SPI_CLK_SHIFT) 52 #define SPI_CLK_1_563MHZ (3 << SPI_CLK_SHIFT) 53 #define SPI_CLK_3_125MHZ (4 << SPI_CLK_SHIFT) 54 #define SPI_CLK_6_250MHZ (5 << SPI_CLK_SHIFT) 55 #define SPI_CLK_12_50MHZ (6 << SPI_CLK_SHIFT) 56 #define SPI_CLK_25MHZ (7 << SPI_CLK_SHIFT) 57 #define SPI_CLK_MASK (7 << SPI_CLK_SHIFT) 58 #define SPI_CLK_SSOFF_SHIFT 3 59 #define SPI_CLK_SSOFF_2 (2 << SPI_CLK_SSOFF_SHIFT) 60 #define SPI_CLK_SSOFF_MASK (7 << SPI_CLK_SSOFF_SHIFT) 61 #define SPI_CLK_BSWAP_SHIFT 7 62 #define SPI_CLK_BSWAP_MASK (1 << SPI_CLK_BSWAP_SHIFT) 63 64 /* SPI Command register */ 65 #define SPI_CMD_OP_SHIFT 0 66 #define SPI_CMD_OP_START (0x3 << SPI_CMD_OP_SHIFT) 67 #define SPI_CMD_SLAVE_SHIFT 4 68 #define SPI_CMD_SLAVE_MASK (0xf << SPI_CMD_SLAVE_SHIFT) 69 #define SPI_CMD_PREPEND_SHIFT 8 70 #define SPI_CMD_PREPEND_BYTES 0xf 71 #define SPI_CMD_3WIRE_SHIFT 12 72 #define SPI_CMD_3WIRE_MASK (1 << SPI_CMD_3WIRE_SHIFT) 73 74 /* SPI Control register */ 75 #define SPI_CTL_TYPE_FD_RW 0 76 #define SPI_CTL_TYPE_HD_W 1 77 #define SPI_CTL_TYPE_HD_R 2 78 79 /* SPI Interrupt registers */ 80 #define SPI_IR_DONE_SHIFT 0 81 #define SPI_IR_DONE_MASK (1 << SPI_IR_DONE_SHIFT) 82 #define SPI_IR_RXOVER_SHIFT 1 83 #define SPI_IR_RXOVER_MASK (1 << SPI_IR_RXOVER_SHIFT) 84 #define SPI_IR_TXUNDER_SHIFT 2 85 #define SPI_IR_TXUNDER_MASK (1 << SPI_IR_TXUNDER_SHIFT) 86 #define SPI_IR_TXOVER_SHIFT 3 87 #define SPI_IR_TXOVER_MASK (1 << SPI_IR_TXOVER_SHIFT) 88 #define SPI_IR_RXUNDER_SHIFT 4 89 #define SPI_IR_RXUNDER_MASK (1 << SPI_IR_RXUNDER_SHIFT) 90 #define SPI_IR_CLEAR_MASK (SPI_IR_DONE_MASK |\ 91 SPI_IR_RXOVER_MASK |\ 92 SPI_IR_TXUNDER_MASK |\ 93 SPI_IR_TXOVER_MASK |\ 94 SPI_IR_RXUNDER_MASK) 95 96 enum bcm63xx_regs_spi { 97 SPI_CLK, 98 SPI_CMD, 99 SPI_CTL, 100 SPI_CTL_SHIFT, 101 SPI_FILL, 102 SPI_IR_MASK, 103 SPI_IR_STAT, 104 SPI_RX, 105 SPI_RX_SIZE, 106 SPI_TX, 107 SPI_TX_SIZE, 108 }; 109 110 struct bcm63xx_spi_priv { 111 const unsigned long *regs; 112 void __iomem *base; 113 size_t tx_bytes; 114 uint8_t num_cs; 115 }; 116 117 #define SPI_CLK_CNT 8 118 static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = { 119 { 25000000, SPI_CLK_25MHZ }, 120 { 20000000, SPI_CLK_20MHZ }, 121 { 12500000, SPI_CLK_12_50MHZ }, 122 { 6250000, SPI_CLK_6_250MHZ }, 123 { 3125000, SPI_CLK_3_125MHZ }, 124 { 1563000, SPI_CLK_1_563MHZ }, 125 { 781000, SPI_CLK_0_781MHZ }, 126 { 391000, SPI_CLK_0_391MHZ } 127 }; 128 129 static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs, 130 struct spi_cs_info *info) 131 { 132 struct bcm63xx_spi_priv *priv = dev_get_priv(bus); 133 134 if (cs >= priv->num_cs) { 135 printf("no cs %u\n", cs); 136 return -ENODEV; 137 } 138 139 return 0; 140 } 141 142 static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode) 143 { 144 struct bcm63xx_spi_priv *priv = dev_get_priv(bus); 145 const unsigned long *regs = priv->regs; 146 147 if (mode & SPI_LSB_FIRST) 148 setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK); 149 else 150 clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK); 151 152 return 0; 153 } 154 155 static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed) 156 { 157 struct bcm63xx_spi_priv *priv = dev_get_priv(bus); 158 const unsigned long *regs = priv->regs; 159 uint8_t clk_cfg; 160 int i; 161 162 /* default to lowest clock configuration */ 163 clk_cfg = SPI_CLK_0_391MHZ; 164 165 /* find the closest clock configuration */ 166 for (i = 0; i < SPI_CLK_CNT; i++) { 167 if (speed >= bcm63xx_spi_freq_table[i][0]) { 168 clk_cfg = bcm63xx_spi_freq_table[i][1]; 169 break; 170 } 171 } 172 173 /* write clock configuration */ 174 clrsetbits_8(priv->base + regs[SPI_CLK], 175 SPI_CLK_SSOFF_MASK | SPI_CLK_MASK, 176 clk_cfg | SPI_CLK_SSOFF_2); 177 178 return 0; 179 } 180 181 /* 182 * BCM63xx SPI driver doesn't allow keeping CS active between transfers since 183 * they are HW controlled. 184 * However, it provides a mechanism to prepend write transfers prior to read 185 * transfers (with a maximum prepend of 15 bytes), which is usually enough for 186 * SPI-connected flashes since reading requires prepending a write transfer of 187 * 5 bytes. 188 * 189 * This implementation takes advantage of the prepend mechanism and combines 190 * multiple transfers into a single one where possible (single/multiple write 191 * transfer(s) followed by a final read/write transfer). 192 * However, it's not possible to buffer reads, which means that read transfers 193 * should always be done as the final ones. 194 * On the other hand, take into account that combining write transfers into 195 * a single one is just buffering and doesn't require prepend mechanism. 196 */ 197 static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen, 198 const void *dout, void *din, unsigned long flags) 199 { 200 struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent); 201 const unsigned long *regs = priv->regs; 202 size_t data_bytes = bitlen / 8; 203 204 if (flags & SPI_XFER_BEGIN) { 205 /* clear prepends */ 206 priv->tx_bytes = 0; 207 208 /* initialize hardware */ 209 writeb_be(0, priv->base + regs[SPI_IR_MASK]); 210 } 211 212 if (din) { 213 /* buffering reads not possible since cs is hw controlled */ 214 if (!(flags & SPI_XFER_END)) { 215 printf("unable to buffer reads\n"); 216 return -EINVAL; 217 } 218 219 /* check rx size */ 220 if (data_bytes > regs[SPI_RX_SIZE]) { 221 printf("max rx bytes exceeded\n"); 222 return -EMSGSIZE; 223 } 224 } 225 226 if (dout) { 227 /* check tx size */ 228 if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) { 229 printf("max tx bytes exceeded\n"); 230 return -EMSGSIZE; 231 } 232 233 /* copy tx data */ 234 memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes, 235 dout, data_bytes); 236 priv->tx_bytes += data_bytes; 237 } 238 239 if (flags & SPI_XFER_END) { 240 struct dm_spi_slave_platdata *plat = 241 dev_get_parent_platdata(dev); 242 uint16_t val, cmd; 243 int ret; 244 245 /* determine control config */ 246 if (dout && !din) { 247 /* buffered write transfers */ 248 val = priv->tx_bytes; 249 val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]); 250 priv->tx_bytes = 0; 251 } else { 252 if (dout && din && (flags & SPI_XFER_ONCE)) { 253 /* full duplex read/write */ 254 val = data_bytes; 255 val |= (SPI_CTL_TYPE_FD_RW << 256 regs[SPI_CTL_SHIFT]); 257 priv->tx_bytes = 0; 258 } else { 259 /* prepended write transfer */ 260 val = data_bytes; 261 val |= (SPI_CTL_TYPE_HD_R << 262 regs[SPI_CTL_SHIFT]); 263 if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) { 264 printf("max prepend bytes exceeded\n"); 265 return -EMSGSIZE; 266 } 267 } 268 } 269 270 if (regs[SPI_CTL_SHIFT] >= 8) 271 writew_be(val, priv->base + regs[SPI_CTL]); 272 else 273 writeb_be(val, priv->base + regs[SPI_CTL]); 274 275 /* clear interrupts */ 276 writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]); 277 278 /* issue the transfer */ 279 cmd = SPI_CMD_OP_START; 280 cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; 281 cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT); 282 if (plat->mode & SPI_3WIRE) 283 cmd |= SPI_CMD_3WIRE_MASK; 284 writew_be(cmd, priv->base + regs[SPI_CMD]); 285 286 /* enable interrupts */ 287 writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]); 288 289 ret = wait_for_bit_8(priv->base + regs[SPI_IR_STAT], 290 SPI_IR_DONE_MASK, true, 1000, false); 291 if (ret) { 292 printf("interrupt timeout\n"); 293 return ret; 294 } 295 296 /* copy rx data */ 297 if (din) 298 memcpy_fromio(din, priv->base + regs[SPI_RX], 299 data_bytes); 300 } 301 302 return 0; 303 } 304 305 static const struct dm_spi_ops bcm63xx_spi_ops = { 306 .cs_info = bcm63xx_spi_cs_info, 307 .set_mode = bcm63xx_spi_set_mode, 308 .set_speed = bcm63xx_spi_set_speed, 309 .xfer = bcm63xx_spi_xfer, 310 }; 311 312 static const unsigned long bcm6348_spi_regs[] = { 313 [SPI_CLK] = SPI_6348_CLK, 314 [SPI_CMD] = SPI_6348_CMD, 315 [SPI_CTL] = SPI_6348_CTL, 316 [SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT, 317 [SPI_FILL] = SPI_6348_FILL, 318 [SPI_IR_MASK] = SPI_6348_IR_MASK, 319 [SPI_IR_STAT] = SPI_6348_IR_STAT, 320 [SPI_RX] = SPI_6348_RX, 321 [SPI_RX_SIZE] = SPI_6348_RX_SIZE, 322 [SPI_TX] = SPI_6348_TX, 323 [SPI_TX_SIZE] = SPI_6348_TX_SIZE, 324 }; 325 326 static const unsigned long bcm6358_spi_regs[] = { 327 [SPI_CLK] = SPI_6358_CLK, 328 [SPI_CMD] = SPI_6358_CMD, 329 [SPI_CTL] = SPI_6358_CTL, 330 [SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT, 331 [SPI_FILL] = SPI_6358_FILL, 332 [SPI_IR_MASK] = SPI_6358_IR_MASK, 333 [SPI_IR_STAT] = SPI_6358_IR_STAT, 334 [SPI_RX] = SPI_6358_RX, 335 [SPI_RX_SIZE] = SPI_6358_RX_SIZE, 336 [SPI_TX] = SPI_6358_TX, 337 [SPI_TX_SIZE] = SPI_6358_TX_SIZE, 338 }; 339 340 static const struct udevice_id bcm63xx_spi_ids[] = { 341 { 342 .compatible = "brcm,bcm6348-spi", 343 .data = (ulong)&bcm6348_spi_regs, 344 }, { 345 .compatible = "brcm,bcm6358-spi", 346 .data = (ulong)&bcm6358_spi_regs, 347 }, { /* sentinel */ } 348 }; 349 350 static int bcm63xx_spi_child_pre_probe(struct udevice *dev) 351 { 352 struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent); 353 const unsigned long *regs = priv->regs; 354 struct spi_slave *slave = dev_get_parent_priv(dev); 355 struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); 356 357 /* check cs */ 358 if (plat->cs >= priv->num_cs) { 359 printf("no cs %u\n", plat->cs); 360 return -ENODEV; 361 } 362 363 /* max read/write sizes */ 364 slave->max_read_size = regs[SPI_RX_SIZE]; 365 slave->max_write_size = regs[SPI_TX_SIZE]; 366 367 return 0; 368 } 369 370 static int bcm63xx_spi_probe(struct udevice *dev) 371 { 372 struct bcm63xx_spi_priv *priv = dev_get_priv(dev); 373 const unsigned long *regs = 374 (const unsigned long *)dev_get_driver_data(dev); 375 struct reset_ctl rst_ctl; 376 struct clk clk; 377 fdt_addr_t addr; 378 fdt_size_t size; 379 int ret; 380 381 addr = devfdt_get_addr_size_index(dev, 0, &size); 382 if (addr == FDT_ADDR_T_NONE) 383 return -EINVAL; 384 385 priv->regs = regs; 386 priv->base = ioremap(addr, size); 387 priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), 388 "num-cs", 8); 389 390 /* enable clock */ 391 ret = clk_get_by_index(dev, 0, &clk); 392 if (ret < 0) 393 return ret; 394 395 ret = clk_enable(&clk); 396 if (ret < 0) 397 return ret; 398 399 ret = clk_free(&clk); 400 if (ret < 0) 401 return ret; 402 403 /* perform reset */ 404 ret = reset_get_by_index(dev, 0, &rst_ctl); 405 if (ret < 0) 406 return ret; 407 408 ret = reset_deassert(&rst_ctl); 409 if (ret < 0) 410 return ret; 411 412 ret = reset_free(&rst_ctl); 413 if (ret < 0) 414 return ret; 415 416 /* initialize hardware */ 417 writeb_be(0, priv->base + regs[SPI_IR_MASK]); 418 419 /* set fill register */ 420 writeb_be(0xff, priv->base + regs[SPI_FILL]); 421 422 return 0; 423 } 424 425 U_BOOT_DRIVER(bcm63xx_spi) = { 426 .name = "bcm63xx_spi", 427 .id = UCLASS_SPI, 428 .of_match = bcm63xx_spi_ids, 429 .ops = &bcm63xx_spi_ops, 430 .priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv), 431 .child_pre_probe = bcm63xx_spi_child_pre_probe, 432 .probe = bcm63xx_spi_probe, 433 }; 434