Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Freescale SPI controller driver cpm functions.
0004  *
0005  * Maintainer: Kumar Gala
0006  *
0007  * Copyright (C) 2006 Polycom, Inc.
0008  * Copyright 2010 Freescale Semiconductor, Inc.
0009  *
0010  * CPM SPI and QE buffer descriptors mode support:
0011  * Copyright (c) 2009  MontaVista Software, Inc.
0012  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
0013  */
0014 #include <asm/cpm.h>
0015 #include <soc/fsl/qe/qe.h>
0016 #include <linux/dma-mapping.h>
0017 #include <linux/fsl_devices.h>
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/of_address.h>
0021 #include <linux/spi/spi.h>
0022 #include <linux/types.h>
0023 #include <linux/platform_device.h>
0024 
0025 #include "spi-fsl-cpm.h"
0026 #include "spi-fsl-lib.h"
0027 #include "spi-fsl-spi.h"
0028 
0029 /* CPM1 and CPM2 are mutually exclusive. */
0030 #ifdef CONFIG_CPM1
0031 #include <asm/cpm1.h>
0032 #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
0033 #else
0034 #include <asm/cpm2.h>
0035 #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
0036 #endif
0037 
0038 #define SPIE_TXB    0x00000200  /* Last char is written to tx fifo */
0039 #define SPIE_RXB    0x00000100  /* Last char is written to rx buf */
0040 
0041 /* SPCOM register values */
0042 #define SPCOM_STR   (1 << 23)   /* Start transmit */
0043 
0044 #define SPI_PRAM_SIZE   0x100
0045 #define SPI_MRBLR   ((unsigned int)PAGE_SIZE)
0046 
0047 static void *fsl_dummy_rx;
0048 static DEFINE_MUTEX(fsl_dummy_rx_lock);
0049 static int fsl_dummy_rx_refcnt;
0050 
0051 void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi)
0052 {
0053     if (mspi->flags & SPI_QE) {
0054         qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
0055                  QE_CR_PROTOCOL_UNSPECIFIED, 0);
0056     } else {
0057         if (mspi->flags & SPI_CPM1) {
0058             out_be32(&mspi->pram->rstate, 0);
0059             out_be16(&mspi->pram->rbptr,
0060                  in_be16(&mspi->pram->rbase));
0061             out_be32(&mspi->pram->tstate, 0);
0062             out_be16(&mspi->pram->tbptr,
0063                  in_be16(&mspi->pram->tbase));
0064         } else {
0065             cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
0066         }
0067     }
0068 }
0069 EXPORT_SYMBOL_GPL(fsl_spi_cpm_reinit_txrx);
0070 
0071 static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
0072 {
0073     struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
0074     struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
0075     unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
0076     unsigned int xfer_ofs;
0077     struct fsl_spi_reg *reg_base = mspi->reg_base;
0078 
0079     xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
0080 
0081     if (mspi->rx_dma == mspi->dma_dummy_rx)
0082         out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
0083     else
0084         out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
0085     out_be16(&rx_bd->cbd_datlen, 0);
0086     out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
0087 
0088     if (mspi->tx_dma == mspi->dma_dummy_tx)
0089         out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
0090     else
0091         out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
0092     out_be16(&tx_bd->cbd_datlen, xfer_len);
0093     out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
0094                  BD_SC_LAST);
0095 
0096     /* start transfer */
0097     mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
0098 }
0099 
0100 int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
0101              struct spi_transfer *t, bool is_dma_mapped)
0102 {
0103     struct device *dev = mspi->dev;
0104     struct fsl_spi_reg *reg_base = mspi->reg_base;
0105 
0106     if (is_dma_mapped) {
0107         mspi->map_tx_dma = 0;
0108         mspi->map_rx_dma = 0;
0109     } else {
0110         mspi->map_tx_dma = 1;
0111         mspi->map_rx_dma = 1;
0112     }
0113 
0114     if (!t->tx_buf) {
0115         mspi->tx_dma = mspi->dma_dummy_tx;
0116         mspi->map_tx_dma = 0;
0117     }
0118 
0119     if (!t->rx_buf) {
0120         mspi->rx_dma = mspi->dma_dummy_rx;
0121         mspi->map_rx_dma = 0;
0122     }
0123 
0124     if (mspi->map_tx_dma) {
0125         void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
0126 
0127         mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
0128                           DMA_TO_DEVICE);
0129         if (dma_mapping_error(dev, mspi->tx_dma)) {
0130             dev_err(dev, "unable to map tx dma\n");
0131             return -ENOMEM;
0132         }
0133     } else if (t->tx_buf) {
0134         mspi->tx_dma = t->tx_dma;
0135     }
0136 
0137     if (mspi->map_rx_dma) {
0138         mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
0139                           DMA_FROM_DEVICE);
0140         if (dma_mapping_error(dev, mspi->rx_dma)) {
0141             dev_err(dev, "unable to map rx dma\n");
0142             goto err_rx_dma;
0143         }
0144     } else if (t->rx_buf) {
0145         mspi->rx_dma = t->rx_dma;
0146     }
0147 
0148     /* enable rx ints */
0149     mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
0150 
0151     mspi->xfer_in_progress = t;
0152     mspi->count = t->len;
0153 
0154     /* start CPM transfers */
0155     fsl_spi_cpm_bufs_start(mspi);
0156 
0157     return 0;
0158 
0159 err_rx_dma:
0160     if (mspi->map_tx_dma)
0161         dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
0162     return -ENOMEM;
0163 }
0164 EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs);
0165 
0166 void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
0167 {
0168     struct device *dev = mspi->dev;
0169     struct spi_transfer *t = mspi->xfer_in_progress;
0170 
0171     if (mspi->map_tx_dma)
0172         dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
0173     if (mspi->map_rx_dma)
0174         dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
0175     mspi->xfer_in_progress = NULL;
0176 }
0177 EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);
0178 
0179 void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
0180 {
0181     u16 len;
0182     struct fsl_spi_reg *reg_base = mspi->reg_base;
0183 
0184     dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
0185         in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
0186 
0187     len = in_be16(&mspi->rx_bd->cbd_datlen);
0188     if (len > mspi->count) {
0189         WARN_ON(1);
0190         len = mspi->count;
0191     }
0192 
0193     /* Clear the events */
0194     mpc8xxx_spi_write_reg(&reg_base->event, events);
0195 
0196     mspi->count -= len;
0197     if (mspi->count)
0198         fsl_spi_cpm_bufs_start(mspi);
0199     else
0200         complete(&mspi->done);
0201 }
0202 EXPORT_SYMBOL_GPL(fsl_spi_cpm_irq);
0203 
0204 static void *fsl_spi_alloc_dummy_rx(void)
0205 {
0206     mutex_lock(&fsl_dummy_rx_lock);
0207 
0208     if (!fsl_dummy_rx)
0209         fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
0210     if (fsl_dummy_rx)
0211         fsl_dummy_rx_refcnt++;
0212 
0213     mutex_unlock(&fsl_dummy_rx_lock);
0214 
0215     return fsl_dummy_rx;
0216 }
0217 
0218 static void fsl_spi_free_dummy_rx(void)
0219 {
0220     mutex_lock(&fsl_dummy_rx_lock);
0221 
0222     switch (fsl_dummy_rx_refcnt) {
0223     case 0:
0224         WARN_ON(1);
0225         break;
0226     case 1:
0227         kfree(fsl_dummy_rx);
0228         fsl_dummy_rx = NULL;
0229         fallthrough;
0230     default:
0231         fsl_dummy_rx_refcnt--;
0232         break;
0233     }
0234 
0235     mutex_unlock(&fsl_dummy_rx_lock);
0236 }
0237 
0238 static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
0239 {
0240     struct device *dev = mspi->dev;
0241     struct device_node *np = dev->of_node;
0242     const u32 *iprop;
0243     int size;
0244     void __iomem *spi_base;
0245     unsigned long pram_ofs = -ENOMEM;
0246 
0247     /* Can't use of_address_to_resource(), QE muram isn't at 0. */
0248     iprop = of_get_property(np, "reg", &size);
0249 
0250     /* QE with a fixed pram location? */
0251     if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
0252         return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
0253 
0254     /* QE but with a dynamic pram location? */
0255     if (mspi->flags & SPI_QE) {
0256         pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
0257         qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
0258                  QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
0259         return pram_ofs;
0260     }
0261 
0262     spi_base = of_iomap(np, 1);
0263     if (spi_base == NULL)
0264         return -EINVAL;
0265 
0266     if (mspi->flags & SPI_CPM2) {
0267         pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
0268         out_be16(spi_base, pram_ofs);
0269     }
0270 
0271     iounmap(spi_base);
0272     return pram_ofs;
0273 }
0274 
0275 int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
0276 {
0277     struct device *dev = mspi->dev;
0278     struct device_node *np = dev->of_node;
0279     const u32 *iprop;
0280     int size;
0281     unsigned long bds_ofs;
0282 
0283     if (!(mspi->flags & SPI_CPM_MODE))
0284         return 0;
0285 
0286     if (!fsl_spi_alloc_dummy_rx())
0287         return -ENOMEM;
0288 
0289     if (mspi->flags & SPI_QE) {
0290         iprop = of_get_property(np, "cell-index", &size);
0291         if (iprop && size == sizeof(*iprop))
0292             mspi->subblock = *iprop;
0293 
0294         switch (mspi->subblock) {
0295         default:
0296             dev_warn(dev, "cell-index unspecified, assuming SPI1\n");
0297             fallthrough;
0298         case 0:
0299             mspi->subblock = QE_CR_SUBBLOCK_SPI1;
0300             break;
0301         case 1:
0302             mspi->subblock = QE_CR_SUBBLOCK_SPI2;
0303             break;
0304         }
0305     }
0306 
0307     if (mspi->flags & SPI_CPM1) {
0308         void *pram;
0309 
0310         pram = devm_platform_ioremap_resource(to_platform_device(dev),
0311                               1);
0312         if (IS_ERR(pram))
0313             mspi->pram = NULL;
0314         else
0315             mspi->pram = pram;
0316     } else {
0317         unsigned long pram_ofs = fsl_spi_cpm_get_pram(mspi);
0318 
0319         if (IS_ERR_VALUE(pram_ofs))
0320             mspi->pram = NULL;
0321         else
0322             mspi->pram = cpm_muram_addr(pram_ofs);
0323     }
0324     if (mspi->pram == NULL) {
0325         dev_err(dev, "can't allocate spi parameter ram\n");
0326         goto err_pram;
0327     }
0328 
0329     bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
0330                   sizeof(*mspi->rx_bd), 8);
0331     if (IS_ERR_VALUE(bds_ofs)) {
0332         dev_err(dev, "can't allocate bds\n");
0333         goto err_bds;
0334     }
0335 
0336     mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
0337                         DMA_TO_DEVICE);
0338     if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
0339         dev_err(dev, "unable to map dummy tx buffer\n");
0340         goto err_dummy_tx;
0341     }
0342 
0343     mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
0344                         DMA_FROM_DEVICE);
0345     if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
0346         dev_err(dev, "unable to map dummy rx buffer\n");
0347         goto err_dummy_rx;
0348     }
0349 
0350     mspi->tx_bd = cpm_muram_addr(bds_ofs);
0351     mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
0352 
0353     /* Initialize parameter ram. */
0354     out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
0355     out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
0356     out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
0357     out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
0358     out_be16(&mspi->pram->mrblr, SPI_MRBLR);
0359     out_be32(&mspi->pram->rstate, 0);
0360     out_be32(&mspi->pram->rdp, 0);
0361     out_be16(&mspi->pram->rbptr, 0);
0362     out_be16(&mspi->pram->rbc, 0);
0363     out_be32(&mspi->pram->rxtmp, 0);
0364     out_be32(&mspi->pram->tstate, 0);
0365     out_be32(&mspi->pram->tdp, 0);
0366     out_be16(&mspi->pram->tbptr, 0);
0367     out_be16(&mspi->pram->tbc, 0);
0368     out_be32(&mspi->pram->txtmp, 0);
0369 
0370     return 0;
0371 
0372 err_dummy_rx:
0373     dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
0374 err_dummy_tx:
0375     cpm_muram_free(bds_ofs);
0376 err_bds:
0377     if (!(mspi->flags & SPI_CPM1))
0378         cpm_muram_free(cpm_muram_offset(mspi->pram));
0379 err_pram:
0380     fsl_spi_free_dummy_rx();
0381     return -ENOMEM;
0382 }
0383 EXPORT_SYMBOL_GPL(fsl_spi_cpm_init);
0384 
0385 void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
0386 {
0387     struct device *dev = mspi->dev;
0388 
0389     if (!(mspi->flags & SPI_CPM_MODE))
0390         return;
0391 
0392     dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
0393     dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
0394     cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
0395     if (!(mspi->flags & SPI_CPM1))
0396         cpm_muram_free(cpm_muram_offset(mspi->pram));
0397     fsl_spi_free_dummy_rx();
0398 }
0399 EXPORT_SYMBOL_GPL(fsl_spi_cpm_free);
0400 
0401 MODULE_LICENSE("GPL");