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