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