linux/drivers/spi/spi-bcm63xx.c
<<
>>
Prefs
   1/*
   2 * Broadcom BCM63xx SPI controller support
   3 *
   4 * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
   5 * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * as published by the Free Software Foundation; either version 2
  10 * of the License, or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the
  19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  20 */
  21
  22#include <linux/kernel.h>
  23#include <linux/init.h>
  24#include <linux/clk.h>
  25#include <linux/io.h>
  26#include <linux/module.h>
  27#include <linux/platform_device.h>
  28#include <linux/delay.h>
  29#include <linux/interrupt.h>
  30#include <linux/spi/spi.h>
  31#include <linux/completion.h>
  32#include <linux/err.h>
  33#include <linux/workqueue.h>
  34#include <linux/pm_runtime.h>
  35
  36#include <bcm63xx_dev_spi.h>
  37
  38#define PFX             KBUILD_MODNAME
  39
  40struct bcm63xx_spi {
  41        struct completion       done;
  42
  43        void __iomem            *regs;
  44        int                     irq;
  45
  46        /* Platform data */
  47        u32                     speed_hz;
  48        unsigned                fifo_size;
  49        unsigned int            msg_type_shift;
  50        unsigned int            msg_ctl_width;
  51
  52        /* Data buffers */
  53        const unsigned char     *tx_ptr;
  54        unsigned char           *rx_ptr;
  55
  56        /* data iomem */
  57        u8 __iomem              *tx_io;
  58        const u8 __iomem        *rx_io;
  59
  60        int                     remaining_bytes;
  61
  62        struct clk              *clk;
  63        struct platform_device  *pdev;
  64};
  65
  66static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
  67                                unsigned int offset)
  68{
  69        return bcm_readb(bs->regs + bcm63xx_spireg(offset));
  70}
  71
  72static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
  73                                unsigned int offset)
  74{
  75        return bcm_readw(bs->regs + bcm63xx_spireg(offset));
  76}
  77
  78static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
  79                                  u8 value, unsigned int offset)
  80{
  81        bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
  82}
  83
  84static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
  85                                  u16 value, unsigned int offset)
  86{
  87        bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
  88}
  89
  90static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
  91        { 20000000, SPI_CLK_20MHZ },
  92        { 12500000, SPI_CLK_12_50MHZ },
  93        {  6250000, SPI_CLK_6_250MHZ },
  94        {  3125000, SPI_CLK_3_125MHZ },
  95        {  1563000, SPI_CLK_1_563MHZ },
  96        {   781000, SPI_CLK_0_781MHZ },
  97        {   391000, SPI_CLK_0_391MHZ }
  98};
  99
 100static int bcm63xx_spi_check_transfer(struct spi_device *spi,
 101                                        struct spi_transfer *t)
 102{
 103        u8 bits_per_word;
 104
 105        bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
 106        if (bits_per_word != 8) {
 107                dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
 108                        __func__, bits_per_word);
 109                return -EINVAL;
 110        }
 111
 112        if (spi->chip_select > spi->master->num_chipselect) {
 113                dev_err(&spi->dev, "%s, unsupported slave %d\n",
 114                        __func__, spi->chip_select);
 115                return -EINVAL;
 116        }
 117
 118        return 0;
 119}
 120
 121static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
 122                                      struct spi_transfer *t)
 123{
 124        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
 125        u32 hz;
 126        u8 clk_cfg, reg;
 127        int i;
 128
 129        hz = (t) ? t->speed_hz : spi->max_speed_hz;
 130
 131        /* Find the closest clock configuration */
 132        for (i = 0; i < SPI_CLK_MASK; i++) {
 133                if (hz >= bcm63xx_spi_freq_table[i][0]) {
 134                        clk_cfg = bcm63xx_spi_freq_table[i][1];
 135                        break;
 136                }
 137        }
 138
 139        /* No matching configuration found, default to lowest */
 140        if (i == SPI_CLK_MASK)
 141                clk_cfg = SPI_CLK_0_391MHZ;
 142
 143        /* clear existing clock configuration bits of the register */
 144        reg = bcm_spi_readb(bs, SPI_CLK_CFG);
 145        reg &= ~SPI_CLK_MASK;
 146        reg |= clk_cfg;
 147
 148        bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
 149        dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
 150                clk_cfg, hz);
 151}
 152
 153/* the spi->mode bits understood by this driver: */
 154#define MODEBITS (SPI_CPOL | SPI_CPHA)
 155
 156static int bcm63xx_spi_setup(struct spi_device *spi)
 157{
 158        struct bcm63xx_spi *bs;
 159        int ret;
 160
 161        bs = spi_master_get_devdata(spi->master);
 162
 163        if (!spi->bits_per_word)
 164                spi->bits_per_word = 8;
 165
 166        if (spi->mode & ~MODEBITS) {
 167                dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
 168                        __func__, spi->mode & ~MODEBITS);
 169                return -EINVAL;
 170        }
 171
 172        dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
 173                __func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
 174
 175        return 0;
 176}
 177
 178/* Fill the TX FIFO with as many bytes as possible */
 179static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
 180{
 181        u8 size;
 182
 183        /* Fill the Tx FIFO with as many bytes as possible */
 184        size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes :
 185                bs->fifo_size;
 186        memcpy_toio(bs->tx_io, bs->tx_ptr, size);
 187        bs->remaining_bytes -= size;
 188}
 189
 190static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
 191                                        struct spi_transfer *t)
 192{
 193        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
 194        u16 msg_ctl;
 195        u16 cmd;
 196
 197        /* Disable the CMD_DONE interrupt */
 198        bcm_spi_writeb(bs, 0, SPI_INT_MASK);
 199
 200        dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
 201                t->tx_buf, t->rx_buf, t->len);
 202
 203        /* Transmitter is inhibited */
 204        bs->tx_ptr = t->tx_buf;
 205        bs->rx_ptr = t->rx_buf;
 206
 207        if (t->tx_buf) {
 208                bs->remaining_bytes = t->len;
 209                bcm63xx_spi_fill_tx_fifo(bs);
 210        }
 211
 212        init_completion(&bs->done);
 213
 214        /* Fill in the Message control register */
 215        msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
 216
 217        if (t->rx_buf && t->tx_buf)
 218                msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
 219        else if (t->rx_buf)
 220                msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
 221        else if (t->tx_buf)
 222                msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
 223
 224        switch (bs->msg_ctl_width) {
 225        case 8:
 226                bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL);
 227                break;
 228        case 16:
 229                bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
 230                break;
 231        }
 232
 233        /* Issue the transfer */
 234        cmd = SPI_CMD_START_IMMEDIATE;
 235        cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
 236        cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
 237        bcm_spi_writew(bs, cmd, SPI_CMD);
 238
 239        /* Enable the CMD_DONE interrupt */
 240        bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
 241
 242        return t->len - bs->remaining_bytes;
 243}
 244
 245static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
 246{
 247        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 248
 249        pm_runtime_get_sync(&bs->pdev->dev);
 250
 251        return 0;
 252}
 253
 254static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
 255{
 256        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 257
 258        pm_runtime_put(&bs->pdev->dev);
 259
 260        return 0;
 261}
 262
 263static int bcm63xx_spi_transfer_one(struct spi_master *master,
 264                                        struct spi_message *m)
 265{
 266        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 267        struct spi_transfer *t;
 268        struct spi_device *spi = m->spi;
 269        int status = 0;
 270        unsigned int timeout = 0;
 271
 272        list_for_each_entry(t, &m->transfers, transfer_list) {
 273                unsigned int len = t->len;
 274                u8 rx_tail;
 275
 276                status = bcm63xx_spi_check_transfer(spi, t);
 277                if (status < 0)
 278                        goto exit;
 279
 280                /* configure adapter for a new transfer */
 281                bcm63xx_spi_setup_transfer(spi, t);
 282
 283                while (len) {
 284                        /* send the data */
 285                        len -= bcm63xx_txrx_bufs(spi, t);
 286
 287                        timeout = wait_for_completion_timeout(&bs->done, HZ);
 288                        if (!timeout) {
 289                                status = -ETIMEDOUT;
 290                                goto exit;
 291                        }
 292
 293                        /* read out all data */
 294                        rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
 295
 296                        /* Read out all the data */
 297                        if (rx_tail)
 298                                memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
 299                }
 300
 301                m->actual_length += t->len;
 302        }
 303exit:
 304        m->status = status;
 305        spi_finalize_current_message(master);
 306
 307        return 0;
 308}
 309
 310/* This driver supports single master mode only. Hence
 311 * CMD_DONE is the only interrupt we care about
 312 */
 313static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
 314{
 315        struct spi_master *master = (struct spi_master *)dev_id;
 316        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 317        u8 intr;
 318
 319        /* Read interupts and clear them immediately */
 320        intr = bcm_spi_readb(bs, SPI_INT_STATUS);
 321        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
 322        bcm_spi_writeb(bs, 0, SPI_INT_MASK);
 323
 324        /* A transfer completed */
 325        if (intr & SPI_INTR_CMD_DONE)
 326                complete(&bs->done);
 327
 328        return IRQ_HANDLED;
 329}
 330
 331
 332static int bcm63xx_spi_probe(struct platform_device *pdev)
 333{
 334        struct resource *r;
 335        struct device *dev = &pdev->dev;
 336        struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
 337        int irq;
 338        struct spi_master *master;
 339        struct clk *clk;
 340        struct bcm63xx_spi *bs;
 341        int ret;
 342
 343        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 344        if (!r) {
 345                dev_err(dev, "no iomem\n");
 346                ret = -ENXIO;
 347                goto out;
 348        }
 349
 350        irq = platform_get_irq(pdev, 0);
 351        if (irq < 0) {
 352                dev_err(dev, "no irq\n");
 353                ret = -ENXIO;
 354                goto out;
 355        }
 356
 357        clk = clk_get(dev, "spi");
 358        if (IS_ERR(clk)) {
 359                dev_err(dev, "no clock for device\n");
 360                ret = PTR_ERR(clk);
 361                goto out;
 362        }
 363
 364        master = spi_alloc_master(dev, sizeof(*bs));
 365        if (!master) {
 366                dev_err(dev, "out of memory\n");
 367                ret = -ENOMEM;
 368                goto out_clk;
 369        }
 370
 371        bs = spi_master_get_devdata(master);
 372
 373        platform_set_drvdata(pdev, master);
 374        bs->pdev = pdev;
 375
 376        if (!devm_request_mem_region(&pdev->dev, r->start,
 377                                        resource_size(r), PFX)) {
 378                dev_err(dev, "iomem request failed\n");
 379                ret = -ENXIO;
 380                goto out_err;
 381        }
 382
 383        bs->regs = devm_ioremap_nocache(&pdev->dev, r->start,
 384                                                        resource_size(r));
 385        if (!bs->regs) {
 386                dev_err(dev, "unable to ioremap regs\n");
 387                ret = -ENOMEM;
 388                goto out_err;
 389        }
 390
 391        bs->irq = irq;
 392        bs->clk = clk;
 393        bs->fifo_size = pdata->fifo_size;
 394
 395        ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
 396                                                        pdev->name, master);
 397        if (ret) {
 398                dev_err(dev, "unable to request irq\n");
 399                goto out_err;
 400        }
 401
 402        master->bus_num = pdata->bus_num;
 403        master->num_chipselect = pdata->num_chipselect;
 404        master->setup = bcm63xx_spi_setup;
 405        master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
 406        master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
 407        master->transfer_one_message = bcm63xx_spi_transfer_one;
 408        master->mode_bits = MODEBITS;
 409        bs->speed_hz = pdata->speed_hz;
 410        bs->msg_type_shift = pdata->msg_type_shift;
 411        bs->msg_ctl_width = pdata->msg_ctl_width;
 412        bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
 413        bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
 414
 415        switch (bs->msg_ctl_width) {
 416        case 8:
 417        case 16:
 418                break;
 419        default:
 420                dev_err(dev, "unsupported MSG_CTL width: %d\n",
 421                         bs->msg_ctl_width);
 422                goto out_clk_disable;
 423        }
 424
 425        /* Initialize hardware */
 426        clk_enable(bs->clk);
 427        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
 428
 429        /* register and we are done */
 430        ret = spi_register_master(master);
 431        if (ret) {
 432                dev_err(dev, "spi register failed\n");
 433                goto out_clk_disable;
 434        }
 435
 436        dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d)\n",
 437                 r->start, irq, bs->fifo_size);
 438
 439        return 0;
 440
 441out_clk_disable:
 442        clk_disable(clk);
 443out_err:
 444        platform_set_drvdata(pdev, NULL);
 445        spi_master_put(master);
 446out_clk:
 447        clk_put(clk);
 448out:
 449        return ret;
 450}
 451
 452static int bcm63xx_spi_remove(struct platform_device *pdev)
 453{
 454        struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
 455        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 456
 457        spi_unregister_master(master);
 458
 459        /* reset spi block */
 460        bcm_spi_writeb(bs, 0, SPI_INT_MASK);
 461
 462        /* HW shutdown */
 463        clk_disable(bs->clk);
 464        clk_put(bs->clk);
 465
 466        platform_set_drvdata(pdev, 0);
 467
 468        spi_master_put(master);
 469
 470        return 0;
 471}
 472
 473#ifdef CONFIG_PM
 474static int bcm63xx_spi_suspend(struct device *dev)
 475{
 476        struct spi_master *master =
 477                        platform_get_drvdata(to_platform_device(dev));
 478        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 479
 480        spi_master_suspend(master);
 481
 482        clk_disable(bs->clk);
 483
 484        return 0;
 485}
 486
 487static int bcm63xx_spi_resume(struct device *dev)
 488{
 489        struct spi_master *master =
 490                        platform_get_drvdata(to_platform_device(dev));
 491        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 492
 493        clk_enable(bs->clk);
 494
 495        spi_master_resume(master);
 496
 497        return 0;
 498}
 499
 500static const struct dev_pm_ops bcm63xx_spi_pm_ops = {
 501        .suspend        = bcm63xx_spi_suspend,
 502        .resume         = bcm63xx_spi_resume,
 503};
 504
 505#define BCM63XX_SPI_PM_OPS      (&bcm63xx_spi_pm_ops)
 506#else
 507#define BCM63XX_SPI_PM_OPS      NULL
 508#endif
 509
 510static struct platform_driver bcm63xx_spi_driver = {
 511        .driver = {
 512                .name   = "bcm63xx-spi",
 513                .owner  = THIS_MODULE,
 514                .pm     = BCM63XX_SPI_PM_OPS,
 515        },
 516        .probe          = bcm63xx_spi_probe,
 517        .remove         = bcm63xx_spi_remove,
 518};
 519
 520module_platform_driver(bcm63xx_spi_driver);
 521
 522MODULE_ALIAS("platform:bcm63xx_spi");
 523MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
 524MODULE_AUTHOR("Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>");
 525MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver");
 526MODULE_LICENSE("GPL");
 527
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.