Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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(&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(&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(&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");