linux/drivers/spi/spi-ti-ssp.c
<<
>>
Prefs
   1/*
   2 * Sequencer Serial Port (SSP) based SPI master driver
   3 *
   4 * Copyright (C) 2010 Texas Instruments Inc
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/err.h>
  23#include <linux/completion.h>
  24#include <linux/delay.h>
  25#include <linux/module.h>
  26#include <linux/platform_device.h>
  27#include <linux/spi/spi.h>
  28#include <linux/mfd/ti_ssp.h>
  29
  30#define MODE_BITS       (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
  31
  32struct ti_ssp_spi {
  33        struct spi_master               *master;
  34        struct device                   *dev;
  35        spinlock_t                      lock;
  36        struct list_head                msg_queue;
  37        struct completion               complete;
  38        bool                            shutdown;
  39        struct workqueue_struct         *workqueue;
  40        struct work_struct              work;
  41        u8                              mode, bpw;
  42        int                             cs_active;
  43        u32                             pc_en, pc_dis, pc_wr, pc_rd;
  44        void                            (*select)(int cs);
  45};
  46
  47static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
  48{
  49        u32 ret;
  50
  51        ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
  52        return ret;
  53}
  54
  55static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
  56{
  57        ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
  58}
  59
  60static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
  61                       struct spi_transfer *t)
  62{
  63        int count;
  64
  65        if (hw->bpw <= 8) {
  66                u8              *rx = t->rx_buf;
  67                const u8        *tx = t->tx_buf;
  68
  69                for (count = 0; count < t->len; count += 1) {
  70                        if (t->tx_buf)
  71                                ti_ssp_spi_tx(hw, *tx++);
  72                        if (t->rx_buf)
  73                                *rx++ = ti_ssp_spi_rx(hw);
  74                }
  75        } else if (hw->bpw <= 16) {
  76                u16             *rx = t->rx_buf;
  77                const u16       *tx = t->tx_buf;
  78
  79                for (count = 0; count < t->len; count += 2) {
  80                        if (t->tx_buf)
  81                                ti_ssp_spi_tx(hw, *tx++);
  82                        if (t->rx_buf)
  83                                *rx++ = ti_ssp_spi_rx(hw);
  84                }
  85        } else {
  86                u32             *rx = t->rx_buf;
  87                const u32       *tx = t->tx_buf;
  88
  89                for (count = 0; count < t->len; count += 4) {
  90                        if (t->tx_buf)
  91                                ti_ssp_spi_tx(hw, *tx++);
  92                        if (t->rx_buf)
  93                                *rx++ = ti_ssp_spi_rx(hw);
  94                }
  95        }
  96
  97        msg->actual_length += count; /* bytes transferred */
  98
  99        dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
 100                t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
 101                hw->bpw, count, (count < t->len) ? " (under)" : "");
 102
 103        return (count < t->len) ? -EIO : 0; /* left over data */
 104}
 105
 106static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
 107{
 108        cs_active = !!cs_active;
 109        if (cs_active == hw->cs_active)
 110                return;
 111        ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
 112        hw->cs_active = cs_active;
 113}
 114
 115#define __SHIFT_OUT(bits)       (SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
 116                                 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
 117#define __SHIFT_IN(bits)        (SSP_OPCODE_SHIFT | SSP_IN_MODE  | \
 118                                 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
 119
 120static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
 121{
 122        int error, idx = 0;
 123        u32 seqram[16];
 124        u32 cs_en, cs_dis, clk;
 125        u32 topbits, botbits;
 126
 127        mode &= MODE_BITS;
 128        if (mode == hw->mode && bpw == hw->bpw)
 129                return 0;
 130
 131        cs_en  = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
 132        cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW  : SSP_CS_HIGH;
 133        clk    = (mode & SPI_CPOL)    ? SSP_CLK_HIGH : SSP_CLK_LOW;
 134
 135        /* Construct instructions */
 136
 137        /* Disable Chip Select */
 138        hw->pc_dis = idx;
 139        seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
 140        seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_dis | clk;
 141
 142        /* Enable Chip Select */
 143        hw->pc_en = idx;
 144        seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
 145        seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_en | clk;
 146
 147        /* Reads and writes need to be split for bpw > 16 */
 148        topbits = (bpw > 16) ? 16 : bpw;
 149        botbits = bpw - topbits;
 150
 151        /* Write */
 152        hw->pc_wr = idx;
 153        seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
 154        if (botbits)
 155                seqram[idx++] = __SHIFT_OUT(botbits)  | SSP_DATA_REG;
 156        seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
 157
 158        /* Read */
 159        hw->pc_rd = idx;
 160        if (botbits)
 161                seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
 162        seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
 163        seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
 164
 165        error = ti_ssp_load(hw->dev, 0, seqram, idx);
 166        if (error < 0)
 167                return error;
 168
 169        error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
 170                                          0 : SSP_EARLY_DIN));
 171        if (error < 0)
 172                return error;
 173
 174        hw->bpw = bpw;
 175        hw->mode = mode;
 176
 177        return error;
 178}
 179
 180static void ti_ssp_spi_work(struct work_struct *work)
 181{
 182        struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
 183
 184        spin_lock(&hw->lock);
 185
 186         while (!list_empty(&hw->msg_queue)) {
 187                struct spi_message      *m;
 188                struct spi_device       *spi;
 189                struct spi_transfer     *t = NULL;
 190                int                     status = 0;
 191
 192                m = container_of(hw->msg_queue.next, struct spi_message,
 193                                 queue);
 194
 195                list_del_init(&m->queue);
 196
 197                spin_unlock(&hw->lock);
 198
 199                spi = m->spi;
 200
 201                if (hw->select)
 202                        hw->select(spi->chip_select);
 203
 204                list_for_each_entry(t, &m->transfers, transfer_list) {
 205                        int bpw = spi->bits_per_word;
 206                        int xfer_status;
 207
 208                        if (t->bits_per_word)
 209                                bpw = t->bits_per_word;
 210
 211                        if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
 212                                break;
 213
 214                        ti_ssp_spi_chip_select(hw, 1);
 215
 216                        xfer_status = ti_ssp_spi_txrx(hw, m, t);
 217                        if (xfer_status < 0)
 218                                status = xfer_status;
 219
 220                        if (t->delay_usecs)
 221                                udelay(t->delay_usecs);
 222
 223                        if (t->cs_change)
 224                                ti_ssp_spi_chip_select(hw, 0);
 225                }
 226
 227                ti_ssp_spi_chip_select(hw, 0);
 228                m->status = status;
 229                m->complete(m->context);
 230
 231                spin_lock(&hw->lock);
 232        }
 233
 234        if (hw->shutdown)
 235                complete(&hw->complete);
 236
 237        spin_unlock(&hw->lock);
 238}
 239
 240static int ti_ssp_spi_setup(struct spi_device *spi)
 241{
 242        if (spi->bits_per_word > 32)
 243                return -EINVAL;
 244
 245        return 0;
 246}
 247
 248static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
 249{
 250        struct ti_ssp_spi       *hw;
 251        struct spi_transfer     *t;
 252        int                     error = 0;
 253
 254        m->actual_length = 0;
 255        m->status = -EINPROGRESS;
 256
 257        hw = spi_master_get_devdata(spi->master);
 258
 259        if (list_empty(&m->transfers) || !m->complete)
 260                return -EINVAL;
 261
 262        list_for_each_entry(t, &m->transfers, transfer_list) {
 263                if (t->len && !(t->rx_buf || t->tx_buf)) {
 264                        dev_err(&spi->dev, "invalid xfer, no buffer\n");
 265                        return -EINVAL;
 266                }
 267
 268                if (t->len && t->rx_buf && t->tx_buf) {
 269                        dev_err(&spi->dev, "invalid xfer, full duplex\n");
 270                        return -EINVAL;
 271                }
 272
 273                if (t->bits_per_word > 32) {
 274                        dev_err(&spi->dev, "invalid xfer width %d\n",
 275                                t->bits_per_word);
 276                        return -EINVAL;
 277                }
 278        }
 279
 280        spin_lock(&hw->lock);
 281        if (hw->shutdown) {
 282                error = -ESHUTDOWN;
 283                goto error_unlock;
 284        }
 285        list_add_tail(&m->queue, &hw->msg_queue);
 286        queue_work(hw->workqueue, &hw->work);
 287error_unlock:
 288        spin_unlock(&hw->lock);
 289        return error;
 290}
 291
 292static int ti_ssp_spi_probe(struct platform_device *pdev)
 293{
 294        const struct ti_ssp_spi_data *pdata;
 295        struct ti_ssp_spi *hw;
 296        struct spi_master *master;
 297        struct device *dev = &pdev->dev;
 298        int error = 0;
 299
 300        pdata = dev->platform_data;
 301        if (!pdata) {
 302                dev_err(dev, "platform data not found\n");
 303                return -EINVAL;
 304        }
 305
 306        master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
 307        if (!master) {
 308                dev_err(dev, "cannot allocate SPI master\n");
 309                return -ENOMEM;
 310        }
 311
 312        hw = spi_master_get_devdata(master);
 313        platform_set_drvdata(pdev, hw);
 314
 315        hw->master = master;
 316        hw->dev = dev;
 317        hw->select = pdata->select;
 318
 319        spin_lock_init(&hw->lock);
 320        init_completion(&hw->complete);
 321        INIT_LIST_HEAD(&hw->msg_queue);
 322        INIT_WORK(&hw->work, ti_ssp_spi_work);
 323
 324        hw->workqueue = create_singlethread_workqueue(dev_name(dev));
 325        if (!hw->workqueue) {
 326                error = -ENOMEM;
 327                dev_err(dev, "work queue creation failed\n");
 328                goto error_wq;
 329        }
 330
 331        error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
 332        if (error < 0) {
 333                dev_err(dev, "io setup failed\n");
 334                goto error_iosel;
 335        }
 336
 337        master->bus_num         = pdev->id;
 338        master->num_chipselect  = pdata->num_cs;
 339        master->mode_bits       = MODE_BITS;
 340        master->flags           = SPI_MASTER_HALF_DUPLEX;
 341        master->setup           = ti_ssp_spi_setup;
 342        master->transfer        = ti_ssp_spi_transfer;
 343
 344        error = spi_register_master(master);
 345        if (error) {
 346                dev_err(dev, "master registration failed\n");
 347                goto error_reg;
 348        }
 349
 350        return 0;
 351
 352error_reg:
 353error_iosel:
 354        destroy_workqueue(hw->workqueue);
 355error_wq:
 356        spi_master_put(master);
 357        return error;
 358}
 359
 360static int ti_ssp_spi_remove(struct platform_device *pdev)
 361{
 362        struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
 363        int error;
 364
 365        hw->shutdown = 1;
 366        while (!list_empty(&hw->msg_queue)) {
 367                error = wait_for_completion_interruptible(&hw->complete);
 368                if (error < 0) {
 369                        hw->shutdown = 0;
 370                        return error;
 371                }
 372        }
 373        destroy_workqueue(hw->workqueue);
 374        spi_unregister_master(hw->master);
 375
 376        return 0;
 377}
 378
 379static struct platform_driver ti_ssp_spi_driver = {
 380        .probe          = ti_ssp_spi_probe,
 381        .remove         = ti_ssp_spi_remove,
 382        .driver         = {
 383                .name   = "ti-ssp-spi",
 384                .owner  = THIS_MODULE,
 385        },
 386};
 387module_platform_driver(ti_ssp_spi_driver);
 388
 389MODULE_DESCRIPTION("SSP SPI Master");
 390MODULE_AUTHOR("Cyril Chemparathy");
 391MODULE_LICENSE("GPL");
 392MODULE_ALIAS("platform:ti-ssp-spi");
 393