xref: /rk3399_rockchip-uboot/drivers/spi/spi-mem.c (revision 305d7e6eb355be2c9fdd766a19e8873f59ce6378)
1967efcaeSBoris Brezillon // SPDX-License-Identifier: GPL-2.0+
2967efcaeSBoris Brezillon /*
3967efcaeSBoris Brezillon  * Copyright (C) 2018 Exceet Electronics GmbH
4967efcaeSBoris Brezillon  * Copyright (C) 2018 Bootlin
5967efcaeSBoris Brezillon  *
6967efcaeSBoris Brezillon  * Author: Boris Brezillon <boris.brezillon@bootlin.com>
7967efcaeSBoris Brezillon  */
8967efcaeSBoris Brezillon 
9967efcaeSBoris Brezillon #ifndef __UBOOT__
10967efcaeSBoris Brezillon #include <linux/dmaengine.h>
11967efcaeSBoris Brezillon #include <linux/pm_runtime.h>
12967efcaeSBoris Brezillon #include "internals.h"
13967efcaeSBoris Brezillon #else
14967efcaeSBoris Brezillon #include <spi.h>
15967efcaeSBoris Brezillon #include <spi-mem.h>
16967efcaeSBoris Brezillon #endif
17967efcaeSBoris Brezillon 
18967efcaeSBoris Brezillon #ifndef __UBOOT__
19967efcaeSBoris Brezillon /**
20967efcaeSBoris Brezillon  * spi_controller_dma_map_mem_op_data() - DMA-map the buffer attached to a
21967efcaeSBoris Brezillon  *					  memory operation
22967efcaeSBoris Brezillon  * @ctlr: the SPI controller requesting this dma_map()
23967efcaeSBoris Brezillon  * @op: the memory operation containing the buffer to map
24967efcaeSBoris Brezillon  * @sgt: a pointer to a non-initialized sg_table that will be filled by this
25967efcaeSBoris Brezillon  *	 function
26967efcaeSBoris Brezillon  *
27967efcaeSBoris Brezillon  * Some controllers might want to do DMA on the data buffer embedded in @op.
28967efcaeSBoris Brezillon  * This helper prepares everything for you and provides a ready-to-use
29967efcaeSBoris Brezillon  * sg_table. This function is not intended to be called from spi drivers.
30967efcaeSBoris Brezillon  * Only SPI controller drivers should use it.
31967efcaeSBoris Brezillon  * Note that the caller must ensure the memory region pointed by
32967efcaeSBoris Brezillon  * op->data.buf.{in,out} is DMA-able before calling this function.
33967efcaeSBoris Brezillon  *
34967efcaeSBoris Brezillon  * Return: 0 in case of success, a negative error code otherwise.
35967efcaeSBoris Brezillon  */
spi_controller_dma_map_mem_op_data(struct spi_controller * ctlr,const struct spi_mem_op * op,struct sg_table * sgt)36967efcaeSBoris Brezillon int spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr,
37967efcaeSBoris Brezillon 				       const struct spi_mem_op *op,
38967efcaeSBoris Brezillon 				       struct sg_table *sgt)
39967efcaeSBoris Brezillon {
40967efcaeSBoris Brezillon 	struct device *dmadev;
41967efcaeSBoris Brezillon 
42967efcaeSBoris Brezillon 	if (!op->data.nbytes)
43967efcaeSBoris Brezillon 		return -EINVAL;
44967efcaeSBoris Brezillon 
45967efcaeSBoris Brezillon 	if (op->data.dir == SPI_MEM_DATA_OUT && ctlr->dma_tx)
46967efcaeSBoris Brezillon 		dmadev = ctlr->dma_tx->device->dev;
47967efcaeSBoris Brezillon 	else if (op->data.dir == SPI_MEM_DATA_IN && ctlr->dma_rx)
48967efcaeSBoris Brezillon 		dmadev = ctlr->dma_rx->device->dev;
49967efcaeSBoris Brezillon 	else
50967efcaeSBoris Brezillon 		dmadev = ctlr->dev.parent;
51967efcaeSBoris Brezillon 
52967efcaeSBoris Brezillon 	if (!dmadev)
53967efcaeSBoris Brezillon 		return -EINVAL;
54967efcaeSBoris Brezillon 
55967efcaeSBoris Brezillon 	return spi_map_buf(ctlr, dmadev, sgt, op->data.buf.in, op->data.nbytes,
56967efcaeSBoris Brezillon 			   op->data.dir == SPI_MEM_DATA_IN ?
57967efcaeSBoris Brezillon 			   DMA_FROM_DEVICE : DMA_TO_DEVICE);
58967efcaeSBoris Brezillon }
59967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_controller_dma_map_mem_op_data);
60967efcaeSBoris Brezillon 
61967efcaeSBoris Brezillon /**
62967efcaeSBoris Brezillon  * spi_controller_dma_unmap_mem_op_data() - DMA-unmap the buffer attached to a
63967efcaeSBoris Brezillon  *					    memory operation
64967efcaeSBoris Brezillon  * @ctlr: the SPI controller requesting this dma_unmap()
65967efcaeSBoris Brezillon  * @op: the memory operation containing the buffer to unmap
66967efcaeSBoris Brezillon  * @sgt: a pointer to an sg_table previously initialized by
67967efcaeSBoris Brezillon  *	 spi_controller_dma_map_mem_op_data()
68967efcaeSBoris Brezillon  *
69967efcaeSBoris Brezillon  * Some controllers might want to do DMA on the data buffer embedded in @op.
70967efcaeSBoris Brezillon  * This helper prepares things so that the CPU can access the
71967efcaeSBoris Brezillon  * op->data.buf.{in,out} buffer again.
72967efcaeSBoris Brezillon  *
73967efcaeSBoris Brezillon  * This function is not intended to be called from SPI drivers. Only SPI
74967efcaeSBoris Brezillon  * controller drivers should use it.
75967efcaeSBoris Brezillon  *
76967efcaeSBoris Brezillon  * This function should be called after the DMA operation has finished and is
77967efcaeSBoris Brezillon  * only valid if the previous spi_controller_dma_map_mem_op_data() call
78967efcaeSBoris Brezillon  * returned 0.
79967efcaeSBoris Brezillon  *
80967efcaeSBoris Brezillon  * Return: 0 in case of success, a negative error code otherwise.
81967efcaeSBoris Brezillon  */
spi_controller_dma_unmap_mem_op_data(struct spi_controller * ctlr,const struct spi_mem_op * op,struct sg_table * sgt)82967efcaeSBoris Brezillon void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
83967efcaeSBoris Brezillon 					  const struct spi_mem_op *op,
84967efcaeSBoris Brezillon 					  struct sg_table *sgt)
85967efcaeSBoris Brezillon {
86967efcaeSBoris Brezillon 	struct device *dmadev;
87967efcaeSBoris Brezillon 
88967efcaeSBoris Brezillon 	if (!op->data.nbytes)
89967efcaeSBoris Brezillon 		return;
90967efcaeSBoris Brezillon 
91967efcaeSBoris Brezillon 	if (op->data.dir == SPI_MEM_DATA_OUT && ctlr->dma_tx)
92967efcaeSBoris Brezillon 		dmadev = ctlr->dma_tx->device->dev;
93967efcaeSBoris Brezillon 	else if (op->data.dir == SPI_MEM_DATA_IN && ctlr->dma_rx)
94967efcaeSBoris Brezillon 		dmadev = ctlr->dma_rx->device->dev;
95967efcaeSBoris Brezillon 	else
96967efcaeSBoris Brezillon 		dmadev = ctlr->dev.parent;
97967efcaeSBoris Brezillon 
98967efcaeSBoris Brezillon 	spi_unmap_buf(ctlr, dmadev, sgt,
99967efcaeSBoris Brezillon 		      op->data.dir == SPI_MEM_DATA_IN ?
100967efcaeSBoris Brezillon 		      DMA_FROM_DEVICE : DMA_TO_DEVICE);
101967efcaeSBoris Brezillon }
102967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_controller_dma_unmap_mem_op_data);
103967efcaeSBoris Brezillon #endif /* __UBOOT__ */
104967efcaeSBoris Brezillon 
spi_check_buswidth_req(struct spi_slave * slave,u8 buswidth,bool tx)105967efcaeSBoris Brezillon static int spi_check_buswidth_req(struct spi_slave *slave, u8 buswidth, bool tx)
106967efcaeSBoris Brezillon {
107967efcaeSBoris Brezillon 	u32 mode = slave->mode;
108967efcaeSBoris Brezillon 
109967efcaeSBoris Brezillon 	switch (buswidth) {
110967efcaeSBoris Brezillon 	case 1:
111967efcaeSBoris Brezillon 		return 0;
112967efcaeSBoris Brezillon 
113967efcaeSBoris Brezillon 	case 2:
114967efcaeSBoris Brezillon 		if ((tx && (mode & (SPI_TX_DUAL | SPI_TX_QUAD))) ||
115967efcaeSBoris Brezillon 		    (!tx && (mode & (SPI_RX_DUAL | SPI_RX_QUAD))))
116967efcaeSBoris Brezillon 			return 0;
117967efcaeSBoris Brezillon 
118967efcaeSBoris Brezillon 		break;
119967efcaeSBoris Brezillon 
120967efcaeSBoris Brezillon 	case 4:
121967efcaeSBoris Brezillon 		if ((tx && (mode & SPI_TX_QUAD)) ||
122967efcaeSBoris Brezillon 		    (!tx && (mode & SPI_RX_QUAD)))
123967efcaeSBoris Brezillon 			return 0;
124967efcaeSBoris Brezillon 
125967efcaeSBoris Brezillon 		break;
126*305d7e6eSVignesh Raghavendra 	case 8:
127*305d7e6eSVignesh Raghavendra 		if ((tx && (mode & SPI_TX_OCTAL)) ||
128*305d7e6eSVignesh Raghavendra 		    (!tx && (mode & SPI_RX_OCTAL)))
129*305d7e6eSVignesh Raghavendra 			return 0;
130*305d7e6eSVignesh Raghavendra 
131*305d7e6eSVignesh Raghavendra 		break;
132967efcaeSBoris Brezillon 
133967efcaeSBoris Brezillon 	default:
134967efcaeSBoris Brezillon 		break;
135967efcaeSBoris Brezillon 	}
136967efcaeSBoris Brezillon 
137967efcaeSBoris Brezillon 	return -ENOTSUPP;
138967efcaeSBoris Brezillon }
139967efcaeSBoris Brezillon 
spi_mem_default_supports_op(struct spi_slave * slave,const struct spi_mem_op * op)140967efcaeSBoris Brezillon bool spi_mem_default_supports_op(struct spi_slave *slave,
141967efcaeSBoris Brezillon 				 const struct spi_mem_op *op)
142967efcaeSBoris Brezillon {
143967efcaeSBoris Brezillon 	if (spi_check_buswidth_req(slave, op->cmd.buswidth, true))
144967efcaeSBoris Brezillon 		return false;
145967efcaeSBoris Brezillon 
146967efcaeSBoris Brezillon 	if (op->addr.nbytes &&
147967efcaeSBoris Brezillon 	    spi_check_buswidth_req(slave, op->addr.buswidth, true))
148967efcaeSBoris Brezillon 		return false;
149967efcaeSBoris Brezillon 
150967efcaeSBoris Brezillon 	if (op->dummy.nbytes &&
151967efcaeSBoris Brezillon 	    spi_check_buswidth_req(slave, op->dummy.buswidth, true))
152967efcaeSBoris Brezillon 		return false;
153967efcaeSBoris Brezillon 
154967efcaeSBoris Brezillon 	if (op->data.nbytes &&
155967efcaeSBoris Brezillon 	    spi_check_buswidth_req(slave, op->data.buswidth,
156967efcaeSBoris Brezillon 				   op->data.dir == SPI_MEM_DATA_OUT))
157967efcaeSBoris Brezillon 		return false;
158967efcaeSBoris Brezillon 
159967efcaeSBoris Brezillon 	return true;
160967efcaeSBoris Brezillon }
161967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
162967efcaeSBoris Brezillon 
163967efcaeSBoris Brezillon /**
164967efcaeSBoris Brezillon  * spi_mem_supports_op() - Check if a memory device and the controller it is
165967efcaeSBoris Brezillon  *			   connected to support a specific memory operation
166967efcaeSBoris Brezillon  * @slave: the SPI device
167967efcaeSBoris Brezillon  * @op: the memory operation to check
168967efcaeSBoris Brezillon  *
169967efcaeSBoris Brezillon  * Some controllers are only supporting Single or Dual IOs, others might only
170967efcaeSBoris Brezillon  * support specific opcodes, or it can even be that the controller and device
171967efcaeSBoris Brezillon  * both support Quad IOs but the hardware prevents you from using it because
172967efcaeSBoris Brezillon  * only 2 IO lines are connected.
173967efcaeSBoris Brezillon  *
174967efcaeSBoris Brezillon  * This function checks whether a specific operation is supported.
175967efcaeSBoris Brezillon  *
176967efcaeSBoris Brezillon  * Return: true if @op is supported, false otherwise.
177967efcaeSBoris Brezillon  */
spi_mem_supports_op(struct spi_slave * slave,const struct spi_mem_op * op)178967efcaeSBoris Brezillon bool spi_mem_supports_op(struct spi_slave *slave,
179967efcaeSBoris Brezillon 			 const struct spi_mem_op *op)
180967efcaeSBoris Brezillon {
181967efcaeSBoris Brezillon 	struct udevice *bus = slave->dev->parent;
182967efcaeSBoris Brezillon 	struct dm_spi_ops *ops = spi_get_ops(bus);
183967efcaeSBoris Brezillon 
184967efcaeSBoris Brezillon 	if (ops->mem_ops && ops->mem_ops->supports_op)
185967efcaeSBoris Brezillon 		return ops->mem_ops->supports_op(slave, op);
186967efcaeSBoris Brezillon 
187967efcaeSBoris Brezillon 	return spi_mem_default_supports_op(slave, op);
188967efcaeSBoris Brezillon }
189967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_mem_supports_op);
190967efcaeSBoris Brezillon 
191967efcaeSBoris Brezillon /**
192967efcaeSBoris Brezillon  * spi_mem_exec_op() - Execute a memory operation
193967efcaeSBoris Brezillon  * @slave: the SPI device
194967efcaeSBoris Brezillon  * @op: the memory operation to execute
195967efcaeSBoris Brezillon  *
196967efcaeSBoris Brezillon  * Executes a memory operation.
197967efcaeSBoris Brezillon  *
198967efcaeSBoris Brezillon  * This function first checks that @op is supported and then tries to execute
199967efcaeSBoris Brezillon  * it.
200967efcaeSBoris Brezillon  *
201967efcaeSBoris Brezillon  * Return: 0 in case of success, a negative error code otherwise.
202967efcaeSBoris Brezillon  */
spi_mem_exec_op(struct spi_slave * slave,const struct spi_mem_op * op)203967efcaeSBoris Brezillon int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
204967efcaeSBoris Brezillon {
205967efcaeSBoris Brezillon 	struct udevice *bus = slave->dev->parent;
206967efcaeSBoris Brezillon 	struct dm_spi_ops *ops = spi_get_ops(bus);
207967efcaeSBoris Brezillon 	unsigned int pos = 0;
208967efcaeSBoris Brezillon 	const u8 *tx_buf = NULL;
209967efcaeSBoris Brezillon 	u8 *rx_buf = NULL;
210967efcaeSBoris Brezillon 	int op_len;
211967efcaeSBoris Brezillon 	u32 flag;
212967efcaeSBoris Brezillon 	int ret;
213967efcaeSBoris Brezillon 	int i;
214967efcaeSBoris Brezillon 
215967efcaeSBoris Brezillon 	if (!spi_mem_supports_op(slave, op))
216967efcaeSBoris Brezillon 		return -ENOTSUPP;
217967efcaeSBoris Brezillon 
21883e21979SVignesh R 	ret = spi_claim_bus(slave);
21983e21979SVignesh R 	if (ret < 0)
22083e21979SVignesh R 		return ret;
22183e21979SVignesh R 
2223dc0a5efSBernhard Messerklinger 	if (ops->mem_ops && ops->mem_ops->exec_op) {
223967efcaeSBoris Brezillon #ifndef __UBOOT__
224967efcaeSBoris Brezillon 		/*
225967efcaeSBoris Brezillon 		 * Flush the message queue before executing our SPI memory
226967efcaeSBoris Brezillon 		 * operation to prevent preemption of regular SPI transfers.
227967efcaeSBoris Brezillon 		 */
228967efcaeSBoris Brezillon 		spi_flush_queue(ctlr);
229967efcaeSBoris Brezillon 
230967efcaeSBoris Brezillon 		if (ctlr->auto_runtime_pm) {
231967efcaeSBoris Brezillon 			ret = pm_runtime_get_sync(ctlr->dev.parent);
232967efcaeSBoris Brezillon 			if (ret < 0) {
233967efcaeSBoris Brezillon 				dev_err(&ctlr->dev,
234967efcaeSBoris Brezillon 					"Failed to power device: %d\n",
235967efcaeSBoris Brezillon 					ret);
236967efcaeSBoris Brezillon 				return ret;
237967efcaeSBoris Brezillon 			}
238967efcaeSBoris Brezillon 		}
239967efcaeSBoris Brezillon 
240967efcaeSBoris Brezillon 		mutex_lock(&ctlr->bus_lock_mutex);
241967efcaeSBoris Brezillon 		mutex_lock(&ctlr->io_mutex);
242967efcaeSBoris Brezillon #endif
243967efcaeSBoris Brezillon 		ret = ops->mem_ops->exec_op(slave, op);
24483e21979SVignesh R 
245967efcaeSBoris Brezillon #ifndef __UBOOT__
246967efcaeSBoris Brezillon 		mutex_unlock(&ctlr->io_mutex);
247967efcaeSBoris Brezillon 		mutex_unlock(&ctlr->bus_lock_mutex);
248967efcaeSBoris Brezillon 
249967efcaeSBoris Brezillon 		if (ctlr->auto_runtime_pm)
250967efcaeSBoris Brezillon 			pm_runtime_put(ctlr->dev.parent);
251967efcaeSBoris Brezillon #endif
252967efcaeSBoris Brezillon 
253967efcaeSBoris Brezillon 		/*
254967efcaeSBoris Brezillon 		 * Some controllers only optimize specific paths (typically the
255967efcaeSBoris Brezillon 		 * read path) and expect the core to use the regular SPI
256967efcaeSBoris Brezillon 		 * interface in other cases.
257967efcaeSBoris Brezillon 		 */
25883e21979SVignesh R 		if (!ret || ret != -ENOTSUPP) {
25983e21979SVignesh R 			spi_release_bus(slave);
260967efcaeSBoris Brezillon 			return ret;
261967efcaeSBoris Brezillon 		}
26283e21979SVignesh R 	}
263967efcaeSBoris Brezillon 
264967efcaeSBoris Brezillon #ifndef __UBOOT__
265967efcaeSBoris Brezillon 	tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
266967efcaeSBoris Brezillon 		     op->dummy.nbytes;
267967efcaeSBoris Brezillon 
268967efcaeSBoris Brezillon 	/*
269967efcaeSBoris Brezillon 	 * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
270967efcaeSBoris Brezillon 	 * we're guaranteed that this buffer is DMA-able, as required by the
271967efcaeSBoris Brezillon 	 * SPI layer.
272967efcaeSBoris Brezillon 	 */
273967efcaeSBoris Brezillon 	tmpbuf = kzalloc(tmpbufsize, GFP_KERNEL | GFP_DMA);
274967efcaeSBoris Brezillon 	if (!tmpbuf)
275967efcaeSBoris Brezillon 		return -ENOMEM;
276967efcaeSBoris Brezillon 
277967efcaeSBoris Brezillon 	spi_message_init(&msg);
278967efcaeSBoris Brezillon 
279967efcaeSBoris Brezillon 	tmpbuf[0] = op->cmd.opcode;
280967efcaeSBoris Brezillon 	xfers[xferpos].tx_buf = tmpbuf;
281967efcaeSBoris Brezillon 	xfers[xferpos].len = sizeof(op->cmd.opcode);
282967efcaeSBoris Brezillon 	xfers[xferpos].tx_nbits = op->cmd.buswidth;
283967efcaeSBoris Brezillon 	spi_message_add_tail(&xfers[xferpos], &msg);
284967efcaeSBoris Brezillon 	xferpos++;
285967efcaeSBoris Brezillon 	totalxferlen++;
286967efcaeSBoris Brezillon 
287967efcaeSBoris Brezillon 	if (op->addr.nbytes) {
288967efcaeSBoris Brezillon 		int i;
289967efcaeSBoris Brezillon 
290967efcaeSBoris Brezillon 		for (i = 0; i < op->addr.nbytes; i++)
291967efcaeSBoris Brezillon 			tmpbuf[i + 1] = op->addr.val >>
292967efcaeSBoris Brezillon 					(8 * (op->addr.nbytes - i - 1));
293967efcaeSBoris Brezillon 
294967efcaeSBoris Brezillon 		xfers[xferpos].tx_buf = tmpbuf + 1;
295967efcaeSBoris Brezillon 		xfers[xferpos].len = op->addr.nbytes;
296967efcaeSBoris Brezillon 		xfers[xferpos].tx_nbits = op->addr.buswidth;
297967efcaeSBoris Brezillon 		spi_message_add_tail(&xfers[xferpos], &msg);
298967efcaeSBoris Brezillon 		xferpos++;
299967efcaeSBoris Brezillon 		totalxferlen += op->addr.nbytes;
300967efcaeSBoris Brezillon 	}
301967efcaeSBoris Brezillon 
302967efcaeSBoris Brezillon 	if (op->dummy.nbytes) {
303967efcaeSBoris Brezillon 		memset(tmpbuf + op->addr.nbytes + 1, 0xff, op->dummy.nbytes);
304967efcaeSBoris Brezillon 		xfers[xferpos].tx_buf = tmpbuf + op->addr.nbytes + 1;
305967efcaeSBoris Brezillon 		xfers[xferpos].len = op->dummy.nbytes;
306967efcaeSBoris Brezillon 		xfers[xferpos].tx_nbits = op->dummy.buswidth;
307967efcaeSBoris Brezillon 		spi_message_add_tail(&xfers[xferpos], &msg);
308967efcaeSBoris Brezillon 		xferpos++;
309967efcaeSBoris Brezillon 		totalxferlen += op->dummy.nbytes;
310967efcaeSBoris Brezillon 	}
311967efcaeSBoris Brezillon 
312967efcaeSBoris Brezillon 	if (op->data.nbytes) {
313967efcaeSBoris Brezillon 		if (op->data.dir == SPI_MEM_DATA_IN) {
314967efcaeSBoris Brezillon 			xfers[xferpos].rx_buf = op->data.buf.in;
315967efcaeSBoris Brezillon 			xfers[xferpos].rx_nbits = op->data.buswidth;
316967efcaeSBoris Brezillon 		} else {
317967efcaeSBoris Brezillon 			xfers[xferpos].tx_buf = op->data.buf.out;
318967efcaeSBoris Brezillon 			xfers[xferpos].tx_nbits = op->data.buswidth;
319967efcaeSBoris Brezillon 		}
320967efcaeSBoris Brezillon 
321967efcaeSBoris Brezillon 		xfers[xferpos].len = op->data.nbytes;
322967efcaeSBoris Brezillon 		spi_message_add_tail(&xfers[xferpos], &msg);
323967efcaeSBoris Brezillon 		xferpos++;
324967efcaeSBoris Brezillon 		totalxferlen += op->data.nbytes;
325967efcaeSBoris Brezillon 	}
326967efcaeSBoris Brezillon 
327967efcaeSBoris Brezillon 	ret = spi_sync(slave, &msg);
328967efcaeSBoris Brezillon 
329967efcaeSBoris Brezillon 	kfree(tmpbuf);
330967efcaeSBoris Brezillon 
331967efcaeSBoris Brezillon 	if (ret)
332967efcaeSBoris Brezillon 		return ret;
333967efcaeSBoris Brezillon 
334967efcaeSBoris Brezillon 	if (msg.actual_length != totalxferlen)
335967efcaeSBoris Brezillon 		return -EIO;
336967efcaeSBoris Brezillon #else
337967efcaeSBoris Brezillon 
338967efcaeSBoris Brezillon 	if (op->data.nbytes) {
339967efcaeSBoris Brezillon 		if (op->data.dir == SPI_MEM_DATA_IN)
340967efcaeSBoris Brezillon 			rx_buf = op->data.buf.in;
341967efcaeSBoris Brezillon 		else
342967efcaeSBoris Brezillon 			tx_buf = op->data.buf.out;
343967efcaeSBoris Brezillon 	}
344967efcaeSBoris Brezillon 
345967efcaeSBoris Brezillon 	op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
3466cc5f5ccSSimon Glass 
3476cc5f5ccSSimon Glass 	/*
3486cc5f5ccSSimon Glass 	 * Avoid using malloc() here so that we can use this code in SPL where
3496cc5f5ccSSimon Glass 	 * simple malloc may be used. That implementation does not allow free()
3506cc5f5ccSSimon Glass 	 * so repeated calls to this code can exhaust the space.
3516cc5f5ccSSimon Glass 	 *
3526cc5f5ccSSimon Glass 	 * The value of op_len is small, since it does not include the actual
3536cc5f5ccSSimon Glass 	 * data being sent, only the op-code and address. In fact, it should be
3546cc5f5ccSSimon Glass 	 * possible to just use a small fixed value here instead of op_len.
3556cc5f5ccSSimon Glass 	 */
3566cc5f5ccSSimon Glass 	u8 op_buf[op_len];
357967efcaeSBoris Brezillon 
358967efcaeSBoris Brezillon 	op_buf[pos++] = op->cmd.opcode;
359967efcaeSBoris Brezillon 
360967efcaeSBoris Brezillon 	if (op->addr.nbytes) {
361967efcaeSBoris Brezillon 		for (i = 0; i < op->addr.nbytes; i++)
362967efcaeSBoris Brezillon 			op_buf[pos + i] = op->addr.val >>
363967efcaeSBoris Brezillon 				(8 * (op->addr.nbytes - i - 1));
364967efcaeSBoris Brezillon 
365967efcaeSBoris Brezillon 		pos += op->addr.nbytes;
366967efcaeSBoris Brezillon 	}
367967efcaeSBoris Brezillon 
368967efcaeSBoris Brezillon 	if (op->dummy.nbytes)
369967efcaeSBoris Brezillon 		memset(op_buf + pos, 0xff, op->dummy.nbytes);
370967efcaeSBoris Brezillon 
371967efcaeSBoris Brezillon 	/* 1st transfer: opcode + address + dummy cycles */
372967efcaeSBoris Brezillon 	flag = SPI_XFER_BEGIN;
373967efcaeSBoris Brezillon 	/* Make sure to set END bit if no tx or rx data messages follow */
374967efcaeSBoris Brezillon 	if (!tx_buf && !rx_buf)
375967efcaeSBoris Brezillon 		flag |= SPI_XFER_END;
376967efcaeSBoris Brezillon 
377967efcaeSBoris Brezillon 	ret = spi_xfer(slave, op_len * 8, op_buf, NULL, flag);
378967efcaeSBoris Brezillon 	if (ret)
379967efcaeSBoris Brezillon 		return ret;
380967efcaeSBoris Brezillon 
381967efcaeSBoris Brezillon 	/* 2nd transfer: rx or tx data path */
382967efcaeSBoris Brezillon 	if (tx_buf || rx_buf) {
383f5a32af5SJon Lin 		flag = SPI_XFER_END;
384f5a32af5SJon Lin 		if (slave->mode & SPI_DMA_PREPARE)
385f5a32af5SJon Lin 			flag |= SPI_XFER_PREPARE;
386f5a32af5SJon Lin 
387967efcaeSBoris Brezillon 		ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf,
388f5a32af5SJon Lin 			       rx_buf, flag);
389967efcaeSBoris Brezillon 		if (ret)
390967efcaeSBoris Brezillon 			return ret;
391967efcaeSBoris Brezillon 	}
392967efcaeSBoris Brezillon 
393967efcaeSBoris Brezillon 	spi_release_bus(slave);
394967efcaeSBoris Brezillon 
395967efcaeSBoris Brezillon 	for (i = 0; i < pos; i++)
396967efcaeSBoris Brezillon 		debug("%02x ", op_buf[i]);
397967efcaeSBoris Brezillon 	debug("| [%dB %s] ",
398967efcaeSBoris Brezillon 	      tx_buf || rx_buf ? op->data.nbytes : 0,
399967efcaeSBoris Brezillon 	      tx_buf || rx_buf ? (tx_buf ? "out" : "in") : "-");
400967efcaeSBoris Brezillon 	for (i = 0; i < op->data.nbytes; i++)
401967efcaeSBoris Brezillon 		debug("%02x ", tx_buf ? tx_buf[i] : rx_buf[i]);
402967efcaeSBoris Brezillon 	debug("[ret %d]\n", ret);
403967efcaeSBoris Brezillon 
404967efcaeSBoris Brezillon 	if (ret < 0)
405967efcaeSBoris Brezillon 		return ret;
406967efcaeSBoris Brezillon #endif /* __UBOOT__ */
407967efcaeSBoris Brezillon 
408967efcaeSBoris Brezillon 	return 0;
409967efcaeSBoris Brezillon }
410967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_mem_exec_op);
411967efcaeSBoris Brezillon 
412967efcaeSBoris Brezillon /**
413967efcaeSBoris Brezillon  * spi_mem_adjust_op_size() - Adjust the data size of a SPI mem operation to
414967efcaeSBoris Brezillon  *				 match controller limitations
415967efcaeSBoris Brezillon  * @slave: the SPI device
416967efcaeSBoris Brezillon  * @op: the operation to adjust
417967efcaeSBoris Brezillon  *
418967efcaeSBoris Brezillon  * Some controllers have FIFO limitations and must split a data transfer
419967efcaeSBoris Brezillon  * operation into multiple ones, others require a specific alignment for
420967efcaeSBoris Brezillon  * optimized accesses. This function allows SPI mem drivers to split a single
421967efcaeSBoris Brezillon  * operation into multiple sub-operations when required.
422967efcaeSBoris Brezillon  *
423967efcaeSBoris Brezillon  * Return: a negative error code if the controller can't properly adjust @op,
424967efcaeSBoris Brezillon  *	   0 otherwise. Note that @op->data.nbytes will be updated if @op
425967efcaeSBoris Brezillon  *	   can't be handled in a single step.
426967efcaeSBoris Brezillon  */
spi_mem_adjust_op_size(struct spi_slave * slave,struct spi_mem_op * op)427967efcaeSBoris Brezillon int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op)
428967efcaeSBoris Brezillon {
429967efcaeSBoris Brezillon 	struct udevice *bus = slave->dev->parent;
430967efcaeSBoris Brezillon 	struct dm_spi_ops *ops = spi_get_ops(bus);
431967efcaeSBoris Brezillon 
432967efcaeSBoris Brezillon 	if (ops->mem_ops && ops->mem_ops->adjust_op_size)
433967efcaeSBoris Brezillon 		return ops->mem_ops->adjust_op_size(slave, op);
434967efcaeSBoris Brezillon 
4353e37766eSVignesh R 	if (!ops->mem_ops || !ops->mem_ops->exec_op) {
4363e37766eSVignesh R 		unsigned int len;
4373e37766eSVignesh R 
4383e37766eSVignesh R 		len = sizeof(op->cmd.opcode) + op->addr.nbytes +
4393e37766eSVignesh R 			op->dummy.nbytes;
4403e37766eSVignesh R 		if (slave->max_write_size && len > slave->max_write_size)
4413e37766eSVignesh R 			return -EINVAL;
4423e37766eSVignesh R 
4433e37766eSVignesh R 		if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size)
4443e37766eSVignesh R 			op->data.nbytes = min(op->data.nbytes,
4453e37766eSVignesh R 					      slave->max_read_size);
4463e37766eSVignesh R 		else if (slave->max_write_size)
4473e37766eSVignesh R 			op->data.nbytes = min(op->data.nbytes,
4483e37766eSVignesh R 					      slave->max_write_size - len);
4493e37766eSVignesh R 
4503e37766eSVignesh R 		if (!op->data.nbytes)
4513e37766eSVignesh R 			return -EINVAL;
4523e37766eSVignesh R 	}
4533e37766eSVignesh R 
454967efcaeSBoris Brezillon 	return 0;
455967efcaeSBoris Brezillon }
456967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size);
457967efcaeSBoris Brezillon 
458967efcaeSBoris Brezillon #ifndef __UBOOT__
to_spi_mem_drv(struct device_driver * drv)459967efcaeSBoris Brezillon static inline struct spi_mem_driver *to_spi_mem_drv(struct device_driver *drv)
460967efcaeSBoris Brezillon {
461967efcaeSBoris Brezillon 	return container_of(drv, struct spi_mem_driver, spidrv.driver);
462967efcaeSBoris Brezillon }
463967efcaeSBoris Brezillon 
spi_mem_probe(struct spi_device * spi)464967efcaeSBoris Brezillon static int spi_mem_probe(struct spi_device *spi)
465967efcaeSBoris Brezillon {
466967efcaeSBoris Brezillon 	struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver);
467967efcaeSBoris Brezillon 	struct spi_mem *mem;
468967efcaeSBoris Brezillon 
469967efcaeSBoris Brezillon 	mem = devm_kzalloc(&spi->dev, sizeof(*mem), GFP_KERNEL);
470967efcaeSBoris Brezillon 	if (!mem)
471967efcaeSBoris Brezillon 		return -ENOMEM;
472967efcaeSBoris Brezillon 
473967efcaeSBoris Brezillon 	mem->spi = spi;
474967efcaeSBoris Brezillon 	spi_set_drvdata(spi, mem);
475967efcaeSBoris Brezillon 
476967efcaeSBoris Brezillon 	return memdrv->probe(mem);
477967efcaeSBoris Brezillon }
478967efcaeSBoris Brezillon 
spi_mem_remove(struct spi_device * spi)479967efcaeSBoris Brezillon static int spi_mem_remove(struct spi_device *spi)
480967efcaeSBoris Brezillon {
481967efcaeSBoris Brezillon 	struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver);
482967efcaeSBoris Brezillon 	struct spi_mem *mem = spi_get_drvdata(spi);
483967efcaeSBoris Brezillon 
484967efcaeSBoris Brezillon 	if (memdrv->remove)
485967efcaeSBoris Brezillon 		return memdrv->remove(mem);
486967efcaeSBoris Brezillon 
487967efcaeSBoris Brezillon 	return 0;
488967efcaeSBoris Brezillon }
489967efcaeSBoris Brezillon 
spi_mem_shutdown(struct spi_device * spi)490967efcaeSBoris Brezillon static void spi_mem_shutdown(struct spi_device *spi)
491967efcaeSBoris Brezillon {
492967efcaeSBoris Brezillon 	struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver);
493967efcaeSBoris Brezillon 	struct spi_mem *mem = spi_get_drvdata(spi);
494967efcaeSBoris Brezillon 
495967efcaeSBoris Brezillon 	if (memdrv->shutdown)
496967efcaeSBoris Brezillon 		memdrv->shutdown(mem);
497967efcaeSBoris Brezillon }
498967efcaeSBoris Brezillon 
499967efcaeSBoris Brezillon /**
500967efcaeSBoris Brezillon  * spi_mem_driver_register_with_owner() - Register a SPI memory driver
501967efcaeSBoris Brezillon  * @memdrv: the SPI memory driver to register
502967efcaeSBoris Brezillon  * @owner: the owner of this driver
503967efcaeSBoris Brezillon  *
504967efcaeSBoris Brezillon  * Registers a SPI memory driver.
505967efcaeSBoris Brezillon  *
506967efcaeSBoris Brezillon  * Return: 0 in case of success, a negative error core otherwise.
507967efcaeSBoris Brezillon  */
508967efcaeSBoris Brezillon 
spi_mem_driver_register_with_owner(struct spi_mem_driver * memdrv,struct module * owner)509967efcaeSBoris Brezillon int spi_mem_driver_register_with_owner(struct spi_mem_driver *memdrv,
510967efcaeSBoris Brezillon 				       struct module *owner)
511967efcaeSBoris Brezillon {
512967efcaeSBoris Brezillon 	memdrv->spidrv.probe = spi_mem_probe;
513967efcaeSBoris Brezillon 	memdrv->spidrv.remove = spi_mem_remove;
514967efcaeSBoris Brezillon 	memdrv->spidrv.shutdown = spi_mem_shutdown;
515967efcaeSBoris Brezillon 
516967efcaeSBoris Brezillon 	return __spi_register_driver(owner, &memdrv->spidrv);
517967efcaeSBoris Brezillon }
518967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_mem_driver_register_with_owner);
519967efcaeSBoris Brezillon 
520967efcaeSBoris Brezillon /**
521967efcaeSBoris Brezillon  * spi_mem_driver_unregister_with_owner() - Unregister a SPI memory driver
522967efcaeSBoris Brezillon  * @memdrv: the SPI memory driver to unregister
523967efcaeSBoris Brezillon  *
524967efcaeSBoris Brezillon  * Unregisters a SPI memory driver.
525967efcaeSBoris Brezillon  */
spi_mem_driver_unregister(struct spi_mem_driver * memdrv)526967efcaeSBoris Brezillon void spi_mem_driver_unregister(struct spi_mem_driver *memdrv)
527967efcaeSBoris Brezillon {
528967efcaeSBoris Brezillon 	spi_unregister_driver(&memdrv->spidrv);
529967efcaeSBoris Brezillon }
530967efcaeSBoris Brezillon EXPORT_SYMBOL_GPL(spi_mem_driver_unregister);
531967efcaeSBoris Brezillon #endif /* __UBOOT__ */
532