xref: /rk3399_ARM-atf/drivers/renesas/rza/rpc/rpc.c (revision 66a0bb47058db8a4f74ccc1543a146094829e110)
1 /*
2  * Copyright (c) 2026, Renesas Electronics Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdint.h>
8 #include <string.h>
9 
10 #include <common/debug.h>
11 #include <drivers/spi_nor.h>
12 #include <lib/mmio.h>
13 
14 #include "rpc.h"
15 #include "rpc_registers.h"
16 
rpc_get_drenr(const struct spi_mem_op * op)17 static uint32_t rpc_get_drenr(const struct spi_mem_op *op)
18 {
19 	/* Command output enabled, optional command output disabled */
20 	uint32_t drenr = RPC_DRENR_CDE;
21 
22 	/* Address enable */
23 	switch (op->addr.nbytes) {
24 	case 3:
25 		drenr |= RPC_DRENR_ADE_3BYTE << RPC_DRENR_ADE_POS;
26 		break;
27 	case 4:
28 		drenr |= RPC_DRENR_ADE_4BYTE << RPC_DRENR_ADE_POS;
29 		break;
30 	default:
31 		drenr |= RPC_DRENR_ADE_NONE << RPC_DRENR_ADE_POS;
32 		break;
33 	}
34 
35 	/* Set bit size of following fields:
36 	 * Command, optional command, address, option data, data
37 	 */
38 	if ((op->cmd.buswidth == SPI_MEM_BUSWIDTH_1_LINE) &&
39 	    (op->addr.buswidth == SPI_MEM_BUSWIDTH_1_LINE) &&
40 	    (op->data.buswidth == SPI_MEM_BUSWIDTH_1_LINE)) {
41 		drenr |= RPC_DRENR_DB_1BIT << RPC_DRENR_CDB_POS |
42 			 RPC_DRENR_DB_1BIT << RPC_DRENR_OCDB_POS |
43 			 RPC_DRENR_DB_1BIT << RPC_DRENR_ADB_POS |
44 			 RPC_DRENR_DB_1BIT << RPC_DRENR_OPDB_POS |
45 			 RPC_DRENR_DB_1BIT << RPC_DRENR_DRDB_POS;
46 	} else if ((op->cmd.buswidth == SPI_MEM_BUSWIDTH_1_LINE) &&
47 		   (op->addr.buswidth == SPI_MEM_BUSWIDTH_1_LINE) &&
48 		   (op->data.buswidth == SPI_MEM_BUSWIDTH_4_LINE)) {
49 		drenr |= RPC_DRENR_DB_1BIT << RPC_DRENR_CDB_POS |
50 			 RPC_DRENR_DB_1BIT << RPC_DRENR_OCDB_POS |
51 			 RPC_DRENR_DB_1BIT << RPC_DRENR_ADB_POS |
52 			 RPC_DRENR_DB_1BIT << RPC_DRENR_OPDB_POS |
53 			 RPC_DRENR_DB_4BIT << RPC_DRENR_DRDB_POS;
54 	} else if ((op->cmd.buswidth == SPI_MEM_BUSWIDTH_1_LINE) &&
55 		   (op->addr.buswidth == SPI_MEM_BUSWIDTH_4_LINE) &&
56 		   (op->data.buswidth == SPI_MEM_BUSWIDTH_4_LINE)) {
57 		drenr |= RPC_DRENR_DB_1BIT << RPC_DRENR_CDB_POS |
58 			 RPC_DRENR_DB_1BIT << RPC_DRENR_OCDB_POS |
59 			 RPC_DRENR_DB_4BIT << RPC_DRENR_ADB_POS |
60 			 RPC_DRENR_DB_4BIT << RPC_DRENR_OPDB_POS |
61 			 RPC_DRENR_DB_4BIT << RPC_DRENR_DRDB_POS;
62 	}
63 
64 	/* Dummy cycle enable */
65 	drenr |= RPC_DRENR_DME;
66 
67 	/* Optional data enable */
68 	drenr |= RPC_DRENR_OPDE_1BYTE << RPC_DRENR_OPDE_POS;
69 
70 	return drenr;
71 }
72 
rpc_config_xread_mode(const struct spi_mem_op * op)73 int rpc_config_xread_mode(const struct spi_mem_op *op)
74 {
75 	if (op->data.dir != SPI_MEM_DATA_IN) {
76 		ERROR("%s: only read command is supported for external read mode\n",
77 		      __func__);
78 		return -1;
79 	}
80 
81 	if ((op->cmd.buswidth != SPI_MEM_BUSWIDTH_1_LINE) ||
82 	    (op->addr.buswidth != SPI_MEM_BUSWIDTH_4_LINE) ||
83 	    (op->data.buswidth != SPI_MEM_BUSWIDTH_4_LINE)) {
84 		ERROR("%s: currently, only 1-4-4 format is supported\n",
85 		      __func__);
86 		return -1;
87 	}
88 
89 	/* Switch to manual mode to temporarily disable external address space read mode */
90 	mmio_clrsetbits_32(RPC_CMNCR, RPC_CMNCR_MD, 1u << RPC_CMNCR_MD_POS);
91 
92 	uint32_t mask = 0;
93 	uint32_t set = 0;
94 
95 	/* PHYOFFSET1 */
96 	mask = RPC_PHYOFFSET1_DDRTMG;
97 	set = RPC_PHYOFFSET1_SDR << RPC_PHYOFFSET1_DDRTMG_POS;
98 	mmio_clrsetbits_32(RPC_PHYOFFSET1, mask, set);
99 
100 	/* PHYOFFSET2 */
101 	mask = RPC_PHYOFFSET2_OCTTMG;
102 	set = RPC_PHYOFFSET2_SPI << RPC_PHYOFFSET2_OCTTMG_POS;
103 	mmio_clrsetbits_32(RPC_PHYOFFSET2, mask, set);
104 
105 	/* PHYCNT */
106 	mask = RPC_PHYCNT_PHYMEM;
107 	set = (RPC_PHYCNT_SDR << RPC_PHYCNT_PHYMEM_POS) | RPC_PHYCNT_CAL;
108 	mmio_clrsetbits_32(RPC_PHYCNT, mask, set);
109 
110 	/* CMNCR */
111 	mask = RPC_CMNCR_BSZ | RPC_CMNCR_IO2FV | RPC_CMNCR_IO3FV |
112 	       RPC_CMNCR_MOIIO1 | RPC_CMNCR_MOIIO2 | RPC_CMNCR_MOIIO3;
113 	set = (RPC_CMNCR_BSZ_SINGLE << RPC_CMNCR_BSZ_POS) |
114 	      (RPC_CMNCR_IO_HIGH << RPC_CMNCR_MOIIO3_POS) |
115 	      (RPC_CMNCR_IO_KEEP << RPC_CMNCR_IO3FV_POS) |
116 	      (RPC_CMNCR_IO_HIZ << RPC_CMNCR_MOIIO2_POS) |
117 	      (RPC_CMNCR_IO_HIZ << RPC_CMNCR_IO2FV_POS) |
118 	      (RPC_CMNCR_IO_HIZ << RPC_CMNCR_MOIIO1_POS);
119 	mmio_clrsetbits_32(RPC_CMNCR, mask, set);
120 
121 	/* SSLDR */
122 	mask = RPC_SSLDR_SCKDL | RPC_SSLDR_SLNDL | RPC_SSLDR_SPNDL;
123 	set = (0 << RPC_SSLDR_SCKDL_POS) | (0 << RPC_SSLDR_SLNDL_POS) |
124 	      (6u << RPC_SSLDR_SPNDL_POS);
125 	mmio_clrsetbits_32(RPC_SSLDR, mask, set);
126 
127 	/* DRCR */
128 	mask = RPC_DRCR_RBURST | RPC_DRCR_RBE | RPC_DRCR_SSLE;
129 	set = (7u << RPC_DRCR_RBURST_POS) | RPC_DRCR_RCF | RPC_DRCR_RBE | RPC_DRCR_SSLE;
130 	mmio_clrsetbits_32(RPC_DRCR, mask, set);
131 
132 	/* DRCMR */
133 	mask = RPC_DRCMR_CMD | RPC_DRCMR_OCMD;
134 	set = (op->cmd.opcode & 0xff) << RPC_DRCMR_CMD_POS;
135 	mmio_clrsetbits_32(RPC_DRCMR, mask, set);
136 
137 	/* DROPR */
138 	mask = 0xffff;
139 	set = (0x55555555u & 0xffu) << RPC_DROPR_OPD3_POS;
140 	mmio_write_32(RPC_DROPR, set);
141 
142 	/* DRENR */
143 	mask = RPC_DRENR_ADB | RPC_DRENR_ADE | RPC_DRENR_CDB | RPC_DRENR_CDE |
144 	       RPC_DRENR_DME | RPC_DRENR_DRDB | RPC_DRENR_OCDB |
145 	       RPC_DRENR_OCDE | RPC_DRENR_OPDB | RPC_DRENR_OPDE;
146 	set = rpc_get_drenr(op);
147 	mmio_clrsetbits_32(RPC_DRENR, mask, set);
148 
149 	/* DRDMCR */
150 	mask = RPC_DRDMCR_DMCYC;
151 	set = (op->dummy.nbytes * 2 - 1) << RPC_DRDMCR_DMCYC_POS;
152 	mmio_write_32(RPC_DRDMCR, set);
153 
154 	/* DRDRENR */
155 	mask = RPC_DRDRENR_ADDRE | RPC_DRDRENR_DRDRE | RPC_DRDRENR_HYPE | RPC_DRDRENR_OPDRE;
156 	set = 0;
157 	mmio_clrsetbits_32(RPC_DRDRENR, mask, set);
158 
159 	/* Start XIP */
160 	mmio_clrbits_32(RPC_CMNCR, RPC_CMNCR_MD);
161 	mmio_read_32(RPC_CMNCR);
162 
163 	return 0;
164 }
165