1#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2 3#include <linux/kernel.h> 4#include <linux/module.h> 5#include <linux/slab.h> 6#include <linux/delay.h> 7#include <linux/bcma/bcma.h> 8#include <linux/spi/spi.h> 9 10#include "spi-bcm53xx.h" 11 12#define BCM53XXSPI_MAX_SPI_BAUD 13500000 /* 216 MHz? */ 13 14/* The longest observed required wait was 19 ms */ 15#define BCM53XXSPI_SPE_TIMEOUT_MS 80 16 17struct bcm53xxspi { 18 struct bcma_device *core; 19 struct spi_master *master; 20 21 size_t read_offset; 22}; 23 24static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset) 25{ 26 return bcma_read32(b53spi->core, offset); 27} 28 29static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset, 30 u32 value) 31{ 32 bcma_write32(b53spi->core, offset, value); 33} 34 35static inline unsigned int bcm53xxspi_calc_timeout(size_t len) 36{ 37 /* Do some magic calculation based on length and buad. Add 10% and 1. */ 38 return (len * 9000 / BCM53XXSPI_MAX_SPI_BAUD * 110 / 100) + 1; 39} 40 41static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms) 42{ 43 unsigned long deadline; 44 u32 tmp; 45 46 /* SPE bit has to be 0 before we read MSPI STATUS */ 47 deadline = jiffies + msecs_to_jiffies(BCM53XXSPI_SPE_TIMEOUT_MS); 48 do { 49 tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); 50 if (!(tmp & B53SPI_MSPI_SPCR2_SPE)) 51 break; 52 udelay(5); 53 } while (!time_after_eq(jiffies, deadline)); 54 55 if (tmp & B53SPI_MSPI_SPCR2_SPE) 56 goto spi_timeout; 57 58 /* Check status */ 59 deadline = jiffies + msecs_to_jiffies(timeout_ms); 60 do { 61 tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS); 62 if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) { 63 bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0); 64 return 0; 65 } 66 67 cpu_relax(); 68 udelay(100); 69 } while (!time_after_eq(jiffies, deadline)); 70 71spi_timeout: 72 bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0); 73 74 pr_err("Timeout waiting for SPI to be ready!\n"); 75 76 return -EBUSY; 77} 78 79static void bcm53xxspi_buf_write(struct bcm53xxspi *b53spi, u8 *w_buf, 80 size_t len, bool cont) 81{ 82 u32 tmp; 83 int i; 84 85 for (i = 0; i < len; i++) { 86 /* Transmit Register File MSB */ 87 bcm53xxspi_write(b53spi, B53SPI_MSPI_TXRAM + 4 * (i * 2), 88 (unsigned int)w_buf[i]); 89 } 90 91 for (i = 0; i < len; i++) { 92 tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | 93 B53SPI_CDRAM_PCS_DSCK; 94 if (!cont && i == len - 1) 95 tmp &= ~B53SPI_CDRAM_CONT; 96 tmp &= ~0x1; 97 /* Command Register File */ 98 bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp); 99 } 100 101 /* Set queue pointers */ 102 bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); 103 bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); 104 105 if (cont) 106 bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); 107 108 /* Start SPI transfer */ 109 tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); 110 tmp |= B53SPI_MSPI_SPCR2_SPE; 111 if (cont) 112 tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD; 113 bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp); 114 115 /* Wait for SPI to finish */ 116 bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len)); 117 118 if (!cont) 119 bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); 120 121 b53spi->read_offset = len; 122} 123 124static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, 125 size_t len, bool cont) 126{ 127 u32 tmp; 128 int i; 129 130 for (i = 0; i < b53spi->read_offset + len; i++) { 131 tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | 132 B53SPI_CDRAM_PCS_DSCK; 133 if (!cont && i == b53spi->read_offset + len - 1) 134 tmp &= ~B53SPI_CDRAM_CONT; 135 tmp &= ~0x1; 136 /* Command Register File */ 137 bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp); 138 } 139 140 /* Set queue pointers */ 141 bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); 142 bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, 143 b53spi->read_offset + len - 1); 144 145 if (cont) 146 bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); 147 148 /* Start SPI transfer */ 149 tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); 150 tmp |= B53SPI_MSPI_SPCR2_SPE; 151 if (cont) 152 tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD; 153 bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp); 154 155 /* Wait for SPI to finish */ 156 bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len)); 157 158 if (!cont) 159 bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); 160 161 for (i = 0; i < len; ++i) { 162 int offset = b53spi->read_offset + i; 163 164 /* Data stored in the transmit register file LSB */ 165 r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); 166 } 167 168 b53spi->read_offset = 0; 169} 170 171static int bcm53xxspi_transfer_one(struct spi_master *master, 172 struct spi_device *spi, 173 struct spi_transfer *t) 174{ 175 struct bcm53xxspi *b53spi = spi_master_get_devdata(master); 176 u8 *buf; 177 size_t left; 178 179 if (t->tx_buf) { 180 buf = (u8 *)t->tx_buf; 181 left = t->len; 182 while (left) { 183 size_t to_write = min_t(size_t, 16, left); 184 bool cont = left - to_write > 0; 185 186 bcm53xxspi_buf_write(b53spi, buf, to_write, cont); 187 left -= to_write; 188 buf += to_write; 189 } 190 } 191 192 if (t->rx_buf) { 193 buf = (u8 *)t->rx_buf; 194 left = t->len; 195 while (left) { 196 size_t to_read = min_t(size_t, 16 - b53spi->read_offset, 197 left); 198 bool cont = left - to_read > 0; 199 200 bcm53xxspi_buf_read(b53spi, buf, to_read, cont); 201 left -= to_read; 202 buf += to_read; 203 } 204 } 205 206 return 0; 207} 208 209/************************************************** 210 * BCMA 211 **************************************************/ 212 213static struct spi_board_info bcm53xx_info = { 214 .modalias = "bcm53xxspiflash", 215}; 216 217static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { 218 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), 219 {}, 220}; 221MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl); 222 223static int bcm53xxspi_bcma_probe(struct bcma_device *core) 224{ 225 struct bcm53xxspi *b53spi; 226 struct spi_master *master; 227 int err; 228 229 if (core->bus->drv_cc.core->id.rev != 42) { 230 pr_err("SPI on SoC with unsupported ChipCommon rev\n"); 231 return -ENOTSUPP; 232 } 233 234 master = spi_alloc_master(&core->dev, sizeof(*b53spi)); 235 if (!master) 236 return -ENOMEM; 237 238 b53spi = spi_master_get_devdata(master); 239 b53spi->master = master; 240 b53spi->core = core; 241 242 master->transfer_one = bcm53xxspi_transfer_one; 243 244 bcma_set_drvdata(core, b53spi); 245 246 err = devm_spi_register_master(&core->dev, master); 247 if (err) { 248 spi_master_put(master); 249 bcma_set_drvdata(core, NULL); 250 goto out; 251 } 252 253 /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */ 254 spi_new_device(master, &bcm53xx_info); 255 256out: 257 return err; 258} 259 260static void bcm53xxspi_bcma_remove(struct bcma_device *core) 261{ 262 struct bcm53xxspi *b53spi = bcma_get_drvdata(core); 263 264 spi_unregister_master(b53spi->master); 265} 266 267static struct bcma_driver bcm53xxspi_bcma_driver = { 268 .name = KBUILD_MODNAME, 269 .id_table = bcm53xxspi_bcma_tbl, 270 .probe = bcm53xxspi_bcma_probe, 271 .remove = bcm53xxspi_bcma_remove, 272}; 273 274/************************************************** 275 * Init & exit 276 **************************************************/ 277 278static int __init bcm53xxspi_module_init(void) 279{ 280 int err = 0; 281 282 err = bcma_driver_register(&bcm53xxspi_bcma_driver); 283 if (err) 284 pr_err("Failed to register bcma driver: %d\n", err); 285 286 return err; 287} 288 289static void __exit bcm53xxspi_module_exit(void) 290{ 291 bcma_driver_unregister(&bcm53xxspi_bcma_driver); 292} 293 294module_init(bcm53xxspi_module_init); 295module_exit(bcm53xxspi_module_exit); 296 297MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver"); 298MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>"); 299MODULE_LICENSE("GPL"); 300