xref: /rk3399_rockchip-uboot/drivers/spi/cadence_qspi.c (revision 4e609b6cb1e6e8cb14c55fd50c73c5affcba26b5)
110e8bf88SStefan Roese /*
210e8bf88SStefan Roese  * Copyright (C) 2012
310e8bf88SStefan Roese  * Altera Corporation <www.altera.com>
410e8bf88SStefan Roese  *
510e8bf88SStefan Roese  * SPDX-License-Identifier:	GPL-2.0+
610e8bf88SStefan Roese  */
710e8bf88SStefan Roese 
810e8bf88SStefan Roese #include <common.h>
910e8bf88SStefan Roese #include <dm.h>
1010e8bf88SStefan Roese #include <fdtdec.h>
1110e8bf88SStefan Roese #include <malloc.h>
1210e8bf88SStefan Roese #include <spi.h>
1310e8bf88SStefan Roese #include <asm/errno.h>
1410e8bf88SStefan Roese #include "cadence_qspi.h"
1510e8bf88SStefan Roese 
1610e8bf88SStefan Roese #define CQSPI_STIG_READ			0
1710e8bf88SStefan Roese #define CQSPI_STIG_WRITE		1
1810e8bf88SStefan Roese #define CQSPI_INDIRECT_READ		2
1910e8bf88SStefan Roese #define CQSPI_INDIRECT_WRITE		3
2010e8bf88SStefan Roese 
2110e8bf88SStefan Roese DECLARE_GLOBAL_DATA_PTR;
2210e8bf88SStefan Roese 
2310e8bf88SStefan Roese static int cadence_spi_write_speed(struct udevice *bus, uint hz)
2410e8bf88SStefan Roese {
2510e8bf88SStefan Roese 	struct cadence_spi_platdata *plat = bus->platdata;
2610e8bf88SStefan Roese 	struct cadence_spi_priv *priv = dev_get_priv(bus);
2710e8bf88SStefan Roese 
2810e8bf88SStefan Roese 	cadence_qspi_apb_config_baudrate_div(priv->regbase,
2910e8bf88SStefan Roese 					     CONFIG_CQSPI_REF_CLK, hz);
3010e8bf88SStefan Roese 
3110e8bf88SStefan Roese 	/* Reconfigure delay timing if speed is changed. */
3210e8bf88SStefan Roese 	cadence_qspi_apb_delay(priv->regbase, CONFIG_CQSPI_REF_CLK, hz,
3310e8bf88SStefan Roese 			       plat->tshsl_ns, plat->tsd2d_ns,
3410e8bf88SStefan Roese 			       plat->tchsh_ns, plat->tslch_ns);
3510e8bf88SStefan Roese 
3610e8bf88SStefan Roese 	return 0;
3710e8bf88SStefan Roese }
3810e8bf88SStefan Roese 
3910e8bf88SStefan Roese /* Calibration sequence to determine the read data capture delay register */
4098fbd71dSChin Liang See static int spi_calibration(struct udevice *bus, uint hz)
4110e8bf88SStefan Roese {
4210e8bf88SStefan Roese 	struct cadence_spi_priv *priv = dev_get_priv(bus);
4310e8bf88SStefan Roese 	void *base = priv->regbase;
4410e8bf88SStefan Roese 	u8 opcode_rdid = 0x9F;
4510e8bf88SStefan Roese 	unsigned int idcode = 0, temp = 0;
4610e8bf88SStefan Roese 	int err = 0, i, range_lo = -1, range_hi = -1;
4710e8bf88SStefan Roese 
4810e8bf88SStefan Roese 	/* start with slowest clock (1 MHz) */
4910e8bf88SStefan Roese 	cadence_spi_write_speed(bus, 1000000);
5010e8bf88SStefan Roese 
5110e8bf88SStefan Roese 	/* configure the read data capture delay register to 0 */
5210e8bf88SStefan Roese 	cadence_qspi_apb_readdata_capture(base, 1, 0);
5310e8bf88SStefan Roese 
5410e8bf88SStefan Roese 	/* Enable QSPI */
5510e8bf88SStefan Roese 	cadence_qspi_apb_controller_enable(base);
5610e8bf88SStefan Roese 
5710e8bf88SStefan Roese 	/* read the ID which will be our golden value */
5810e8bf88SStefan Roese 	err = cadence_qspi_apb_command_read(base, 1, &opcode_rdid,
5910e8bf88SStefan Roese 		3, (u8 *)&idcode);
6010e8bf88SStefan Roese 	if (err) {
6110e8bf88SStefan Roese 		puts("SF: Calibration failed (read)\n");
6210e8bf88SStefan Roese 		return err;
6310e8bf88SStefan Roese 	}
6410e8bf88SStefan Roese 
6510e8bf88SStefan Roese 	/* use back the intended clock and find low range */
6698fbd71dSChin Liang See 	cadence_spi_write_speed(bus, hz);
6710e8bf88SStefan Roese 	for (i = 0; i < CQSPI_READ_CAPTURE_MAX_DELAY; i++) {
6810e8bf88SStefan Roese 		/* Disable QSPI */
6910e8bf88SStefan Roese 		cadence_qspi_apb_controller_disable(base);
7010e8bf88SStefan Roese 
7110e8bf88SStefan Roese 		/* reconfigure the read data capture delay register */
7210e8bf88SStefan Roese 		cadence_qspi_apb_readdata_capture(base, 1, i);
7310e8bf88SStefan Roese 
7410e8bf88SStefan Roese 		/* Enable back QSPI */
7510e8bf88SStefan Roese 		cadence_qspi_apb_controller_enable(base);
7610e8bf88SStefan Roese 
7710e8bf88SStefan Roese 		/* issue a RDID to get the ID value */
7810e8bf88SStefan Roese 		err = cadence_qspi_apb_command_read(base, 1, &opcode_rdid,
7910e8bf88SStefan Roese 			3, (u8 *)&temp);
8010e8bf88SStefan Roese 		if (err) {
8110e8bf88SStefan Roese 			puts("SF: Calibration failed (read)\n");
8210e8bf88SStefan Roese 			return err;
8310e8bf88SStefan Roese 		}
8410e8bf88SStefan Roese 
8510e8bf88SStefan Roese 		/* search for range lo */
8610e8bf88SStefan Roese 		if (range_lo == -1 && temp == idcode) {
8710e8bf88SStefan Roese 			range_lo = i;
8810e8bf88SStefan Roese 			continue;
8910e8bf88SStefan Roese 		}
9010e8bf88SStefan Roese 
9110e8bf88SStefan Roese 		/* search for range hi */
9210e8bf88SStefan Roese 		if (range_lo != -1 && temp != idcode) {
9310e8bf88SStefan Roese 			range_hi = i - 1;
9410e8bf88SStefan Roese 			break;
9510e8bf88SStefan Roese 		}
9610e8bf88SStefan Roese 		range_hi = i;
9710e8bf88SStefan Roese 	}
9810e8bf88SStefan Roese 
9910e8bf88SStefan Roese 	if (range_lo == -1) {
10010e8bf88SStefan Roese 		puts("SF: Calibration failed (low range)\n");
10110e8bf88SStefan Roese 		return err;
10210e8bf88SStefan Roese 	}
10310e8bf88SStefan Roese 
10410e8bf88SStefan Roese 	/* Disable QSPI for subsequent initialization */
10510e8bf88SStefan Roese 	cadence_qspi_apb_controller_disable(base);
10610e8bf88SStefan Roese 
10710e8bf88SStefan Roese 	/* configure the final value for read data capture delay register */
10810e8bf88SStefan Roese 	cadence_qspi_apb_readdata_capture(base, 1, (range_hi + range_lo) / 2);
10910e8bf88SStefan Roese 	debug("SF: Read data capture delay calibrated to %i (%i - %i)\n",
11010e8bf88SStefan Roese 	      (range_hi + range_lo) / 2, range_lo, range_hi);
11110e8bf88SStefan Roese 
11210e8bf88SStefan Roese 	/* just to ensure we do once only when speed or chip select change */
11398fbd71dSChin Liang See 	priv->qspi_calibrated_hz = hz;
11410e8bf88SStefan Roese 	priv->qspi_calibrated_cs = spi_chip_select(bus);
11510e8bf88SStefan Roese 
11610e8bf88SStefan Roese 	return 0;
11710e8bf88SStefan Roese }
11810e8bf88SStefan Roese 
11910e8bf88SStefan Roese static int cadence_spi_set_speed(struct udevice *bus, uint hz)
12010e8bf88SStefan Roese {
12110e8bf88SStefan Roese 	struct cadence_spi_platdata *plat = bus->platdata;
12210e8bf88SStefan Roese 	struct cadence_spi_priv *priv = dev_get_priv(bus);
12310e8bf88SStefan Roese 	int err;
12410e8bf88SStefan Roese 
125*4e609b6cSChin Liang See 	if (hz > plat->max_hz)
126*4e609b6cSChin Liang See 		hz = plat->max_hz;
127*4e609b6cSChin Liang See 
12810e8bf88SStefan Roese 	/* Disable QSPI */
12910e8bf88SStefan Roese 	cadence_qspi_apb_controller_disable(priv->regbase);
13010e8bf88SStefan Roese 
13198fbd71dSChin Liang See 	/*
13298fbd71dSChin Liang See 	 * Calibration required for different current SCLK speed, requested
13398fbd71dSChin Liang See 	 * SCLK speed or chip select
13498fbd71dSChin Liang See 	 */
13598fbd71dSChin Liang See 	if (priv->previous_hz != hz ||
13698fbd71dSChin Liang See 	    priv->qspi_calibrated_hz != hz ||
13710e8bf88SStefan Roese 	    priv->qspi_calibrated_cs != spi_chip_select(bus)) {
13898fbd71dSChin Liang See 		err = spi_calibration(bus, hz);
13910e8bf88SStefan Roese 		if (err)
14010e8bf88SStefan Roese 			return err;
14198fbd71dSChin Liang See 
14298fbd71dSChin Liang See 		/* prevent calibration run when same as previous request */
14398fbd71dSChin Liang See 		priv->previous_hz = hz;
14410e8bf88SStefan Roese 	}
14510e8bf88SStefan Roese 
14610e8bf88SStefan Roese 	/* Enable QSPI */
14710e8bf88SStefan Roese 	cadence_qspi_apb_controller_enable(priv->regbase);
14810e8bf88SStefan Roese 
14910e8bf88SStefan Roese 	debug("%s: speed=%d\n", __func__, hz);
15010e8bf88SStefan Roese 
15110e8bf88SStefan Roese 	return 0;
15210e8bf88SStefan Roese }
15310e8bf88SStefan Roese 
15410e8bf88SStefan Roese static int cadence_spi_probe(struct udevice *bus)
15510e8bf88SStefan Roese {
15610e8bf88SStefan Roese 	struct cadence_spi_platdata *plat = bus->platdata;
15710e8bf88SStefan Roese 	struct cadence_spi_priv *priv = dev_get_priv(bus);
15810e8bf88SStefan Roese 
15910e8bf88SStefan Roese 	priv->regbase = plat->regbase;
16010e8bf88SStefan Roese 	priv->ahbbase = plat->ahbbase;
16110e8bf88SStefan Roese 
16210e8bf88SStefan Roese 	if (!priv->qspi_is_init) {
16310e8bf88SStefan Roese 		cadence_qspi_apb_controller_init(plat);
16410e8bf88SStefan Roese 		priv->qspi_is_init = 1;
16510e8bf88SStefan Roese 	}
16610e8bf88SStefan Roese 
16710e8bf88SStefan Roese 	return 0;
16810e8bf88SStefan Roese }
16910e8bf88SStefan Roese 
17010e8bf88SStefan Roese static int cadence_spi_set_mode(struct udevice *bus, uint mode)
17110e8bf88SStefan Roese {
17210e8bf88SStefan Roese 	struct cadence_spi_priv *priv = dev_get_priv(bus);
17310e8bf88SStefan Roese 	unsigned int clk_pol = (mode & SPI_CPOL) ? 1 : 0;
17410e8bf88SStefan Roese 	unsigned int clk_pha = (mode & SPI_CPHA) ? 1 : 0;
17510e8bf88SStefan Roese 
17610e8bf88SStefan Roese 	/* Disable QSPI */
17710e8bf88SStefan Roese 	cadence_qspi_apb_controller_disable(priv->regbase);
17810e8bf88SStefan Roese 
17910e8bf88SStefan Roese 	/* Set SPI mode */
18010e8bf88SStefan Roese 	cadence_qspi_apb_set_clk_mode(priv->regbase, clk_pol, clk_pha);
18110e8bf88SStefan Roese 
18210e8bf88SStefan Roese 	/* Enable QSPI */
18310e8bf88SStefan Roese 	cadence_qspi_apb_controller_enable(priv->regbase);
18410e8bf88SStefan Roese 
18510e8bf88SStefan Roese 	return 0;
18610e8bf88SStefan Roese }
18710e8bf88SStefan Roese 
18810e8bf88SStefan Roese static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen,
18910e8bf88SStefan Roese 			    const void *dout, void *din, unsigned long flags)
19010e8bf88SStefan Roese {
19110e8bf88SStefan Roese 	struct udevice *bus = dev->parent;
19210e8bf88SStefan Roese 	struct cadence_spi_platdata *plat = bus->platdata;
19310e8bf88SStefan Roese 	struct cadence_spi_priv *priv = dev_get_priv(bus);
19410e8bf88SStefan Roese 	void *base = priv->regbase;
19510e8bf88SStefan Roese 	u8 *cmd_buf = priv->cmd_buf;
19610e8bf88SStefan Roese 	size_t data_bytes;
19710e8bf88SStefan Roese 	int err = 0;
19810e8bf88SStefan Roese 	u32 mode = CQSPI_STIG_WRITE;
19910e8bf88SStefan Roese 
20010e8bf88SStefan Roese 	if (flags & SPI_XFER_BEGIN) {
20110e8bf88SStefan Roese 		/* copy command to local buffer */
20210e8bf88SStefan Roese 		priv->cmd_len = bitlen / 8;
20310e8bf88SStefan Roese 		memcpy(cmd_buf, dout, priv->cmd_len);
20410e8bf88SStefan Roese 	}
20510e8bf88SStefan Roese 
20610e8bf88SStefan Roese 	if (flags == (SPI_XFER_BEGIN | SPI_XFER_END)) {
20710e8bf88SStefan Roese 		/* if start and end bit are set, the data bytes is 0. */
20810e8bf88SStefan Roese 		data_bytes = 0;
20910e8bf88SStefan Roese 	} else {
21010e8bf88SStefan Roese 		data_bytes = bitlen / 8;
21110e8bf88SStefan Roese 	}
21210e8bf88SStefan Roese 	debug("%s: len=%d [bytes]\n", __func__, data_bytes);
21310e8bf88SStefan Roese 
21410e8bf88SStefan Roese 	/* Set Chip select */
21510e8bf88SStefan Roese 	cadence_qspi_apb_chipselect(base, spi_chip_select(dev),
21610e8bf88SStefan Roese 				    CONFIG_CQSPI_DECODER);
21710e8bf88SStefan Roese 
21810e8bf88SStefan Roese 	if ((flags & SPI_XFER_END) || (flags == 0)) {
21910e8bf88SStefan Roese 		if (priv->cmd_len == 0) {
22010e8bf88SStefan Roese 			printf("QSPI: Error, command is empty.\n");
22110e8bf88SStefan Roese 			return -1;
22210e8bf88SStefan Roese 		}
22310e8bf88SStefan Roese 
22410e8bf88SStefan Roese 		if (din && data_bytes) {
22510e8bf88SStefan Roese 			/* read */
22610e8bf88SStefan Roese 			/* Use STIG if no address. */
22710e8bf88SStefan Roese 			if (!CQSPI_IS_ADDR(priv->cmd_len))
22810e8bf88SStefan Roese 				mode = CQSPI_STIG_READ;
22910e8bf88SStefan Roese 			else
23010e8bf88SStefan Roese 				mode = CQSPI_INDIRECT_READ;
23110e8bf88SStefan Roese 		} else if (dout && !(flags & SPI_XFER_BEGIN)) {
23210e8bf88SStefan Roese 			/* write */
23310e8bf88SStefan Roese 			if (!CQSPI_IS_ADDR(priv->cmd_len))
23410e8bf88SStefan Roese 				mode = CQSPI_STIG_WRITE;
23510e8bf88SStefan Roese 			else
23610e8bf88SStefan Roese 				mode = CQSPI_INDIRECT_WRITE;
23710e8bf88SStefan Roese 		}
23810e8bf88SStefan Roese 
23910e8bf88SStefan Roese 		switch (mode) {
24010e8bf88SStefan Roese 		case CQSPI_STIG_READ:
24110e8bf88SStefan Roese 			err = cadence_qspi_apb_command_read(
24210e8bf88SStefan Roese 				base, priv->cmd_len, cmd_buf,
24310e8bf88SStefan Roese 				data_bytes, din);
24410e8bf88SStefan Roese 
24510e8bf88SStefan Roese 		break;
24610e8bf88SStefan Roese 		case CQSPI_STIG_WRITE:
24710e8bf88SStefan Roese 			err = cadence_qspi_apb_command_write(base,
24810e8bf88SStefan Roese 				priv->cmd_len, cmd_buf,
24910e8bf88SStefan Roese 				data_bytes, dout);
25010e8bf88SStefan Roese 		break;
25110e8bf88SStefan Roese 		case CQSPI_INDIRECT_READ:
25210e8bf88SStefan Roese 			err = cadence_qspi_apb_indirect_read_setup(plat,
25310e8bf88SStefan Roese 				priv->cmd_len, cmd_buf);
25410e8bf88SStefan Roese 			if (!err) {
25510e8bf88SStefan Roese 				err = cadence_qspi_apb_indirect_read_execute
25610e8bf88SStefan Roese 				(plat, data_bytes, din);
25710e8bf88SStefan Roese 			}
25810e8bf88SStefan Roese 		break;
25910e8bf88SStefan Roese 		case CQSPI_INDIRECT_WRITE:
26010e8bf88SStefan Roese 			err = cadence_qspi_apb_indirect_write_setup
26110e8bf88SStefan Roese 				(plat, priv->cmd_len, cmd_buf);
26210e8bf88SStefan Roese 			if (!err) {
26310e8bf88SStefan Roese 				err = cadence_qspi_apb_indirect_write_execute
26410e8bf88SStefan Roese 				(plat, data_bytes, dout);
26510e8bf88SStefan Roese 			}
26610e8bf88SStefan Roese 		break;
26710e8bf88SStefan Roese 		default:
26810e8bf88SStefan Roese 			err = -1;
26910e8bf88SStefan Roese 			break;
27010e8bf88SStefan Roese 		}
27110e8bf88SStefan Roese 
27210e8bf88SStefan Roese 		if (flags & SPI_XFER_END) {
27310e8bf88SStefan Roese 			/* clear command buffer */
27410e8bf88SStefan Roese 			memset(cmd_buf, 0, sizeof(priv->cmd_buf));
27510e8bf88SStefan Roese 			priv->cmd_len = 0;
27610e8bf88SStefan Roese 		}
27710e8bf88SStefan Roese 	}
27810e8bf88SStefan Roese 
27910e8bf88SStefan Roese 	return err;
28010e8bf88SStefan Roese }
28110e8bf88SStefan Roese 
28210e8bf88SStefan Roese static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
28310e8bf88SStefan Roese {
28410e8bf88SStefan Roese 	struct cadence_spi_platdata *plat = bus->platdata;
28510e8bf88SStefan Roese 	const void *blob = gd->fdt_blob;
28610e8bf88SStefan Roese 	int node = bus->of_offset;
28710e8bf88SStefan Roese 	int subnode;
28810e8bf88SStefan Roese 	u32 data[4];
28910e8bf88SStefan Roese 	int ret;
29010e8bf88SStefan Roese 
29110e8bf88SStefan Roese 	/* 2 base addresses are needed, lets get them from the DT */
29210e8bf88SStefan Roese 	ret = fdtdec_get_int_array(blob, node, "reg", data, ARRAY_SIZE(data));
29310e8bf88SStefan Roese 	if (ret) {
29410e8bf88SStefan Roese 		printf("Error: Can't get base addresses (ret=%d)!\n", ret);
29510e8bf88SStefan Roese 		return -ENODEV;
29610e8bf88SStefan Roese 	}
29710e8bf88SStefan Roese 
29810e8bf88SStefan Roese 	plat->regbase = (void *)data[0];
29910e8bf88SStefan Roese 	plat->ahbbase = (void *)data[2];
30010e8bf88SStefan Roese 
30110e8bf88SStefan Roese 	/* All other paramters are embedded in the child node */
30210e8bf88SStefan Roese 	subnode = fdt_first_subnode(blob, node);
3031dc7d00fSAxel Lin 	if (subnode < 0) {
30410e8bf88SStefan Roese 		printf("Error: subnode with SPI flash config missing!\n");
30510e8bf88SStefan Roese 		return -ENODEV;
30610e8bf88SStefan Roese 	}
30710e8bf88SStefan Roese 
308040f4ba7SChin Liang See 	/* Use 500 KHz as a suitable default */
309040f4ba7SChin Liang See 	plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency",
310040f4ba7SChin Liang See 				       500000);
311040f4ba7SChin Liang See 
31210e8bf88SStefan Roese 	/* Read other parameters from DT */
31310e8bf88SStefan Roese 	plat->page_size = fdtdec_get_int(blob, subnode, "page-size", 256);
31410e8bf88SStefan Roese 	plat->block_size = fdtdec_get_int(blob, subnode, "block-size", 16);
31510e8bf88SStefan Roese 	plat->tshsl_ns = fdtdec_get_int(blob, subnode, "tshsl-ns", 200);
31610e8bf88SStefan Roese 	plat->tsd2d_ns = fdtdec_get_int(blob, subnode, "tsd2d-ns", 255);
31710e8bf88SStefan Roese 	plat->tchsh_ns = fdtdec_get_int(blob, subnode, "tchsh-ns", 20);
31810e8bf88SStefan Roese 	plat->tslch_ns = fdtdec_get_int(blob, subnode, "tslch-ns", 20);
31990a2f717SVikas Manocha 	plat->sram_size = fdtdec_get_int(blob, node, "sram-size", 128);
32010e8bf88SStefan Roese 
32110e8bf88SStefan Roese 	debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n",
32210e8bf88SStefan Roese 	      __func__, plat->regbase, plat->ahbbase, plat->max_hz,
32310e8bf88SStefan Roese 	      plat->page_size);
32410e8bf88SStefan Roese 
32510e8bf88SStefan Roese 	return 0;
32610e8bf88SStefan Roese }
32710e8bf88SStefan Roese 
32810e8bf88SStefan Roese static const struct dm_spi_ops cadence_spi_ops = {
32910e8bf88SStefan Roese 	.xfer		= cadence_spi_xfer,
33010e8bf88SStefan Roese 	.set_speed	= cadence_spi_set_speed,
33110e8bf88SStefan Roese 	.set_mode	= cadence_spi_set_mode,
33210e8bf88SStefan Roese 	/*
33310e8bf88SStefan Roese 	 * cs_info is not needed, since we require all chip selects to be
33410e8bf88SStefan Roese 	 * in the device tree explicitly
33510e8bf88SStefan Roese 	 */
33610e8bf88SStefan Roese };
33710e8bf88SStefan Roese 
33810e8bf88SStefan Roese static const struct udevice_id cadence_spi_ids[] = {
33910e8bf88SStefan Roese 	{ .compatible = "cadence,qspi" },
34010e8bf88SStefan Roese 	{ }
34110e8bf88SStefan Roese };
34210e8bf88SStefan Roese 
34310e8bf88SStefan Roese U_BOOT_DRIVER(cadence_spi) = {
34410e8bf88SStefan Roese 	.name = "cadence_spi",
34510e8bf88SStefan Roese 	.id = UCLASS_SPI,
34610e8bf88SStefan Roese 	.of_match = cadence_spi_ids,
34710e8bf88SStefan Roese 	.ops = &cadence_spi_ops,
34810e8bf88SStefan Roese 	.ofdata_to_platdata = cadence_spi_ofdata_to_platdata,
34910e8bf88SStefan Roese 	.platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
35010e8bf88SStefan Roese 	.priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
35110e8bf88SStefan Roese 	.probe = cadence_spi_probe,
35210e8bf88SStefan Roese };
353