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