brintos

brintos / linux-shallow public Read only

0
0
Text · 10.4 KiB · 23ad124 Raw
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(&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(&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(&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