xref: /rk3399_ARM-atf/drivers/mtd/spi-mem/spi_mem.c (revision 8d9c1b3ca5f11c50150ff368981883c2ea444b66)
105e6a563SLionel Debieve /*
2*6e86b462SYann Gautier  * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
305e6a563SLionel Debieve  *
405e6a563SLionel Debieve  * SPDX-License-Identifier: BSD-3-Clause
505e6a563SLionel Debieve  */
605e6a563SLionel Debieve 
705e6a563SLionel Debieve #include <assert.h>
84ce3e99aSScott Branden #include <inttypes.h>
94ce3e99aSScott Branden #include <stdint.h>
1005e6a563SLionel Debieve 
1105e6a563SLionel Debieve #include <drivers/spi_mem.h>
1205e6a563SLionel Debieve #include <lib/utils_def.h>
13*6e86b462SYann Gautier #include <libfdt.h>
1405e6a563SLionel Debieve 
1505e6a563SLionel Debieve #define SPI_MEM_DEFAULT_SPEED_HZ 100000U
1605e6a563SLionel Debieve 
1705e6a563SLionel Debieve /*
1805e6a563SLionel Debieve  * struct spi_slave - Representation of a SPI slave.
1905e6a563SLionel Debieve  *
2005e6a563SLionel Debieve  * @max_hz:		Maximum speed for this slave in Hertz.
2105e6a563SLionel Debieve  * @cs:			ID of the chip select connected to the slave.
2205e6a563SLionel Debieve  * @mode:		SPI mode to use for this slave (see SPI mode flags).
2305e6a563SLionel Debieve  * @ops:		Ops defined by the bus.
2405e6a563SLionel Debieve  */
2505e6a563SLionel Debieve struct spi_slave {
2605e6a563SLionel Debieve 	unsigned int max_hz;
2705e6a563SLionel Debieve 	unsigned int cs;
2805e6a563SLionel Debieve 	unsigned int mode;
2905e6a563SLionel Debieve 	const struct spi_bus_ops *ops;
3005e6a563SLionel Debieve };
3105e6a563SLionel Debieve 
3205e6a563SLionel Debieve static struct spi_slave spi_slave;
3305e6a563SLionel Debieve 
spi_mem_check_buswidth_req(uint8_t buswidth,bool tx)3405e6a563SLionel Debieve static bool spi_mem_check_buswidth_req(uint8_t buswidth, bool tx)
3505e6a563SLionel Debieve {
3605e6a563SLionel Debieve 	switch (buswidth) {
3705e6a563SLionel Debieve 	case 1U:
3805e6a563SLionel Debieve 		return true;
3905e6a563SLionel Debieve 
4005e6a563SLionel Debieve 	case 2U:
4105e6a563SLionel Debieve 		if ((tx && (spi_slave.mode & (SPI_TX_DUAL | SPI_TX_QUAD)) !=
4205e6a563SLionel Debieve 		     0U) ||
4305e6a563SLionel Debieve 		    (!tx && (spi_slave.mode & (SPI_RX_DUAL | SPI_RX_QUAD)) !=
4405e6a563SLionel Debieve 		     0U)) {
4505e6a563SLionel Debieve 			return true;
4605e6a563SLionel Debieve 		}
4705e6a563SLionel Debieve 		break;
4805e6a563SLionel Debieve 
4905e6a563SLionel Debieve 	case 4U:
5005e6a563SLionel Debieve 		if ((tx && (spi_slave.mode & SPI_TX_QUAD) != 0U) ||
5105e6a563SLionel Debieve 		    (!tx && (spi_slave.mode & SPI_RX_QUAD) != 0U)) {
5205e6a563SLionel Debieve 			return true;
5305e6a563SLionel Debieve 		}
5405e6a563SLionel Debieve 		break;
5505e6a563SLionel Debieve 
5605e6a563SLionel Debieve 	default:
5705e6a563SLionel Debieve 		break;
5805e6a563SLionel Debieve 	}
5905e6a563SLionel Debieve 
6005e6a563SLionel Debieve 	return false;
6105e6a563SLionel Debieve }
6205e6a563SLionel Debieve 
spi_mem_supports_op(const struct spi_mem_op * op)6305e6a563SLionel Debieve static bool spi_mem_supports_op(const struct spi_mem_op *op)
6405e6a563SLionel Debieve {
6505e6a563SLionel Debieve 	if (!spi_mem_check_buswidth_req(op->cmd.buswidth, true)) {
6605e6a563SLionel Debieve 		return false;
6705e6a563SLionel Debieve 	}
6805e6a563SLionel Debieve 
6905e6a563SLionel Debieve 	if ((op->addr.nbytes != 0U) &&
7005e6a563SLionel Debieve 	    !spi_mem_check_buswidth_req(op->addr.buswidth, true)) {
7105e6a563SLionel Debieve 		return false;
7205e6a563SLionel Debieve 	}
7305e6a563SLionel Debieve 
7405e6a563SLionel Debieve 	if ((op->dummy.nbytes != 0U) &&
7505e6a563SLionel Debieve 	    !spi_mem_check_buswidth_req(op->dummy.buswidth, true)) {
7605e6a563SLionel Debieve 		return false;
7705e6a563SLionel Debieve 	}
7805e6a563SLionel Debieve 
7905e6a563SLionel Debieve 	if ((op->data.nbytes != 0U) &&
8005e6a563SLionel Debieve 	    !spi_mem_check_buswidth_req(op->data.buswidth,
8105e6a563SLionel Debieve 				       op->data.dir == SPI_MEM_DATA_OUT)) {
8205e6a563SLionel Debieve 		return false;
8305e6a563SLionel Debieve 	}
8405e6a563SLionel Debieve 
8505e6a563SLionel Debieve 	return true;
8605e6a563SLionel Debieve }
8705e6a563SLionel Debieve 
spi_mem_set_speed_mode(void)8805e6a563SLionel Debieve static int spi_mem_set_speed_mode(void)
8905e6a563SLionel Debieve {
9005e6a563SLionel Debieve 	const struct spi_bus_ops *ops = spi_slave.ops;
9105e6a563SLionel Debieve 	int ret;
9205e6a563SLionel Debieve 
9305e6a563SLionel Debieve 	ret = ops->set_speed(spi_slave.max_hz);
9405e6a563SLionel Debieve 	if (ret != 0) {
9505e6a563SLionel Debieve 		VERBOSE("Cannot set speed (err=%d)\n", ret);
9605e6a563SLionel Debieve 		return ret;
9705e6a563SLionel Debieve 	}
9805e6a563SLionel Debieve 
9905e6a563SLionel Debieve 	ret = ops->set_mode(spi_slave.mode);
10005e6a563SLionel Debieve 	if (ret != 0) {
10105e6a563SLionel Debieve 		VERBOSE("Cannot set mode (err=%d)\n", ret);
10205e6a563SLionel Debieve 		return ret;
10305e6a563SLionel Debieve 	}
10405e6a563SLionel Debieve 
10505e6a563SLionel Debieve 	return 0;
10605e6a563SLionel Debieve }
10705e6a563SLionel Debieve 
spi_mem_check_bus_ops(const struct spi_bus_ops * ops)10805e6a563SLionel Debieve static int spi_mem_check_bus_ops(const struct spi_bus_ops *ops)
10905e6a563SLionel Debieve {
11005e6a563SLionel Debieve 	bool error = false;
11105e6a563SLionel Debieve 
11205e6a563SLionel Debieve 	if (ops->claim_bus == NULL) {
11305e6a563SLionel Debieve 		VERBOSE("Ops claim bus is not defined\n");
11405e6a563SLionel Debieve 		error = true;
11505e6a563SLionel Debieve 	}
11605e6a563SLionel Debieve 
11705e6a563SLionel Debieve 	if (ops->release_bus == NULL) {
11805e6a563SLionel Debieve 		VERBOSE("Ops release bus is not defined\n");
11905e6a563SLionel Debieve 		error = true;
12005e6a563SLionel Debieve 	}
12105e6a563SLionel Debieve 
12205e6a563SLionel Debieve 	if (ops->exec_op == NULL) {
12305e6a563SLionel Debieve 		VERBOSE("Ops exec op is not defined\n");
12405e6a563SLionel Debieve 		error = true;
12505e6a563SLionel Debieve 	}
12605e6a563SLionel Debieve 
12705e6a563SLionel Debieve 	if (ops->set_speed == NULL) {
12805e6a563SLionel Debieve 		VERBOSE("Ops set speed is not defined\n");
12905e6a563SLionel Debieve 		error = true;
13005e6a563SLionel Debieve 	}
13105e6a563SLionel Debieve 
13205e6a563SLionel Debieve 	if (ops->set_mode == NULL) {
13305e6a563SLionel Debieve 		VERBOSE("Ops set mode is not defined\n");
13405e6a563SLionel Debieve 		error = true;
13505e6a563SLionel Debieve 	}
13605e6a563SLionel Debieve 
13705e6a563SLionel Debieve 	return error ? -EINVAL : 0;
13805e6a563SLionel Debieve }
13905e6a563SLionel Debieve 
14005e6a563SLionel Debieve /*
14105e6a563SLionel Debieve  * spi_mem_exec_op() - Execute a memory operation.
14205e6a563SLionel Debieve  * @op: The memory operation to execute.
14305e6a563SLionel Debieve  *
14405e6a563SLionel Debieve  * This function first checks that @op is supported and then tries to execute
14505e6a563SLionel Debieve  * it.
14605e6a563SLionel Debieve  *
14705e6a563SLionel Debieve  * Return: 0 in case of success, a negative error code otherwise.
14805e6a563SLionel Debieve  */
spi_mem_exec_op(const struct spi_mem_op * op)14905e6a563SLionel Debieve int spi_mem_exec_op(const struct spi_mem_op *op)
15005e6a563SLionel Debieve {
15105e6a563SLionel Debieve 	const struct spi_bus_ops *ops = spi_slave.ops;
15205e6a563SLionel Debieve 	int ret;
15305e6a563SLionel Debieve 
1544ce3e99aSScott Branden 	VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addqr:%" PRIx64 " len:%x\n",
15505e6a563SLionel Debieve 		__func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
15605e6a563SLionel Debieve 		op->dummy.buswidth, op->data.buswidth,
15705e6a563SLionel Debieve 		op->addr.val, op->data.nbytes);
15805e6a563SLionel Debieve 
15905e6a563SLionel Debieve 	if (!spi_mem_supports_op(op)) {
16005e6a563SLionel Debieve 		WARN("Error in spi_mem_support\n");
16105e6a563SLionel Debieve 		return -ENOTSUP;
16205e6a563SLionel Debieve 	}
16305e6a563SLionel Debieve 
16405e6a563SLionel Debieve 	ret = ops->claim_bus(spi_slave.cs);
16505e6a563SLionel Debieve 	if (ret != 0) {
16605e6a563SLionel Debieve 		WARN("Error claim_bus\n");
16705e6a563SLionel Debieve 		return ret;
16805e6a563SLionel Debieve 	}
16905e6a563SLionel Debieve 
17005e6a563SLionel Debieve 	ret = ops->exec_op(op);
17105e6a563SLionel Debieve 
17205e6a563SLionel Debieve 	ops->release_bus();
17305e6a563SLionel Debieve 
17405e6a563SLionel Debieve 	return ret;
17505e6a563SLionel Debieve }
17605e6a563SLionel Debieve 
17705e6a563SLionel Debieve /*
17805e6a563SLionel Debieve  * spi_mem_init_slave() - SPI slave device initialization.
17905e6a563SLionel Debieve  * @fdt: Pointer to the device tree blob.
18005e6a563SLionel Debieve  * @bus_node: Offset of the bus node.
18105e6a563SLionel Debieve  * @ops: The SPI bus ops defined.
18205e6a563SLionel Debieve  *
18305e6a563SLionel Debieve  * This function first checks that @ops are supported and then tries to find
18405e6a563SLionel Debieve  * a SPI slave device.
18505e6a563SLionel Debieve  *
18605e6a563SLionel Debieve  * Return: 0 in case of success, a negative error code otherwise.
18705e6a563SLionel Debieve  */
spi_mem_init_slave(void * fdt,int bus_node,const struct spi_bus_ops * ops)18805e6a563SLionel Debieve int spi_mem_init_slave(void *fdt, int bus_node, const struct spi_bus_ops *ops)
18905e6a563SLionel Debieve {
19005e6a563SLionel Debieve 	int ret;
19105e6a563SLionel Debieve 	int mode = 0;
19205e6a563SLionel Debieve 	int nchips = 0;
19305e6a563SLionel Debieve 	int bus_subnode = 0;
19405e6a563SLionel Debieve 	const fdt32_t *cuint = NULL;
19505e6a563SLionel Debieve 
19605e6a563SLionel Debieve 	ret = spi_mem_check_bus_ops(ops);
19705e6a563SLionel Debieve 	if (ret != 0) {
19805e6a563SLionel Debieve 		return ret;
19905e6a563SLionel Debieve 	}
20005e6a563SLionel Debieve 
20105e6a563SLionel Debieve 	fdt_for_each_subnode(bus_subnode, fdt, bus_node) {
20205e6a563SLionel Debieve 		nchips++;
20305e6a563SLionel Debieve 	}
20405e6a563SLionel Debieve 
20505e6a563SLionel Debieve 	if (nchips != 1) {
20605e6a563SLionel Debieve 		ERROR("Only one SPI device is currently supported\n");
20705e6a563SLionel Debieve 		return -EINVAL;
20805e6a563SLionel Debieve 	}
20905e6a563SLionel Debieve 
21005e6a563SLionel Debieve 	fdt_for_each_subnode(bus_subnode, fdt, bus_node) {
21105e6a563SLionel Debieve 		/* Get chip select */
21205e6a563SLionel Debieve 		cuint = fdt_getprop(fdt, bus_subnode, "reg", NULL);
21305e6a563SLionel Debieve 		if (cuint == NULL) {
21405e6a563SLionel Debieve 			ERROR("Chip select not well defined\n");
21505e6a563SLionel Debieve 			return -EINVAL;
21605e6a563SLionel Debieve 		}
21705e6a563SLionel Debieve 		spi_slave.cs = fdt32_to_cpu(*cuint);
21805e6a563SLionel Debieve 
21905e6a563SLionel Debieve 		/* Get max slave frequency */
22005e6a563SLionel Debieve 		spi_slave.max_hz = SPI_MEM_DEFAULT_SPEED_HZ;
22105e6a563SLionel Debieve 		cuint = fdt_getprop(fdt, bus_subnode,
22205e6a563SLionel Debieve 				    "spi-max-frequency", NULL);
22305e6a563SLionel Debieve 		if (cuint != NULL) {
22405e6a563SLionel Debieve 			spi_slave.max_hz = fdt32_to_cpu(*cuint);
22505e6a563SLionel Debieve 		}
22605e6a563SLionel Debieve 
22705e6a563SLionel Debieve 		/* Get mode */
22805e6a563SLionel Debieve 		if ((fdt_getprop(fdt, bus_subnode, "spi-cpol", NULL)) != NULL) {
22905e6a563SLionel Debieve 			mode |= SPI_CPOL;
23005e6a563SLionel Debieve 		}
23105e6a563SLionel Debieve 		if ((fdt_getprop(fdt, bus_subnode, "spi-cpha", NULL)) != NULL) {
23205e6a563SLionel Debieve 			mode |= SPI_CPHA;
23305e6a563SLionel Debieve 		}
23405e6a563SLionel Debieve 		if ((fdt_getprop(fdt, bus_subnode, "spi-cs-high", NULL)) !=
23505e6a563SLionel Debieve 		    NULL) {
23605e6a563SLionel Debieve 			mode |= SPI_CS_HIGH;
23705e6a563SLionel Debieve 		}
23805e6a563SLionel Debieve 		if ((fdt_getprop(fdt, bus_subnode, "spi-3wire", NULL)) !=
23905e6a563SLionel Debieve 		    NULL) {
24005e6a563SLionel Debieve 			mode |= SPI_3WIRE;
24105e6a563SLionel Debieve 		}
24205e6a563SLionel Debieve 		if ((fdt_getprop(fdt, bus_subnode, "spi-half-duplex", NULL)) !=
24305e6a563SLionel Debieve 		    NULL) {
24405e6a563SLionel Debieve 			mode |= SPI_PREAMBLE;
24505e6a563SLionel Debieve 		}
24605e6a563SLionel Debieve 
24705e6a563SLionel Debieve 		/* Get dual/quad mode */
24805e6a563SLionel Debieve 		cuint = fdt_getprop(fdt, bus_subnode, "spi-tx-bus-width", NULL);
24905e6a563SLionel Debieve 		if (cuint != NULL) {
25005e6a563SLionel Debieve 			switch (fdt32_to_cpu(*cuint)) {
25105e6a563SLionel Debieve 			case 1U:
25205e6a563SLionel Debieve 				break;
25305e6a563SLionel Debieve 			case 2U:
25405e6a563SLionel Debieve 				mode |= SPI_TX_DUAL;
25505e6a563SLionel Debieve 				break;
25605e6a563SLionel Debieve 			case 4U:
25705e6a563SLionel Debieve 				mode |= SPI_TX_QUAD;
25805e6a563SLionel Debieve 				break;
25905e6a563SLionel Debieve 			default:
260*6e86b462SYann Gautier 				WARN("spi-tx-bus-width %u not supported\n",
26105e6a563SLionel Debieve 				     fdt32_to_cpu(*cuint));
26205e6a563SLionel Debieve 				return -EINVAL;
26305e6a563SLionel Debieve 			}
26405e6a563SLionel Debieve 		}
26505e6a563SLionel Debieve 
26605e6a563SLionel Debieve 		cuint = fdt_getprop(fdt, bus_subnode, "spi-rx-bus-width", NULL);
26705e6a563SLionel Debieve 		if (cuint != NULL) {
26805e6a563SLionel Debieve 			switch (fdt32_to_cpu(*cuint)) {
26905e6a563SLionel Debieve 			case 1U:
27005e6a563SLionel Debieve 				break;
27105e6a563SLionel Debieve 			case 2U:
27205e6a563SLionel Debieve 				mode |= SPI_RX_DUAL;
27305e6a563SLionel Debieve 				break;
27405e6a563SLionel Debieve 			case 4U:
27505e6a563SLionel Debieve 				mode |= SPI_RX_QUAD;
27605e6a563SLionel Debieve 				break;
27705e6a563SLionel Debieve 			default:
278*6e86b462SYann Gautier 				WARN("spi-rx-bus-width %u not supported\n",
27905e6a563SLionel Debieve 				     fdt32_to_cpu(*cuint));
28005e6a563SLionel Debieve 				return -EINVAL;
28105e6a563SLionel Debieve 			}
28205e6a563SLionel Debieve 		}
28305e6a563SLionel Debieve 
28405e6a563SLionel Debieve 		spi_slave.mode = mode;
28505e6a563SLionel Debieve 		spi_slave.ops = ops;
28605e6a563SLionel Debieve 	}
28705e6a563SLionel Debieve 
28805e6a563SLionel Debieve 	return spi_mem_set_speed_mode();
28905e6a563SLionel Debieve }
290