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