1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2018 Cisco Systems, Inc. 4 * 5 * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org> 6 */ 7 8 #include <asm/io.h> 9 #include <command.h> 10 #include <config.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <fdtdec.h> 14 #include <linux/bitops.h> 15 #include <linux/delay.h> 16 #include <log.h> 17 #include <malloc.h> 18 #include <spi.h> 19 #include <time.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 #define SPBR_MIN 8 24 #define BITS_PER_WORD 8 25 26 #define NUM_TXRAM 32 27 #define NUM_RXRAM 32 28 #define NUM_CDRAM 16 29 30 /* hif_mspi register structure. */ 31 struct bcmstb_hif_mspi_regs { 32 u32 spcr0_lsb; /* 0x000 */ 33 u32 spcr0_msb; /* 0x004 */ 34 u32 spcr1_lsb; /* 0x008 */ 35 u32 spcr1_msb; /* 0x00c */ 36 u32 newqp; /* 0x010 */ 37 u32 endqp; /* 0x014 */ 38 u32 spcr2; /* 0x018 */ 39 u32 reserved0; /* 0x01c */ 40 u32 mspi_status; /* 0x020 */ 41 u32 cptqp; /* 0x024 */ 42 u32 spcr3; /* 0x028 */ 43 u32 revision; /* 0x02c */ 44 u32 reserved1[4]; /* 0x030 */ 45 u32 txram[NUM_TXRAM]; /* 0x040 */ 46 u32 rxram[NUM_RXRAM]; /* 0x0c0 */ 47 u32 cdram[NUM_CDRAM]; /* 0x140 */ 48 u32 write_lock; /* 0x180 */ 49 }; 50 51 /* hif_mspi masks. */ 52 #define HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK 0x00000080 53 #define HIF_MSPI_SPCR2_SPE_MASK 0x00000040 54 #define HIF_MSPI_SPCR2_SPIFIE_MASK 0x00000020 55 #define HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK 0x00000001 56 57 /* bspi offsets. */ 58 #define BSPI_MAST_N_BOOT_CTRL 0x008 59 60 /* bspi_raf is not used in this driver. */ 61 62 /* hif_spi_intr2 offsets and masks. */ 63 #define HIF_SPI_INTR2_CPU_CLEAR 0x08 64 #define HIF_SPI_INTR2_CPU_MASK_SET 0x10 65 #define HIF_SPI_INTR2_CPU_MASK_CLEAR 0x14 66 #define HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK 0x00000020 67 68 /* SPI transfer timeout in milliseconds. */ 69 #define HIF_MSPI_WAIT 10 70 71 enum bcmstb_base_type { 72 HIF_MSPI, 73 BSPI, 74 HIF_SPI_INTR2, 75 CS_REG, 76 BASE_LAST, 77 }; 78 79 struct bcmstb_spi_platdata { 80 void *base[4]; 81 }; 82 83 struct bcmstb_spi_priv { 84 struct bcmstb_hif_mspi_regs *regs; 85 void *bspi; 86 void *hif_spi_intr2; 87 void *cs_reg; 88 int default_cs; 89 int curr_cs; 90 uint tx_slot; 91 uint rx_slot; 92 u8 saved_cmd[NUM_CDRAM]; 93 uint saved_cmd_len; 94 void *saved_din_addr; 95 }; 96 97 static int bcmstb_spi_ofdata_to_platdata(struct udevice *bus) 98 { 99 struct bcmstb_spi_platdata *plat = dev_get_platdata(bus); 100 const void *fdt = gd->fdt_blob; 101 int node = dev_of_offset(bus); 102 int ret = 0; 103 int i = 0; 104 struct fdt_resource resource = { 0 }; 105 char *names[BASE_LAST] = { "hif_mspi", "bspi", "hif_spi_intr2", 106 "cs_reg" }; 107 const phys_addr_t defaults[BASE_LAST] = { BCMSTB_HIF_MSPI_BASE, 108 BCMSTB_BSPI_BASE, 109 BCMSTB_HIF_SPI_INTR2, 110 BCMSTB_CS_REG }; 111 112 for (i = 0; i < BASE_LAST; i++) { 113 plat->base[i] = (void *)defaults[i]; 114 115 ret = fdt_get_named_resource(fdt, node, "reg", "reg-names", 116 names[i], &resource); 117 if (ret) { 118 printf("%s: Assuming BCMSTB SPI %s address 0x0x%p\n", 119 __func__, names[i], (void *)defaults[i]); 120 } else { 121 plat->base[i] = (void *)resource.start; 122 debug("BCMSTB SPI %s address: 0x0x%p\n", 123 names[i], (void *)plat->base[i]); 124 } 125 } 126 127 return 0; 128 } 129 130 static void bcmstb_spi_hw_set_parms(struct bcmstb_spi_priv *priv) 131 { 132 writel(SPBR_MIN, &priv->regs->spcr0_lsb); 133 writel(BITS_PER_WORD << 2 | SPI_MODE_3, &priv->regs->spcr0_msb); 134 } 135 136 static void bcmstb_spi_enable_interrupt(void *base, u32 mask) 137 { 138 void *reg = base + HIF_SPI_INTR2_CPU_MASK_CLEAR; 139 140 writel(readl(reg) | mask, reg); 141 readl(reg); 142 } 143 144 static void bcmstb_spi_disable_interrupt(void *base, u32 mask) 145 { 146 void *reg = base + HIF_SPI_INTR2_CPU_MASK_SET; 147 148 writel(readl(reg) | mask, reg); 149 readl(reg); 150 } 151 152 static void bcmstb_spi_clear_interrupt(void *base, u32 mask) 153 { 154 void *reg = base + HIF_SPI_INTR2_CPU_CLEAR; 155 156 writel(readl(reg) | mask, reg); 157 readl(reg); 158 } 159 160 static int bcmstb_spi_probe(struct udevice *bus) 161 { 162 struct bcmstb_spi_platdata *plat = dev_get_platdata(bus); 163 struct bcmstb_spi_priv *priv = dev_get_priv(bus); 164 165 priv->regs = plat->base[HIF_MSPI]; 166 priv->bspi = plat->base[BSPI]; 167 priv->hif_spi_intr2 = plat->base[HIF_SPI_INTR2]; 168 priv->cs_reg = plat->base[CS_REG]; 169 priv->default_cs = 0; 170 priv->curr_cs = -1; 171 priv->tx_slot = 0; 172 priv->rx_slot = 0; 173 memset(priv->saved_cmd, 0, NUM_CDRAM); 174 priv->saved_cmd_len = 0; 175 priv->saved_din_addr = NULL; 176 177 debug("spi_xfer: tx regs: 0x%p\n", &priv->regs->txram[0]); 178 debug("spi_xfer: rx regs: 0x%p\n", &priv->regs->rxram[0]); 179 180 /* Disable BSPI. */ 181 writel(1, priv->bspi + BSPI_MAST_N_BOOT_CTRL); 182 readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL); 183 184 /* Set up interrupts. */ 185 bcmstb_spi_disable_interrupt(priv->hif_spi_intr2, 0xffffffff); 186 bcmstb_spi_clear_interrupt(priv->hif_spi_intr2, 0xffffffff); 187 bcmstb_spi_enable_interrupt(priv->hif_spi_intr2, 188 HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK); 189 190 /* Set up control registers. */ 191 writel(0, &priv->regs->spcr1_lsb); 192 writel(0, &priv->regs->spcr1_msb); 193 writel(0, &priv->regs->newqp); 194 writel(0, &priv->regs->endqp); 195 writel(HIF_MSPI_SPCR2_SPIFIE_MASK, &priv->regs->spcr2); 196 writel(0, &priv->regs->spcr3); 197 198 bcmstb_spi_hw_set_parms(priv); 199 200 return 0; 201 } 202 203 static void bcmstb_spi_submit(struct bcmstb_spi_priv *priv, bool done) 204 { 205 debug("WR NEWQP: %d\n", 0); 206 writel(0, &priv->regs->newqp); 207 208 debug("WR ENDQP: %d\n", priv->tx_slot - 1); 209 writel(priv->tx_slot - 1, &priv->regs->endqp); 210 211 if (done) { 212 debug("WR CDRAM[%d]: %02x\n", priv->tx_slot - 1, 213 readl(&priv->regs->cdram[priv->tx_slot - 1]) & ~0x80); 214 writel(readl(&priv->regs->cdram[priv->tx_slot - 1]) & ~0x80, 215 &priv->regs->cdram[priv->tx_slot - 1]); 216 } 217 218 /* Force chip select first time. */ 219 if (priv->curr_cs != priv->default_cs) { 220 debug("spi_xfer: switching chip select to %d\n", 221 priv->default_cs); 222 writel((readl(priv->cs_reg) & ~0xff) | (1 << priv->default_cs), 223 priv->cs_reg); 224 readl(priv->cs_reg); 225 udelay(10); 226 priv->curr_cs = priv->default_cs; 227 } 228 229 debug("WR WRITE_LOCK: %02x\n", 1); 230 writel((readl(&priv->regs->write_lock) & 231 ~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 1, 232 &priv->regs->write_lock); 233 readl(&priv->regs->write_lock); 234 235 debug("WR SPCR2: %02x\n", 236 HIF_MSPI_SPCR2_SPIFIE_MASK | 237 HIF_MSPI_SPCR2_SPE_MASK | 238 HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK); 239 writel(HIF_MSPI_SPCR2_SPIFIE_MASK | 240 HIF_MSPI_SPCR2_SPE_MASK | 241 HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK, 242 &priv->regs->spcr2); 243 } 244 245 static int bcmstb_spi_wait(struct bcmstb_spi_priv *priv) 246 { 247 u32 start_time = get_timer(0); 248 u32 status = readl(&priv->regs->mspi_status); 249 250 while (!(status & 1)) { 251 if (get_timer(start_time) > HIF_MSPI_WAIT) 252 return -ETIMEDOUT; 253 status = readl(&priv->regs->mspi_status); 254 } 255 256 writel(readl(&priv->regs->mspi_status) & ~1, &priv->regs->mspi_status); 257 bcmstb_spi_clear_interrupt(priv->hif_spi_intr2, 258 HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK); 259 260 return 0; 261 } 262 263 static int bcmstb_spi_xfer(struct udevice *dev, unsigned int bitlen, 264 const void *dout, void *din, unsigned long flags) 265 { 266 uint len = bitlen / 8; 267 uint tx_len = len; 268 uint rx_len = len; 269 const u8 *out_bytes = (u8 *)dout; 270 u8 *in_bytes = (u8 *)din; 271 struct udevice *bus = dev_get_parent(dev); 272 struct bcmstb_spi_priv *priv = dev_get_priv(bus); 273 struct bcmstb_hif_mspi_regs *regs = priv->regs; 274 275 debug("spi_xfer: %d, t: 0x%p, r: 0x%p, f: %lx\n", 276 len, dout, din, flags); 277 debug("spi_xfer: chip select: %x\n", readl(priv->cs_reg) & 0xff); 278 debug("spi_xfer: tx addr: 0x%p\n", ®s->txram[0]); 279 debug("spi_xfer: rx addr: 0x%p\n", ®s->rxram[0]); 280 debug("spi_xfer: cd addr: 0x%p\n", ®s->cdram[0]); 281 282 if (flags & SPI_XFER_END) { 283 debug("spi_xfer: clearing saved din address: 0x%p\n", 284 priv->saved_din_addr); 285 priv->saved_din_addr = NULL; 286 priv->saved_cmd_len = 0; 287 memset(priv->saved_cmd, 0, NUM_CDRAM); 288 } 289 290 if (bitlen == 0) 291 return 0; 292 293 if (bitlen % 8) { 294 printf("%s: Non-byte-aligned transfer\n", __func__); 295 return -EOPNOTSUPP; 296 } 297 298 if (flags & ~(SPI_XFER_BEGIN | SPI_XFER_END)) { 299 printf("%s: Unsupported flags: %lx\n", __func__, flags); 300 return -EOPNOTSUPP; 301 } 302 303 if (flags & SPI_XFER_BEGIN) { 304 priv->tx_slot = 0; 305 priv->rx_slot = 0; 306 307 if (out_bytes && len > NUM_CDRAM) { 308 printf("%s: Unable to save transfer\n", __func__); 309 return -EOPNOTSUPP; 310 } 311 312 if (out_bytes && !(flags & SPI_XFER_END)) { 313 /* 314 * This is the start of a transmit operation 315 * that will need repeating if the calling 316 * code polls for the result. Save it for 317 * subsequent transmission. 318 */ 319 debug("spi_xfer: saving command: %x, %d\n", 320 out_bytes[0], len); 321 priv->saved_cmd_len = len; 322 memcpy(priv->saved_cmd, out_bytes, priv->saved_cmd_len); 323 } 324 } 325 326 if (!(flags & (SPI_XFER_BEGIN | SPI_XFER_END))) { 327 if (priv->saved_din_addr == din) { 328 /* 329 * The caller is polling for status. Repeat 330 * the last transmission. 331 */ 332 int ret = 0; 333 334 debug("spi_xfer: Making recursive call\n"); 335 ret = bcmstb_spi_xfer(dev, priv->saved_cmd_len * 8, 336 priv->saved_cmd, NULL, 337 SPI_XFER_BEGIN); 338 if (ret) { 339 printf("%s: Recursive call failed\n", __func__); 340 return ret; 341 } 342 } else { 343 debug("spi_xfer: saving din address: 0x%p\n", din); 344 priv->saved_din_addr = din; 345 } 346 } 347 348 while (rx_len > 0) { 349 priv->rx_slot = priv->tx_slot; 350 351 while (priv->tx_slot < NUM_CDRAM && tx_len > 0) { 352 bcmstb_spi_hw_set_parms(priv); 353 debug("WR TXRAM[%d]: %02x\n", priv->tx_slot, 354 out_bytes ? out_bytes[len - tx_len] : 0xff); 355 writel(out_bytes ? out_bytes[len - tx_len] : 0xff, 356 ®s->txram[priv->tx_slot << 1]); 357 debug("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e); 358 writel(0x8e, ®s->cdram[priv->tx_slot]); 359 priv->tx_slot++; 360 tx_len--; 361 if (!in_bytes) 362 rx_len--; 363 } 364 365 debug("spi_xfer: early return clauses: %d, %d, %d\n", 366 len <= NUM_CDRAM, 367 !in_bytes, 368 (flags & (SPI_XFER_BEGIN | 369 SPI_XFER_END)) == SPI_XFER_BEGIN); 370 if (len <= NUM_CDRAM && 371 !in_bytes && 372 (flags & (SPI_XFER_BEGIN | SPI_XFER_END)) == SPI_XFER_BEGIN) 373 return 0; 374 375 bcmstb_spi_submit(priv, tx_len == 0); 376 377 if (bcmstb_spi_wait(priv) == -ETIMEDOUT) { 378 printf("%s: Timed out\n", __func__); 379 return -ETIMEDOUT; 380 } 381 382 priv->tx_slot %= NUM_CDRAM; 383 384 if (in_bytes) { 385 while (priv->rx_slot < NUM_CDRAM && rx_len > 0) { 386 in_bytes[len - rx_len] = 387 readl(®s->rxram[(priv->rx_slot << 1) 388 + 1]) 389 & 0xff; 390 debug("RD RXRAM[%d]: %02x\n", 391 priv->rx_slot, in_bytes[len - rx_len]); 392 priv->rx_slot++; 393 rx_len--; 394 } 395 } 396 } 397 398 if (flags & SPI_XFER_END) { 399 debug("WR WRITE_LOCK: %02x\n", 0); 400 writel((readl(&priv->regs->write_lock) & 401 ~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 0, 402 &priv->regs->write_lock); 403 readl(&priv->regs->write_lock); 404 } 405 406 return 0; 407 } 408 409 static int bcmstb_spi_set_speed(struct udevice *dev, uint speed) 410 { 411 return 0; 412 } 413 414 static int bcmstb_spi_set_mode(struct udevice *dev, uint mode) 415 { 416 return 0; 417 } 418 419 static const struct dm_spi_ops bcmstb_spi_ops = { 420 .xfer = bcmstb_spi_xfer, 421 .set_speed = bcmstb_spi_set_speed, 422 .set_mode = bcmstb_spi_set_mode, 423 }; 424 425 static const struct udevice_id bcmstb_spi_id[] = { 426 { .compatible = "brcm,spi-brcmstb" }, 427 { } 428 }; 429 430 U_BOOT_DRIVER(bcmstb_spi) = { 431 .name = "bcmstb_spi", 432 .id = UCLASS_SPI, 433 .of_match = bcmstb_spi_id, 434 .ops = &bcmstb_spi_ops, 435 .ofdata_to_platdata = bcmstb_spi_ofdata_to_platdata, 436 .probe = bcmstb_spi_probe, 437 .platdata_auto_alloc_size = sizeof(struct bcmstb_spi_platdata), 438 .priv_auto_alloc_size = sizeof(struct bcmstb_spi_priv), 439 }; 440