linux/drivers/spi/spi_s3c24xx.c
<<
>>
Prefs
   1/* linux/drivers/spi/spi_s3c24xx.c
   2 *
   3 * Copyright (c) 2006 Ben Dooks
   4 * Copyright (c) 2006 Simtec Electronics
   5 *      Ben Dooks <ben@simtec.co.uk>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11*/
  12
  13#include <linux/init.h>
  14#include <linux/spinlock.h>
  15#include <linux/workqueue.h>
  16#include <linux/interrupt.h>
  17#include <linux/delay.h>
  18#include <linux/errno.h>
  19#include <linux/err.h>
  20#include <linux/clk.h>
  21#include <linux/platform_device.h>
  22#include <linux/gpio.h>
  23
  24#include <linux/spi/spi.h>
  25#include <linux/spi/spi_bitbang.h>
  26
  27#include <asm/io.h>
  28#include <asm/dma.h>
  29#include <mach/hardware.h>
  30
  31#include <plat/regs-spi.h>
  32#include <mach/spi.h>
  33
  34struct s3c24xx_spi {
  35        /* bitbang has to be first */
  36        struct spi_bitbang       bitbang;
  37        struct completion        done;
  38
  39        void __iomem            *regs;
  40        int                      irq;
  41        int                      len;
  42        int                      count;
  43
  44        void                    (*set_cs)(struct s3c2410_spi_info *spi,
  45                                          int cs, int pol);
  46
  47        /* data buffers */
  48        const unsigned char     *tx;
  49        unsigned char           *rx;
  50
  51        struct clk              *clk;
  52        struct resource         *ioarea;
  53        struct spi_master       *master;
  54        struct spi_device       *curdev;
  55        struct device           *dev;
  56        struct s3c2410_spi_info *pdata;
  57};
  58
  59#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
  60#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
  61
  62static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
  63{
  64        return spi_master_get_devdata(sdev->master);
  65}
  66
  67static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
  68{
  69        gpio_set_value(spi->pin_cs, pol);
  70}
  71
  72static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
  73{
  74        struct s3c24xx_spi *hw = to_hw(spi);
  75        unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
  76        unsigned int spcon;
  77
  78        switch (value) {
  79        case BITBANG_CS_INACTIVE:
  80                hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
  81                break;
  82
  83        case BITBANG_CS_ACTIVE:
  84                spcon = readb(hw->regs + S3C2410_SPCON);
  85
  86                if (spi->mode & SPI_CPHA)
  87                        spcon |= S3C2410_SPCON_CPHA_FMTB;
  88                else
  89                        spcon &= ~S3C2410_SPCON_CPHA_FMTB;
  90
  91                if (spi->mode & SPI_CPOL)
  92                        spcon |= S3C2410_SPCON_CPOL_HIGH;
  93                else
  94                        spcon &= ~S3C2410_SPCON_CPOL_HIGH;
  95
  96                spcon |= S3C2410_SPCON_ENSCK;
  97
  98                /* write new configration */
  99
 100                writeb(spcon, hw->regs + S3C2410_SPCON);
 101                hw->set_cs(hw->pdata, spi->chip_select, cspol);
 102
 103                break;
 104        }
 105}
 106
 107static int s3c24xx_spi_setupxfer(struct spi_device *spi,
 108                                 struct spi_transfer *t)
 109{
 110        struct s3c24xx_spi *hw = to_hw(spi);
 111        unsigned int bpw;
 112        unsigned int hz;
 113        unsigned int div;
 114
 115        bpw = t ? t->bits_per_word : spi->bits_per_word;
 116        hz  = t ? t->speed_hz : spi->max_speed_hz;
 117
 118        if (bpw != 8) {
 119                dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
 120                return -EINVAL;
 121        }
 122
 123        div = clk_get_rate(hw->clk) / hz;
 124
 125        /* is clk = pclk / (2 * (pre+1)), or is it
 126         *    clk = (pclk * 2) / ( pre + 1) */
 127
 128        div /= 2;
 129
 130        if (div > 0)
 131                div -= 1;
 132
 133        if (div > 255)
 134                div = 255;
 135
 136        dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz);
 137        writeb(div, hw->regs + S3C2410_SPPRE);
 138
 139        spin_lock(&hw->bitbang.lock);
 140        if (!hw->bitbang.busy) {
 141                hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
 142                /* need to ndelay for 0.5 clocktick ? */
 143        }
 144        spin_unlock(&hw->bitbang.lock);
 145
 146        return 0;
 147}
 148
 149/* the spi->mode bits understood by this driver: */
 150#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
 151
 152static int s3c24xx_spi_setup(struct spi_device *spi)
 153{
 154        int ret;
 155
 156        if (!spi->bits_per_word)
 157                spi->bits_per_word = 8;
 158
 159        if (spi->mode & ~MODEBITS) {
 160                dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
 161                        spi->mode & ~MODEBITS);
 162                return -EINVAL;
 163        }
 164
 165        ret = s3c24xx_spi_setupxfer(spi, NULL);
 166        if (ret < 0) {
 167                dev_err(&spi->dev, "setupxfer returned %d\n", ret);
 168                return ret;
 169        }
 170
 171        dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n",
 172                __func__, spi->mode, spi->bits_per_word,
 173                spi->max_speed_hz);
 174
 175        return 0;
 176}
 177
 178static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
 179{
 180        return hw->tx ? hw->tx[count] : 0;
 181}
 182
 183static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 184{
 185        struct s3c24xx_spi *hw = to_hw(spi);
 186
 187        dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
 188                t->tx_buf, t->rx_buf, t->len);
 189
 190        hw->tx = t->tx_buf;
 191        hw->rx = t->rx_buf;
 192        hw->len = t->len;
 193        hw->count = 0;
 194
 195        init_completion(&hw->done);
 196
 197        /* send the first byte */
 198        writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
 199
 200        wait_for_completion(&hw->done);
 201
 202        return hw->count;
 203}
 204
 205static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
 206{
 207        struct s3c24xx_spi *hw = dev;
 208        unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
 209        unsigned int count = hw->count;
 210
 211        if (spsta & S3C2410_SPSTA_DCOL) {
 212                dev_dbg(hw->dev, "data-collision\n");
 213                complete(&hw->done);
 214                goto irq_done;
 215        }
 216
 217        if (!(spsta & S3C2410_SPSTA_READY)) {
 218                dev_dbg(hw->dev, "spi not ready for tx?\n");
 219                complete(&hw->done);
 220                goto irq_done;
 221        }
 222
 223        hw->count++;
 224
 225        if (hw->rx)
 226                hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
 227
 228        count++;
 229
 230        if (count < hw->len)
 231                writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
 232        else
 233                complete(&hw->done);
 234
 235 irq_done:
 236        return IRQ_HANDLED;
 237}
 238
 239static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
 240{
 241        /* for the moment, permanently enable the clock */
 242
 243        clk_enable(hw->clk);
 244
 245        /* program defaults into the registers */
 246
 247        writeb(0xff, hw->regs + S3C2410_SPPRE);
 248        writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
 249        writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
 250
 251        if (hw->pdata) {
 252                if (hw->set_cs == s3c24xx_spi_gpiocs)
 253                        gpio_direction_output(hw->pdata->pin_cs, 1);
 254
 255                if (hw->pdata->gpio_setup)
 256                        hw->pdata->gpio_setup(hw->pdata, 1);
 257        }
 258}
 259
 260static int __init s3c24xx_spi_probe(struct platform_device *pdev)
 261{
 262        struct s3c2410_spi_info *pdata;
 263        struct s3c24xx_spi *hw;
 264        struct spi_master *master;
 265        struct resource *res;
 266        int err = 0;
 267
 268        master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
 269        if (master == NULL) {
 270                dev_err(&pdev->dev, "No memory for spi_master\n");
 271                err = -ENOMEM;
 272                goto err_nomem;
 273        }
 274
 275        hw = spi_master_get_devdata(master);
 276        memset(hw, 0, sizeof(struct s3c24xx_spi));
 277
 278        hw->master = spi_master_get(master);
 279        hw->pdata = pdata = pdev->dev.platform_data;
 280        hw->dev = &pdev->dev;
 281
 282        if (pdata == NULL) {
 283                dev_err(&pdev->dev, "No platform data supplied\n");
 284                err = -ENOENT;
 285                goto err_no_pdata;
 286        }
 287
 288        platform_set_drvdata(pdev, hw);
 289        init_completion(&hw->done);
 290
 291        /* setup the master state. */
 292
 293        master->num_chipselect = hw->pdata->num_cs;
 294        master->bus_num = pdata->bus_num;
 295
 296        /* setup the state for the bitbang driver */
 297
 298        hw->bitbang.master         = hw->master;
 299        hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
 300        hw->bitbang.chipselect     = s3c24xx_spi_chipsel;
 301        hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;
 302        hw->bitbang.master->setup  = s3c24xx_spi_setup;
 303
 304        dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
 305
 306        /* find and map our resources */
 307
 308        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 309        if (res == NULL) {
 310                dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
 311                err = -ENOENT;
 312                goto err_no_iores;
 313        }
 314
 315        hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,
 316                                        pdev->name);
 317
 318        if (hw->ioarea == NULL) {
 319                dev_err(&pdev->dev, "Cannot reserve region\n");
 320                err = -ENXIO;
 321                goto err_no_iores;
 322        }
 323
 324        hw->regs = ioremap(res->start, (res->end - res->start)+1);
 325        if (hw->regs == NULL) {
 326                dev_err(&pdev->dev, "Cannot map IO\n");
 327                err = -ENXIO;
 328                goto err_no_iomap;
 329        }
 330
 331        hw->irq = platform_get_irq(pdev, 0);
 332        if (hw->irq < 0) {
 333                dev_err(&pdev->dev, "No IRQ specified\n");
 334                err = -ENOENT;
 335                goto err_no_irq;
 336        }
 337
 338        err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
 339        if (err) {
 340                dev_err(&pdev->dev, "Cannot claim IRQ\n");
 341                goto err_no_irq;
 342        }
 343
 344        hw->clk = clk_get(&pdev->dev, "spi");
 345        if (IS_ERR(hw->clk)) {
 346                dev_err(&pdev->dev, "No clock for device\n");
 347                err = PTR_ERR(hw->clk);
 348                goto err_no_clk;
 349        }
 350
 351        /* setup any gpio we can */
 352
 353        if (!pdata->set_cs) {
 354                if (pdata->pin_cs < 0) {
 355                        dev_err(&pdev->dev, "No chipselect pin\n");
 356                        goto err_register;
 357                }
 358
 359                err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
 360                if (err) {
 361                        dev_err(&pdev->dev, "Failed to get gpio for cs\n");
 362                        goto err_register;
 363                }
 364
 365                hw->set_cs = s3c24xx_spi_gpiocs;
 366                gpio_direction_output(pdata->pin_cs, 1);
 367        } else
 368                hw->set_cs = pdata->set_cs;
 369
 370        s3c24xx_spi_initialsetup(hw);
 371
 372        /* register our spi controller */
 373
 374        err = spi_bitbang_start(&hw->bitbang);
 375        if (err) {
 376                dev_err(&pdev->dev, "Failed to register SPI master\n");
 377                goto err_register;
 378        }
 379
 380        return 0;
 381
 382 err_register:
 383        if (hw->set_cs == s3c24xx_spi_gpiocs)
 384                gpio_free(pdata->pin_cs);
 385
 386        clk_disable(hw->clk);
 387        clk_put(hw->clk);
 388
 389 err_no_clk:
 390        free_irq(hw->irq, hw);
 391
 392 err_no_irq:
 393        iounmap(hw->regs);
 394
 395 err_no_iomap:
 396        release_resource(hw->ioarea);
 397        kfree(hw->ioarea);
 398
 399 err_no_iores:
 400 err_no_pdata:
 401        spi_master_put(hw->master);;
 402
 403 err_nomem:
 404        return err;
 405}
 406
 407static int __exit s3c24xx_spi_remove(struct platform_device *dev)
 408{
 409        struct s3c24xx_spi *hw = platform_get_drvdata(dev);
 410
 411        platform_set_drvdata(dev, NULL);
 412
 413        spi_unregister_master(hw->master);
 414
 415        clk_disable(hw->clk);
 416        clk_put(hw->clk);
 417
 418        free_irq(hw->irq, hw);
 419        iounmap(hw->regs);
 420
 421        if (hw->set_cs == s3c24xx_spi_gpiocs)
 422                gpio_free(hw->pdata->pin_cs);
 423
 424        release_resource(hw->ioarea);
 425        kfree(hw->ioarea);
 426
 427        spi_master_put(hw->master);
 428        return 0;
 429}
 430
 431
 432#ifdef CONFIG_PM
 433
 434static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
 435{
 436        struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
 437
 438        if (hw->pdata && hw->pdata->gpio_setup)
 439                hw->pdata->gpio_setup(hw->pdata, 0);
 440
 441        clk_disable(hw->clk);
 442        return 0;
 443}
 444
 445static int s3c24xx_spi_resume(struct platform_device *pdev)
 446{
 447        struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
 448
 449        s3c24xx_spi_initialsetup(hw);
 450        return 0;
 451}
 452
 453#else
 454#define s3c24xx_spi_suspend NULL
 455#define s3c24xx_spi_resume  NULL
 456#endif
 457
 458MODULE_ALIAS("platform:s3c2410-spi");
 459static struct platform_driver s3c24xx_spi_driver = {
 460        .remove         = __exit_p(s3c24xx_spi_remove),
 461        .suspend        = s3c24xx_spi_suspend,
 462        .resume         = s3c24xx_spi_resume,
 463        .driver         = {
 464                .name   = "s3c2410-spi",
 465                .owner  = THIS_MODULE,
 466        },
 467};
 468
 469static int __init s3c24xx_spi_init(void)
 470{
 471        return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
 472}
 473
 474static void __exit s3c24xx_spi_exit(void)
 475{
 476        platform_driver_unregister(&s3c24xx_spi_driver);
 477}
 478
 479module_init(s3c24xx_spi_init);
 480module_exit(s3c24xx_spi_exit);
 481
 482MODULE_DESCRIPTION("S3C24XX SPI Driver");
 483MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 484MODULE_LICENSE("GPL");
 485