linux/drivers/spi/spi-bcm53xx.c
<<
>>
Prefs
   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");
 365