Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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