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