xref: /rk3399_rockchip-uboot/drivers/rkflash/sfc.c (revision 2a3fb7bb049d69d96f3bc7dae8caa756fdc8a613)
1 /*
2  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <linux/delay.h>
9 #include <bouncebuf.h>
10 #include <asm/io.h>
11 
12 #include "sfc.h"
13 
14 #define SFC_MAX_IOSIZE_VER3		(1024 * 8)
15 #define SFC_MAX_IOSIZE_VER4		(0xFFFFFFFF)
16 
17 static void __iomem *g_sfc_reg;
18 
19 static void sfc_reset(void)
20 {
21 	int timeout = 10000;
22 
23 	writel(SFC_RESET, g_sfc_reg + SFC_RCVR);
24 	while ((readl(g_sfc_reg + SFC_RCVR) == SFC_RESET) && (timeout > 0)) {
25 		sfc_delay(1);
26 		timeout--;
27 	}
28 	writel(0xFFFFFFFF, g_sfc_reg + SFC_ICLR);
29 }
30 
31 u16 sfc_get_version(void)
32 {
33 	return  (u32)(readl(g_sfc_reg + SFC_VER) & 0xffff);
34 }
35 
36 u32 sfc_get_max_iosize(void)
37 {
38 	if (sfc_get_version() >= SFC_VER_4)
39 		return SFC_MAX_IOSIZE_VER4;
40 	else
41 		return SFC_MAX_IOSIZE_VER3;
42 }
43 
44 int sfc_init(void __iomem *reg_addr)
45 {
46 	g_sfc_reg = reg_addr;
47 	writel(0, g_sfc_reg + SFC_CTRL);
48 	if (sfc_get_version() >= SFC_VER_4)
49 		writel(1, g_sfc_reg + SFC_LEN_CTRL);
50 
51 	return SFC_OK;
52 }
53 
54 void sfc_clean_irq(void)
55 {
56 	writel(0xFFFFFFFF, g_sfc_reg + SFC_ICLR);
57 	writel(0xFFFFFFFF, g_sfc_reg + SFC_IMR);
58 }
59 
60 int sfc_request(struct rk_sfc_op *op, u32 addr, void *data, u32 size)
61 {
62 	int ret = SFC_OK;
63 	union SFCCMD_DATA cmd;
64 	int reg;
65 	int timeout = 0;
66 
67 	reg = readl(g_sfc_reg + SFC_FSR);
68 	if (!(reg & SFC_TXEMPTY) || !(reg & SFC_RXEMPTY) ||
69 	    (readl(g_sfc_reg + SFC_SR) & SFC_BUSY))
70 		sfc_reset();
71 
72 	cmd.d32 = op->sfcmd.d32;
73 	if (cmd.b.addrbits == SFC_ADDR_XBITS) {
74 		union SFCCTRL_DATA ctrl;
75 
76 		ctrl.d32 = op->sfctrl.d32;
77 		if (!ctrl.b.addrbits)
78 			return SFC_PARAM_ERR;
79 		/* Controller plus 1 automatically */
80 		writel(ctrl.b.addrbits - 1, g_sfc_reg + SFC_ABIT);
81 	}
82 	/* shift in the data at negedge sclk_out */
83 	op->sfctrl.d32 |= 0x2;
84 	cmd.b.datasize = size;
85 	if (sfc_get_version() >= SFC_VER_4)
86 		writel(size, g_sfc_reg + SFC_LEN_EXT);
87 	else
88 		cmd.b.datasize = size;
89 
90 	writel(op->sfctrl.d32, g_sfc_reg + SFC_CTRL);
91 	writel(cmd.d32, g_sfc_reg + SFC_CMD);
92 	if (cmd.b.addrbits)
93 		writel(addr, g_sfc_reg + SFC_ADDR);
94 	if (!size)
95 		goto exit_wait;
96 	if (op->sfctrl.b.enbledma) {
97 		struct bounce_buffer bb;
98 		unsigned int bb_flags;
99 
100 		if (cmd.b.rw == SFC_WRITE)
101 			bb_flags = GEN_BB_READ;
102 		else
103 			bb_flags = GEN_BB_WRITE;
104 
105 		ret = bounce_buffer_start(&bb, data, size, bb_flags);
106 		if (ret)
107 			return ret;
108 
109 		writel(0xFFFFFFFF, g_sfc_reg + SFC_ICLR);
110 		writel(~((u32)DMA_INT), g_sfc_reg + SFC_IMR);
111 		writel((unsigned long)bb.bounce_buffer, g_sfc_reg + SFC_DMA_ADDR);
112 		writel(SFC_DMA_START, g_sfc_reg + SFC_DMA_TRIGGER);
113 
114 		timeout = size * 10;
115 		while ((readl(g_sfc_reg + SFC_SR) & SFC_BUSY) &&
116 		       (timeout-- > 0))
117 			sfc_delay(1);
118 		writel(0xFFFFFFFF, g_sfc_reg + SFC_ICLR);
119 		if (timeout <= 0)
120 			ret = SFC_WAIT_TIMEOUT;
121 		bounce_buffer_stop(&bb);
122 	} else {
123 		u32 i, words, count, bytes;
124 		union SFCFSR_DATA    fifostat;
125 		u32 *p_data = (u32 *)data;
126 
127 		if (cmd.b.rw == SFC_WRITE) {
128 			words  = (size + 3) >> 2;
129 			while (words) {
130 				fifostat.d32 = readl(g_sfc_reg + SFC_FSR);
131 				if (fifostat.b.txlevel > 0) {
132 					count = words < fifostat.b.txlevel ?
133 						words : fifostat.b.txlevel;
134 					for (i = 0; i < count; i++) {
135 						writel(*p_data++,
136 						       g_sfc_reg + SFC_DATA);
137 						words--;
138 					}
139 					if (words == 0)
140 						break;
141 					timeout = 0;
142 				} else {
143 					sfc_delay(1);
144 					if (timeout++ > 10000) {
145 						ret = SFC_TX_TIMEOUT;
146 						break;
147 					}
148 				}
149 			}
150 		} else {
151 			/* SFC_READ == cmd.b.rw */
152 			bytes = size & 0x3;
153 			words = size >> 2;
154 			while (words) {
155 				fifostat.d32 = readl(g_sfc_reg + SFC_FSR);
156 				if (fifostat.b.rxlevel > 0) {
157 					u32 count;
158 
159 					count = words < fifostat.b.rxlevel ?
160 						words : fifostat.b.rxlevel;
161 
162 					for (i = 0; i < count; i++) {
163 						*p_data++ = readl(g_sfc_reg +
164 								  SFC_DATA);
165 						words--;
166 					}
167 					if (words == 0)
168 						break;
169 					timeout = 0;
170 				} else {
171 					sfc_delay(1);
172 					if (timeout++ > 10000) {
173 						ret = SFC_RX_TIMEOUT;
174 						break;
175 					}
176 				}
177 			}
178 
179 			timeout = 0;
180 			while (bytes) {
181 				fifostat.d32 = readl(g_sfc_reg + SFC_FSR);
182 				if (fifostat.b.rxlevel > 0) {
183 					u8 *p_data1 = (u8 *)p_data;
184 
185 					words = readl(g_sfc_reg + SFC_DATA);
186 					for (i = 0; i < bytes; i++)
187 						p_data1[i] =
188 						(u8)((words >> (i * 8)) & 0xFF);
189 					break;
190 				}
191 
192 				sfc_delay(1);
193 				if (timeout++ > 10000) {
194 					ret = SFC_RX_TIMEOUT;
195 					break;
196 				}
197 			}
198 		}
199 	}
200 
201 exit_wait:
202 	timeout = 0;    /* wait cmd or data send complete */
203 	while (readl(g_sfc_reg + SFC_SR) & SFC_BUSY) {
204 		sfc_delay(1);
205 		if (timeout++ > 100000) {         /* wait 100ms */
206 			ret = SFC_TX_TIMEOUT;
207 			break;
208 		}
209 	}
210 	sfc_delay(1); /* CS# High Time (read/write) >100ns */
211 	return ret;
212 }
213