linux/drivers/spi/spi-fsl-cpm.c
<<
>>
Prefs
   1/*
   2 * Freescale SPI controller driver cpm functions.
   3 *
   4 * Maintainer: Kumar Gala
   5 *
   6 * Copyright (C) 2006 Polycom, Inc.
   7 * Copyright 2010 Freescale Semiconductor, Inc.
   8 *
   9 * CPM SPI and QE buffer descriptors mode support:
  10 * Copyright (c) 2009  MontaVista Software, Inc.
  11 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
  12 *
  13 * This program is free software; you can redistribute  it and/or modify it
  14 * under  the terms of  the GNU General  Public License as published by the
  15 * Free Software Foundation;  either version 2 of the  License, or (at your
  16 * option) any later version.
  17 */
  18#include <asm/cpm.h>
  19#include <soc/fsl/qe/qe.h>
  20#include <linux/dma-mapping.h>
  21#include <linux/fsl_devices.h>
  22#include <linux/kernel.h>
  23#include <linux/module.h>
  24#include <linux/of_address.h>
  25#include <linux/spi/spi.h>
  26#include <linux/types.h>
  27#include <linux/platform_device.h>
  28
  29#include "spi-fsl-cpm.h"
  30#include "spi-fsl-lib.h"
  31#include "spi-fsl-spi.h"
  32
  33/* CPM1 and CPM2 are mutually exclusive. */
  34#ifdef CONFIG_CPM1
  35#include <asm/cpm1.h>
  36#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
  37#else
  38#include <asm/cpm2.h>
  39#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
  40#endif
  41
  42#define SPIE_TXB        0x00000200      /* Last char is written to tx fifo */
  43#define SPIE_RXB        0x00000100      /* Last char is written to rx buf */
  44
  45/* SPCOM register values */
  46#define SPCOM_STR       (1 << 23)       /* Start transmit */
  47
  48#define SPI_PRAM_SIZE   0x100
  49#define SPI_MRBLR       ((unsigned int)PAGE_SIZE)
  50
  51static void *fsl_dummy_rx;
  52static DEFINE_MUTEX(fsl_dummy_rx_lock);
  53static int fsl_dummy_rx_refcnt;
  54
  55void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi)
  56{
  57        if (mspi->flags & SPI_QE) {
  58                qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
  59                             QE_CR_PROTOCOL_UNSPECIFIED, 0);
  60        } else {
  61                if (mspi->flags & SPI_CPM1) {
  62                        out_be32(&mspi->pram->rstate, 0);
  63                        out_be16(&mspi->pram->rbptr,
  64                                 in_be16(&mspi->pram->rbase));
  65                        out_be32(&mspi->pram->tstate, 0);
  66                        out_be16(&mspi->pram->tbptr,
  67                                 in_be16(&mspi->pram->tbase));
  68                } else {
  69                        cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
  70                }
  71        }
  72}
  73EXPORT_SYMBOL_GPL(fsl_spi_cpm_reinit_txrx);
  74
  75static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
  76{
  77        struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
  78        struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
  79        unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
  80        unsigned int xfer_ofs;
  81        struct fsl_spi_reg *reg_base = mspi->reg_base;
  82
  83        xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
  84
  85        if (mspi->rx_dma == mspi->dma_dummy_rx)
  86                out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
  87        else
  88                out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
  89        out_be16(&rx_bd->cbd_datlen, 0);
  90        out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
  91
  92        if (mspi->tx_dma == mspi->dma_dummy_tx)
  93                out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
  94        else
  95                out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
  96        out_be16(&tx_bd->cbd_datlen, xfer_len);
  97        out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
  98                                 BD_SC_LAST);
  99
 100        /* start transfer */
 101        mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
 102}
 103
 104int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
 105                     struct spi_transfer *t, bool is_dma_mapped)
 106{
 107        struct device *dev = mspi->dev;
 108        struct fsl_spi_reg *reg_base = mspi->reg_base;
 109
 110        if (is_dma_mapped) {
 111                mspi->map_tx_dma = 0;
 112                mspi->map_rx_dma = 0;
 113        } else {
 114                mspi->map_tx_dma = 1;
 115                mspi->map_rx_dma = 1;
 116        }
 117
 118        if (!t->tx_buf) {
 119                mspi->tx_dma = mspi->dma_dummy_tx;
 120                mspi->map_tx_dma = 0;
 121        }
 122
 123        if (!t->rx_buf) {
 124                mspi->rx_dma = mspi->dma_dummy_rx;
 125                mspi->map_rx_dma = 0;
 126        }
 127
 128        if (mspi->map_tx_dma) {
 129                void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
 130
 131                mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
 132                                              DMA_TO_DEVICE);
 133                if (dma_mapping_error(dev, mspi->tx_dma)) {
 134                        dev_err(dev, "unable to map tx dma\n");
 135                        return -ENOMEM;
 136                }
 137        } else if (t->tx_buf) {
 138                mspi->tx_dma = t->tx_dma;
 139        }
 140
 141        if (mspi->map_rx_dma) {
 142                mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
 143                                              DMA_FROM_DEVICE);
 144                if (dma_mapping_error(dev, mspi->rx_dma)) {
 145                        dev_err(dev, "unable to map rx dma\n");
 146                        goto err_rx_dma;
 147                }
 148        } else if (t->rx_buf) {
 149                mspi->rx_dma = t->rx_dma;
 150        }
 151
 152        /* enable rx ints */
 153        mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
 154
 155        mspi->xfer_in_progress = t;
 156        mspi->count = t->len;
 157
 158        /* start CPM transfers */
 159        fsl_spi_cpm_bufs_start(mspi);
 160
 161        return 0;
 162
 163err_rx_dma:
 164        if (mspi->map_tx_dma)
 165                dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
 166        return -ENOMEM;
 167}
 168EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs);
 169
 170void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
 171{
 172        struct device *dev = mspi->dev;
 173        struct spi_transfer *t = mspi->xfer_in_progress;
 174
 175        if (mspi->map_tx_dma)
 176                dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
 177        if (mspi->map_rx_dma)
 178                dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
 179        mspi->xfer_in_progress = NULL;
 180}
 181EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);
 182
 183void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 184{
 185        u16 len;
 186        struct fsl_spi_reg *reg_base = mspi->reg_base;
 187
 188        dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
 189                in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
 190
 191        len = in_be16(&mspi->rx_bd->cbd_datlen);
 192        if (len > mspi->count) {
 193                WARN_ON(1);
 194                len = mspi->count;
 195        }
 196
 197        /* Clear the events */
 198        mpc8xxx_spi_write_reg(&reg_base->event, events);
 199
 200        mspi->count -= len;
 201        if (mspi->count)
 202                fsl_spi_cpm_bufs_start(mspi);
 203        else
 204                complete(&mspi->done);
 205}
 206EXPORT_SYMBOL_GPL(fsl_spi_cpm_irq);
 207
 208static void *fsl_spi_alloc_dummy_rx(void)
 209{
 210        mutex_lock(&fsl_dummy_rx_lock);
 211
 212        if (!fsl_dummy_rx)
 213                fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
 214        if (fsl_dummy_rx)
 215                fsl_dummy_rx_refcnt++;
 216
 217        mutex_unlock(&fsl_dummy_rx_lock);
 218
 219        return fsl_dummy_rx;
 220}
 221
 222static void fsl_spi_free_dummy_rx(void)
 223{
 224        mutex_lock(&fsl_dummy_rx_lock);
 225
 226        switch (fsl_dummy_rx_refcnt) {
 227        case 0:
 228                WARN_ON(1);
 229                break;
 230        case 1:
 231                kfree(fsl_dummy_rx);
 232                fsl_dummy_rx = NULL;
 233                /* fall through */
 234        default:
 235                fsl_dummy_rx_refcnt--;
 236                break;
 237        }
 238
 239        mutex_unlock(&fsl_dummy_rx_lock);
 240}
 241
 242static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
 243{
 244        struct device *dev = mspi->dev;
 245        struct device_node *np = dev->of_node;
 246        const u32 *iprop;
 247        int size;
 248        void __iomem *spi_base;
 249        unsigned long pram_ofs = -ENOMEM;
 250
 251        /* Can't use of_address_to_resource(), QE muram isn't at 0. */
 252        iprop = of_get_property(np, "reg", &size);
 253
 254        /* QE with a fixed pram location? */
 255        if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
 256                return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
 257
 258        /* QE but with a dynamic pram location? */
 259        if (mspi->flags & SPI_QE) {
 260                pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
 261                qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
 262                             QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
 263                return pram_ofs;
 264        }
 265
 266        spi_base = of_iomap(np, 1);
 267        if (spi_base == NULL)
 268                return -EINVAL;
 269
 270        if (mspi->flags & SPI_CPM2) {
 271                pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
 272                out_be16(spi_base, pram_ofs);
 273        }
 274
 275        iounmap(spi_base);
 276        return pram_ofs;
 277}
 278
 279int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
 280{
 281        struct device *dev = mspi->dev;
 282        struct device_node *np = dev->of_node;
 283        const u32 *iprop;
 284        int size;
 285        unsigned long bds_ofs;
 286
 287        if (!(mspi->flags & SPI_CPM_MODE))
 288                return 0;
 289
 290        if (!fsl_spi_alloc_dummy_rx())
 291                return -ENOMEM;
 292
 293        if (mspi->flags & SPI_QE) {
 294                iprop = of_get_property(np, "cell-index", &size);
 295                if (iprop && size == sizeof(*iprop))
 296                        mspi->subblock = *iprop;
 297
 298                switch (mspi->subblock) {
 299                default:
 300                        dev_warn(dev, "cell-index unspecified, assuming SPI1\n");
 301                        /* fall through */
 302                case 0:
 303                        mspi->subblock = QE_CR_SUBBLOCK_SPI1;
 304                        break;
 305                case 1:
 306                        mspi->subblock = QE_CR_SUBBLOCK_SPI2;
 307                        break;
 308                }
 309        }
 310
 311        if (mspi->flags & SPI_CPM1) {
 312                struct resource *res;
 313                void *pram;
 314
 315                res = platform_get_resource(to_platform_device(dev),
 316                                            IORESOURCE_MEM, 1);
 317                pram = devm_ioremap_resource(dev, res);
 318                if (IS_ERR(pram))
 319                        mspi->pram = NULL;
 320                else
 321                        mspi->pram = pram;
 322        } else {
 323                unsigned long pram_ofs = fsl_spi_cpm_get_pram(mspi);
 324
 325                if (IS_ERR_VALUE(pram_ofs))
 326                        mspi->pram = NULL;
 327                else
 328                        mspi->pram = cpm_muram_addr(pram_ofs);
 329        }
 330        if (mspi->pram == NULL) {
 331                dev_err(dev, "can't allocate spi parameter ram\n");
 332                goto err_pram;
 333        }
 334
 335        bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
 336                                  sizeof(*mspi->rx_bd), 8);
 337        if (IS_ERR_VALUE(bds_ofs)) {
 338                dev_err(dev, "can't allocate bds\n");
 339                goto err_bds;
 340        }
 341
 342        mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
 343                                            DMA_TO_DEVICE);
 344        if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
 345                dev_err(dev, "unable to map dummy tx buffer\n");
 346                goto err_dummy_tx;
 347        }
 348
 349        mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
 350                                            DMA_FROM_DEVICE);
 351        if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
 352                dev_err(dev, "unable to map dummy rx buffer\n");
 353                goto err_dummy_rx;
 354        }
 355
 356        mspi->tx_bd = cpm_muram_addr(bds_ofs);
 357        mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
 358
 359        /* Initialize parameter ram. */
 360        out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
 361        out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
 362        out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
 363        out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
 364        out_be16(&mspi->pram->mrblr, SPI_MRBLR);
 365        out_be32(&mspi->pram->rstate, 0);
 366        out_be32(&mspi->pram->rdp, 0);
 367        out_be16(&mspi->pram->rbptr, 0);
 368        out_be16(&mspi->pram->rbc, 0);
 369        out_be32(&mspi->pram->rxtmp, 0);
 370        out_be32(&mspi->pram->tstate, 0);
 371        out_be32(&mspi->pram->tdp, 0);
 372        out_be16(&mspi->pram->tbptr, 0);
 373        out_be16(&mspi->pram->tbc, 0);
 374        out_be32(&mspi->pram->txtmp, 0);
 375
 376        return 0;
 377
 378err_dummy_rx:
 379        dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
 380err_dummy_tx:
 381        cpm_muram_free(bds_ofs);
 382err_bds:
 383        if (!(mspi->flags & SPI_CPM1))
 384                cpm_muram_free(cpm_muram_offset(mspi->pram));
 385err_pram:
 386        fsl_spi_free_dummy_rx();
 387        return -ENOMEM;
 388}
 389EXPORT_SYMBOL_GPL(fsl_spi_cpm_init);
 390
 391void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
 392{
 393        struct device *dev = mspi->dev;
 394
 395        if (!(mspi->flags & SPI_CPM_MODE))
 396                return;
 397
 398        dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
 399        dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
 400        cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
 401        cpm_muram_free(cpm_muram_offset(mspi->pram));
 402        fsl_spi_free_dummy_rx();
 403}
 404EXPORT_SYMBOL_GPL(fsl_spi_cpm_free);
 405
 406MODULE_LICENSE("GPL");
 407