1 /*
2 * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef HIFMC100_H
17 #define HIFMC100_H
18
19 #include "hdf_base.h"
20 #include "mtd_spi_common.h"
21 #include "osal_mutex.h"
22 #include "osal_io.h"
23 #include "hisoc/flash.h"
24
25 struct HifmcCntlr {
26 volatile void *regBase;
27 uint32_t regBasePhy;
28 uint32_t regSize;
29 volatile uint8_t *memBase;
30 uint32_t memBasePhy;
31 uint32_t memSize;
32 uint8_t *buffer;
33 uint8_t *dmaBuffer;
34 size_t bufferSize;
35 int32_t chipNum;
36 unsigned int flashType;
37 struct OsalMutex mutex;
38 size_t pageSize;
39 size_t oobSize;
40 int eccType;
41 struct SpiFlash *curDev;
42 unsigned int cfg;
43 const struct DeviceResourceNode *drsNode;
44 };
45
46 #define HIFMC_SPI_NOR_CS_NUM 0
47
48 #define HIFMC_DMA_ALIGN_SIZE (CACHE_ALIGNED_SIZE)
49 #define HIFMC_DMA_ALIGN_MASK (HIFMC_DMA_ALIGN_SIZE - 1)
50 #define HIFMC_DMA_MAX_SIZE 4096
51 #define HIFMC_DMA_MAX_MASK (HIFMC_DMA_MAX_SIZE - 1)
52
53 #define HIFMC_REG_READ(_cntlr, _reg) \
54 OSAL_READL((uintptr_t)((uint8_t *)(_cntlr)->regBase + (_reg)))
55
56 #define HIFMC_REG_WRITE(_cntlr, _value, _reg) \
57 OSAL_WRITEL((unsigned long)(_value), (uintptr_t)((uint8_t *)(_cntlr)->regBase + (_reg)))
58
59 // ********* 0x0000 FMC_CFG ****************************************************************
60 #define HIFMC_CFG_REG_OFF 0x00
61 #define HIFMC_CFG_SPI_NAND_SEL(type) (((type) & 0x3) << 11)
62 #define HIFMC_CFG_SPI_NOR_ADDR_MODE(mode) ((mode) << 10)
63 #define HIFMC_CFG_BLOCK_SIZE(size) (((size) & 0x3) << 8)
64 #define HIFMC_CFG_OP_MODE(mode) ((mode) & 0x1)
65
66 #define HIFMC_SPI_NOR_ADDR_MODE_SHIFT 10
67 #define HIFMC_SPI_NOR_ADDR_MODE_MASK (0x1 << HIFMC_SPI_NOR_ADDR_MODE_SHIFT)
68
69 // option mode
70 #define HIFMC_OP_MODE_BOOT 0x0
71 #define HIFMC_OP_MODE_NORMAL 0x1
72 #define HIFMC_OP_MODE_MASK 0x1
73
74 // page config
75 #define HIFMC_PAGE_SIZE_SHIFT 3
76 #define HIFMC_PAGE_SIZE_MASK (0x3 << HIFMC_PAGE_SIZE_SHIFT)
77 #define HIFMC_CFG_PAGE_SIZE(size) (((size) & 0x3) << HIFMC_PAGE_SIZE_SHIFT)
78
79 // ecc config
80 #define HIFMC_ECC_TYPE_SHIFT 5
81 #define HIFMC_ECC_TYPE_MASK (0x7 << HIFMC_ECC_TYPE_SHIFT)
82 #define HIFMC_CFG_ECC_TYPE(type) (((type) & 0x7) << 5)
83
84 // others
85 #define HIFMC_CFG_TYPE_SHIFT 1
86 #define HIFMC_CFG_TYPE_MASK (0x3 << HIFMC_CFG_TYPE_SHIFT)
87 #define HIFMC_CFG_TYPE_SEL(type) (((type) & 0x3) << HIFMC_CFG_TYPE_SHIFT)
88 #define HIFMC_CFG_TYPE_SPI_NOR 0x0
89 #define HIFMC_CFG_TYPE_SPI_NAND 0x1
90 #define HIFMC_CFG_TYPE_NAND 0x2
91 #define HIFMC_CFG_TYPE_DEFAULT 0x3
92
93 enum HifmcPageSizeRegConfig {
94 HIFMC_PAGE_SIZE_2K = 0x0,
95 HIFMC_PAGE_SIZE_4K = 0x1,
96 HIFMC_PAGE_SIZE_8K = 0x2,
97 HIFMC_PAGE_SIZE_16K = 0x3,
98 };
99
100 enum HifmcEccTypeRegConfig {
101 HIFMC_ECC_0BIT = 0x00,
102 HIFMC_ECC_8BIT = 0x01,
103 HIFMC_ECC_16BIT = 0x02,
104 HIFMC_ECC_24BIT = 0x03,
105 HIFMC_ECC_28BIT = 0x04,
106 HIFMC_ECC_40BIT = 0x05,
107 HIFMC_ECC_64BIT = 0x06,
108 };
109
110 // ********* 0x0004 GLOBAL_CFG ************************************************************
111 #define HIFMC_GLOBAL_CFG_REG_OFF 0x4
112 #define HIFMC_GLOBAL_CFG_WP_ENABLE (1 << 6)
113
114 // ********* 0x0008 TIMING_SPI_CFG ********************************************************
115 #define HIFMC_SPI_TIMING_CFG_REG_OFF 0x08
116 #define HIFMC_SPI_TIMING_CFG_TCSH(n) (((n) & 0xf) << 8)
117 #define HIFMC_SPI_TIMING_CFG_TCSS(n) (((n) & 0xf) << 4)
118 #define HIFMC_SPI_TIMING_CFG_TSHSL(n) ((n) & 0xf)
119 #define HIFMC_SPI_CFG_CS_HOLD 0x6
120 #define HIFMC_SPI_CFG_CS_SETUP 0x6
121 #define HIFMC_SPI_CFG_CS_DESELECT 0xf
122
123 // ********* 0x0018 FMC_INT ***************************************************************
124 #define HIFMC_INT_REG_OFF 0x18
125 #define HIFMC_INT_AHB_OP (1 << 7)
126 #define HIFMC_INT_WR_LOCK (1 << 6)
127 #define HIFMC_INT_DMA_ERR (1 << 5)
128 #define HIFMC_INT_ERR_ALARM (1 << 4)
129 #define HIFMC_INT_ERR_INVALID (1 << 3)
130 #define HIFMC_INT_ERR_VALID (1 << 2)
131 #define HIFMC_INT_OP_FAIL (1 << 1)
132 #define HIFMC_INT_OP_DONE (1 << 0)
133
134 // ********* 0x001c FMC_INT_EN ************************************************************
135 #define HIFMC_INT_EN_REG_OFF 0x1c
136 #define HIFMC_INT_EN_AHB_OP (1 << 7)
137 #define HIFMC_INT_EN_WR_LOCK (1 << 6)
138 #define HIFMC_INT_EN_DMA_ERR (1 << 5)
139 #define HIFMC_INT_EN_ERR_ALARM (1 << 4)
140 #define HIFMC_INT_EN_ERR_INVALID (1 << 3)
141 #define HIFMC_INT_EN_ERR_VALID (1 << 2)
142 #define HIFMC_INT_EN_OP_FAIL (1 << 1)
143 #define HIFMC_INT_EN_OP_DONE (1 << 0)
144
145 // ********* 0x0020 FMC_INT_CLR ***********************************************************
146 #define HIFMC_INT_CLR_REG_OFF 0x20
147 #define HIFMC_INT_CLR_AHB_OP (1 << 7)
148 #define HIFMC_INT_CLR_WR_LOCK (1 << 6)
149 #define HIFMC_INT_CLR_DMA_ERR (1 << 5)
150 #define HIFMC_INT_CLR_ERR_ALARM (1 << 4)
151 #define HIFMC_INT_CLR_ERR_INVALID (1 << 3)
152 #define HIFMC_INT_CLR_ERR_VALID (1 << 2)
153 #define HIFMC_INT_CLR_OP_FAIL (1 << 1)
154 #define HIFMC_INT_CLR_OP_DONE (1 << 0)
155 #define HIFMC_INT_CLR_ALL 0xff
156
157 // ********* 0x0024 FMC_CMD ***************************************************************
158 #define HIFMC_CMD_REG_OFF 0x24
159 #define HIFMC_CMD_CMD1(cmd) ((cmd) & 0xff)
160 #define HIFMC_CMD_CMD2(cmd) (((cmd) & 0xff) << 8)
161
162 // ********* 0x0028 FMC_ADDRH *************************************************************
163 #define HIFMC_ADDRH_REG_OFF 0x28
164 // ********* 0x002c FMC_ADDRL *************************************************************
165 #define HIFMC_ADDRL_REG_OFF 0x2c
166
167 // ********* 0x0030 FMC_OP_CFG ************************************************************
168 #define HIFMC_OP_CFG_REG_OFF 0x30
169 #define HIFMC_OP_CFG_FM_CS(cs) ((cs) << 11)
170 #define HIFMC_OP_CFG_FORCE_CS_EN(en) ((en) << 10)
171 #define HIFMC_OP_CFG_MEM_IF_TYPE(type) (((type) & 0x7) << 7)
172 #define HIFMC_OP_CFG_ADDR_NUM(addr) (((addr) & 0x7) << 4)
173 #define HIFMC_OP_CFG_DUMMY_NUM(dummy) ((dummy) & 0xf)
174
175 // ********* 0x0034 SPI_OP_ADDR ***********************************************************
176 #define HIFMC_SPI_OP_ADDR_REG_OFF 0x34
177
178 // ********* 0x0038 FMC_DATA_NUM **********************************************************
179 #define HIFMC_DATA_NUM_REG_OFF 0x38
180 #define HIFMC_DATA_NUM_CNT(n) ((n) & 0x3fff)
181
182 // ********* 0x003c FMC_OP ****************************************************************
183 #define HIFMC_OP_REG_OFF 0x3c
184 #define HIFMC_OP_DUMMY_EN(en) ((en) << 8)
185 #define HIFMC_OP_CMD1_EN(en) ((en) << 7)
186 #define HIFMC_OP_ADDR_EN(en) ((en) << 6)
187 #define HIFMC_OP_WRITE_DATA_EN(en) ((en) << 5)
188 #define HIFMC_OP_CMD2_EN(en) ((en) << 4)
189 #define HIFMC_OP_WAIT_READY_EN(en) ((en) << 3)
190 #define HIFMC_OP_READ_DATA_EN(en) ((en) << 2)
191 #define HIFMC_OP_READ_STATUS_EN(en) ((en) << 1)
192 #define HIFMC_OP_REG_OP_START 1
193
194 // ********* 0x0040 FMC_DATA_LEN **********************************************************
195 #define HIFMC_DMA_LEN_REG_OFF 0x40
196 #define HIFMC_DMA_LEN_SET(len) ((len) & 0x0fffffff)
197
198 // ********* 0x0048 FMC_DMA_AHB_CTRL ******************************************************
199 #define HIFMC_DMA_AHB_CTRL_REG_OFF 0x48
200 #define HIFMC_DMA_AHB_CTRL_DMA_PP_EN (1 << 3)
201 #define HIFMC_DMA_AHB_CTRL_BURST16_EN (1 << 2)
202 #define HIFMC_DMA_AHB_CTRL_BURST8_EN (1 << 1)
203 #define HIFMC_DMA_AHB_CTRL_BURST4_EN (1 << 0)
204 #define HIFMC_ALL_BURST_ENABLE (HIFMC_DMA_AHB_CTRL_BURST16_EN \
205 | HIFMC_DMA_AHB_CTRL_BURST8_EN \
206 | HIFMC_DMA_AHB_CTRL_BURST4_EN)
207
208 // ********* 0x004c FMC_DMA_SADDR_D0 ******************************************************
209 #define HIFMC_DMA_SADDR_D0_REG_OFF 0x4c
210 #define HIFMC_DMA_SADDRH_D0 0x200
211 #define HIFMC_DMA_SADDRH_OOB_OOFSET 0x210
212 #define HIFMC_DMA_ADDR_OFFSET 4096
213
214 // ********* 0x005c FMC_DMA_SADDR_OOB *****************************************************
215 #define HIFMC_DMA_SADDR_OOB_REG_OFF 0x5c
216
217 // ********* 0x0068 FMC_OP_CTRL ***********************************************************
218 #define HIFMC_OP_CTRL_REG_OFF 0x68
219 #define HIFMC_OP_CTRL_RD_OPCODE(code) (((code) & 0xff) << 16)
220 #define HIFMC_OP_CTRL_WR_OPCODE(code) (((code) & 0xff) << 8)
221 #define HIFMC_OP_CTRL_RW_OP(op) ((op) << 1)
222 #define HIFMC_OP_CTRL_RD_OP_SEL(op) (((op) & 0x3) << 4)
223 #define HIFMC_OP_CTRL_DMA_OP(type) ((type) << 2)
224 #define HIFMC_OP_CTRL_DMA_OP_READY 1
225 #define HIFMC_OP_CTRL_TYPE_DMA 0
226 #define HIFMC_OP_CTRL_TYPE_REG 1
227 #define HIFMC_OP_CTRL_OP_READ 0
228 #define HIFMC_OP_CTRL_OP_WRITE 1
229
230 // ********* 0x006c FMC_TIMEOUT_WR ********************************************************
231
232 // ********* 0x0070 FMC_OP_PARA ***********************************************************
233 #define HIFMC_OP_PARA_REG_OFF 0x70
234 #define HIFMC_OP_PARA_RD_OOB_ONLY (1 << 1)
235
236 // ********* 0x0074 FMC_BOOT_SEL **********************************************************
237 #define HIFMC_BOOT_SET_REG_OFF 0x74
238 #define HIFMC_BOOT_SET_DEVICE_ECC_EN (1 << 3)
239 #define HIFMC_BOOT_SET_BOOT_QUAD_EN (1 << 1)
240
241 // ********* 0x0078 FMC_LP_CTRL ***********************************************************
242
243 // ********* 0x00a8 FMC_ERR_THD ***********************************************************
244
245 // ********* 0x00ac FMC_FLASH_INFO ********************************************************
246 #define HIFMC_FLASH_INFO_REG_OFF 0xac
247
248 // ********* 0x00bc FMC_VERSION ***********************************************************
249 #define HIFMC_VERSION_REG_OFF 0xbc
250
251 // ********* 0x00c0 FMC_ERR_NUM0_BUF0 *****************************************************
252
253 // ********* 0x00d0 FMC_ERR_ALARM_ADDRH ***************************************************
254
255 // ********* 0x00d4 FMC_ERR_ALARM_ADDRL ***************************************************
256
257 // ********* 0x00d8 FMC_ECC_INVALID_ADDRH *************************************************
258
259 // ********* 0x00dc FMC_ECC_INVALID_ADDRL *************************************************
260
261 #define HIFMC_CPU_WAIT_TIMEOUT 0x800000
262 #define HIFMC_DMA_WAIT_TIMEOUT 0xf0000000
263
264 #define HIFMC_CMD_WAIT_CPU_FINISH(cntlr) \
265 do { \
266 unsigned int regval, timeout = HIFMC_CPU_WAIT_TIMEOUT; \
267 do { \
268 regval = HIFMC_REG_READ((cntlr), HIFMC_OP_REG_OFF); \
269 --timeout; \
270 } while ((regval & HIFMC_OP_REG_OP_START) && timeout); \
271 if (!timeout) \
272 HDF_LOGE("%s: wait cmd cpu finish timeout(0x%x)", __func__, regval); \
273 } while (0)
274
275
276 #define HIFMC_DMA_WAIT_INT_FINISH(cntlr) \
277 do { \
278 unsigned int regval, timeout = HIFMC_DMA_WAIT_TIMEOUT; \
279 do { \
280 regval = HIFMC_REG_READ((cntlr), HIFMC_INT_REG_OFF); \
281 --timeout; \
282 } while (!(regval & HIFMC_INT_OP_DONE) && timeout); \
283 if (!timeout) \
284 HDF_LOGE("%s: wait dma int finish timeout(0x%x)", __func__, regval); \
285 } while (0)
286
287 #define HIFMC_DMA_WAIT_CPU_FINISH(cntlr) \
288 do { \
289 unsigned long regval, timeout = HIFMC_CPU_WAIT_TIMEOUT; \
290 do { \
291 regval = HIFMC_REG_READ((cntlr), HIFMC_OP_CTRL_REG_OFF); \
292 --timeout; \
293 } while ((regval & HIFMC_OP_CTRL_DMA_OP_READY) && timeout); \
294 if (!timeout) \
295 HDF_LOGE("%s: wait dma cpu finish timeout(0x%x)", __func__, regval); \
296 } while (0)
297
298 uint8_t HifmcCntlrReadDevReg(struct HifmcCntlr *cntlr, struct SpiFlash *spi, uint8_t cmd);
299
300 void HifmcCntlrSet4AddrMode(struct HifmcCntlr *cntlr, int enable);
301
302 const struct DeviceResourceNode *HifmcCntlrGetDevTableNode(struct HifmcCntlr *cntlr);
303
304 int32_t HifmcCntlrReadSpiOp(struct MtdSpiConfig *cfg, const struct DeviceResourceNode *node);
305
HifmcCntlrSetSysClock(struct HifmcCntlr * cntlr,unsigned int clock,int clkEn)306 static inline int32_t HifmcCntlrSetSysClock(struct HifmcCntlr *cntlr, unsigned int clock, int clkEn)
307 {
308 (void)cntlr;
309 hifmc100_set_system_clock(clock, clkEn);
310 return HDF_SUCCESS;
311 }
312
313 void MtdDmaCacheClean(void *addr, size_t size);
314
315 void MtdDmaCacheInv(void *addr, size_t size);
316
317 #endif /* HIFMC100_H */
318