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 #include "hifmc100.h"
17 #include "asm/platform.h"
18 #include "hisoc/flash.h"
19 #include "los_vm_phys.h"
20 #include "reset_shell.h"
21 #include "securec.h"
22
23 #include "device_resource_if.h"
24 #include "hdf_device_desc.h"
25 #include "hdf_log.h"
26 #include "mtd_core.h"
27 #include "mtd_spi_nor.h"
28 #include "osal_io.h"
29 #include "osal_mem.h"
30 #include "osal_mutex.h"
31 #include "platform_core.h"
32
33 #include "hifmc100_spi_nand.h"
34 #include "hifmc100_spi_nor.h"
35
36 #define HDF_LOG_TAG hifmc100
37
38 static struct HifmcCntlr *gHifmc100Cntlr = NULL;
39
HifmcCntlrReadSpiOp(struct MtdSpiConfig * cfg,const struct DeviceResourceNode * node)40 int32_t HifmcCntlrReadSpiOp(struct MtdSpiConfig *cfg, const struct DeviceResourceNode *node)
41 {
42 int32_t ret;
43 struct DeviceResourceIface *drsOps = NULL;
44
45 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
46 if (drsOps == NULL) {
47 HDF_LOGE("%s: invalid drs ops", __func__);
48 return HDF_ERR_NOT_SUPPORT;
49 }
50
51 ret = drsOps->GetUint8(node, "if_type", &cfg->ifType, 0);
52 if (ret != HDF_SUCCESS) {
53 HDF_LOGE("%s: read if type failed:%d", __func__, ret);
54 return ret;
55 }
56
57 ret = drsOps->GetUint8(node, "cmd", &cfg->cmd, 0);
58 if (ret != HDF_SUCCESS) {
59 HDF_LOGE("%s: read cmd failed:%d", __func__, ret);
60 return ret;
61 }
62
63 ret = drsOps->GetUint8(node, "dummy", &cfg->dummy, 0);
64 if (ret != HDF_SUCCESS) {
65 HDF_LOGE("%s: read dummy failed:%d", __func__, ret);
66 return ret;
67 }
68
69 ret = drsOps->GetUint32(node, "size", &cfg->size, 0);
70 if (ret != HDF_SUCCESS) {
71 HDF_LOGE("%s: read size failed:%d", __func__, ret);
72 return ret;
73 }
74
75 ret = drsOps->GetUint32(node, "clock", &cfg->clock, 0);
76 if (ret != HDF_SUCCESS) {
77 HDF_LOGE("%s: read clock failed:%d", __func__, ret);
78 return ret;
79 }
80 hifmc100_get_best_clock(&cfg->clock);
81
82 return HDF_SUCCESS;
83 }
84
HifmcCntlrGetDevTableNode(struct HifmcCntlr * cntlr)85 const struct DeviceResourceNode *HifmcCntlrGetDevTableNode(struct HifmcCntlr *cntlr)
86 {
87 struct DeviceResourceIface *drsOps = NULL;
88 const struct DeviceResourceNode *tableNode = NULL;
89
90 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
91 if (drsOps == NULL) {
92 HDF_LOGE("%s: invalid drs ops", __func__);
93 return NULL;
94 }
95
96 if (cntlr->flashType == HIFMC_CFG_TYPE_SPI_NOR) {
97 tableNode = drsOps->GetChildNode(cntlr->drsNode, "spi_nor_dev_table");
98 } else {
99 tableNode = drsOps->GetChildNode(cntlr->drsNode, "spi_nand_dev_table");
100 }
101
102 if (tableNode == NULL) {
103 HDF_LOGE("%s: dev table not found!", __func__);
104 }
105 return tableNode;
106 }
107
HifmcCntlrSearchDevInfo(struct HifmcCntlr * cntlr,struct SpiFlash * spi)108 static int32_t HifmcCntlrSearchDevInfo(struct HifmcCntlr *cntlr, struct SpiFlash *spi)
109 {
110 if (cntlr->flashType == HIFMC_CFG_TYPE_SPI_NOR) {
111 return HifmcCntlrSearchSpinorInfo(cntlr, spi);
112 } else {
113 return HifmcCntlrSearchSpinandInfo(cntlr, spi);
114 }
115 }
116
HifmcCntlrReadDrs(struct HifmcCntlr * cntlr)117 static int32_t HifmcCntlrReadDrs(struct HifmcCntlr *cntlr)
118 {
119 int32_t ret;
120 struct DeviceResourceIface *drsOps = NULL;
121 const struct DeviceResourceNode *node = NULL;
122
123 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
124 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
125 HDF_LOGE("%s: invalid drs ops", __func__);
126 return HDF_ERR_NOT_SUPPORT;
127 }
128
129 node = cntlr->drsNode;
130 ret = drsOps->GetUint32(node, "regBase", &cntlr->regBasePhy, 0);
131 if (ret != HDF_SUCCESS) {
132 HDF_LOGE("%s: read reg base fail:%d", __func__, ret);
133 return ret;
134 }
135 ret = drsOps->GetUint32(node, "regSize", &cntlr->regSize, 0);
136 if (ret != HDF_SUCCESS) {
137 HDF_LOGE("%s: read reg size fail:%d", __func__, ret);
138 return ret;
139 }
140 ret = drsOps->GetUint32(node, "memBase", &cntlr->memBasePhy, 0);
141 if (ret != HDF_SUCCESS) {
142 HDF_LOGE("%s: read mem base fail:%d", __func__, ret);
143 return ret;
144 }
145 ret = drsOps->GetUint32(node, "memSize", &cntlr->memSize, 0);
146 if (ret != HDF_SUCCESS) {
147 HDF_LOGE("%s: read mem size fail:%d", __func__, ret);
148 return ret;
149 }
150
151 cntlr->regBase = OsalIoRemap(cntlr->regBasePhy, cntlr->regSize);
152 if (cntlr->regBase == NULL) {
153 HDF_LOGE("%s: remap reg base fail", __func__);
154 return HDF_ERR_IO;
155 }
156
157 cntlr->memBase = OsalIoRemap(cntlr->memBasePhy, cntlr->memSize);
158 if (cntlr->memBase == NULL) {
159 HDF_LOGE("%s: remap mem base fail", __func__);
160 OsalIoUnmap((void *)cntlr->regBase);
161 return HDF_ERR_IO;
162 }
163 return HDF_SUCCESS;
164 }
165
HifmcCntlrInitFlashType(struct HifmcCntlr * cntlr,unsigned int flashType)166 static int32_t HifmcCntlrInitFlashType(struct HifmcCntlr *cntlr, unsigned int flashType)
167 {
168 unsigned int reg;
169
170 reg = HIFMC_REG_READ(cntlr, HIFMC_CFG_REG_OFF);
171 HDF_LOGD("%s: before init reg = 0x%x, flashType = %u", __func__,
172 reg, (reg & HIFMC_CFG_TYPE_MASK) >> HIFMC_CFG_TYPE_SHIFT);
173
174 if (flashType != HIFMC_CFG_TYPE_SPI_NOR && flashType != HIFMC_CFG_TYPE_SPI_NAND) {
175 HDF_LOGE("%s: invalid flash type:%u", __func__, flashType);
176 return HDF_ERR_NOT_SUPPORT;
177 }
178 reg &= (~HIFMC_CFG_TYPE_MASK);
179 reg |= HIFMC_CFG_TYPE_SEL(flashType);
180
181 reg &= (~HIFMC_OP_MODE_MASK);
182 reg |= HIFMC_CFG_OP_MODE(HIFMC_OP_MODE_NORMAL);
183
184 HIFMC_REG_WRITE(cntlr, reg, HIFMC_CFG_REG_OFF);
185 cntlr->cfg = reg;
186
187 // read back and check
188 reg = HIFMC_REG_READ(cntlr, HIFMC_CFG_REG_OFF);
189 if ((reg & HIFMC_CFG_TYPE_MASK) != HIFMC_CFG_TYPE_SEL(flashType)) {
190 HDF_LOGE("%s: flash select failed, reg = 0x%x", __func__, reg);
191 return HDF_ERR_IO;
192 }
193 if ((reg & HIFMC_OP_MODE_MASK) != HIFMC_CFG_OP_MODE(HIFMC_OP_MODE_NORMAL)) {
194 HDF_LOGE("%s: op mode set failed, reg = 0x%x", __func__, reg);
195 return HDF_ERR_IO;
196 }
197 HDF_LOGD("%s: after init reg = 0x%x, flashType = %u", __func__,
198 reg, (reg & HIFMC_CFG_TYPE_MASK) >> HIFMC_CFG_TYPE_SHIFT);
199
200 return HDF_SUCCESS;
201 }
202
HifmcCntlrReadDevReg(struct HifmcCntlr * cntlr,struct SpiFlash * spi,uint8_t cmd)203 uint8_t HifmcCntlrReadDevReg(struct HifmcCntlr *cntlr, struct SpiFlash *spi, uint8_t cmd)
204 {
205 if (cntlr->flashType == HIFMC_CFG_TYPE_SPI_NOR) {
206 return HifmcCntlrReadSpinorReg(cntlr, spi, cmd);
207 } else {
208 return HifmcCntlrReadSpinandReg(cntlr, spi, cmd);
209 }
210 }
211
HifmcCntlrSet4AddrMode(struct HifmcCntlr * cntlr,int enable)212 void HifmcCntlrSet4AddrMode(struct HifmcCntlr *cntlr, int enable)
213 {
214 unsigned int reg;
215
216 reg = HIFMC_REG_READ(cntlr, HIFMC_CFG_REG_OFF);
217 if (enable == 1) {
218 reg |= HIFMC_SPI_NOR_ADDR_MODE_MASK;
219 } else {
220 reg &= ~HIFMC_SPI_NOR_ADDR_MODE_MASK;
221 }
222
223 HIFMC_REG_WRITE(cntlr, reg, HIFMC_CFG_REG_OFF);
224 }
225
HifmcCntlrInitBeforeScan(struct HifmcCntlr * cntlr)226 static int32_t HifmcCntlrInitBeforeScan(struct HifmcCntlr *cntlr)
227 {
228 int32_t ret;
229 unsigned int reg;
230 unsigned int flashType;
231
232 (void)OsalMutexInit(&cntlr->mutex);
233
234 reg = HIFMC_REG_READ(cntlr, HIFMC_CFG_REG_OFF);
235 flashType = (reg & HIFMC_CFG_TYPE_MASK) >> HIFMC_CFG_TYPE_SHIFT;
236 ret = HifmcCntlrInitFlashType(cntlr, flashType);
237
238 (void)HifmcCntlrSetSysClock(cntlr, 0, 1); // 0: default clock 1: enable
239
240 if (flashType == HIFMC_CFG_TYPE_SPI_NAND) {
241 // close global write protection
242 reg = HIFMC_REG_READ(cntlr, HIFMC_GLOBAL_CFG_REG_OFF);
243 reg &= ~HIFMC_GLOBAL_CFG_WP_ENABLE;
244 HIFMC_REG_WRITE(cntlr, reg, HIFMC_GLOBAL_CFG_REG_OFF);
245 }
246
247 reg = HIFMC_SPI_TIMING_CFG_TCSH(HIFMC_SPI_CFG_CS_HOLD)
248 | HIFMC_SPI_TIMING_CFG_TCSS(HIFMC_SPI_CFG_CS_SETUP)
249 | HIFMC_SPI_TIMING_CFG_TSHSL(HIFMC_SPI_CFG_CS_DESELECT);
250 HIFMC_REG_WRITE(cntlr, reg, HIFMC_SPI_TIMING_CFG_REG_OFF);
251
252 reg = HIFMC_ALL_BURST_ENABLE;
253 HIFMC_REG_WRITE(cntlr, reg, HIFMC_DMA_AHB_CTRL_REG_OFF);
254
255 cntlr->flashType = flashType;
256 HDF_LOGI("%s: cntlr init done, flash type = %u", __func__, flashType);
257
258 return ret;
259 }
260
HifmcCntlrInitAfterScan(struct HifmcCntlr * cntlr)261 static int32_t HifmcCntlrInitAfterScan(struct HifmcCntlr *cntlr)
262 {
263 int32_t ret;
264
265 if (cntlr->flashType == HIFMC_CFG_TYPE_SPI_NOR) {
266 cntlr->buffer = OsalMemAllocAlign(HIFMC_DMA_ALIGN_SIZE,
267 ALIGN(HIFMC_DMA_ALIGN_SIZE, HIFMC_DMA_ALIGN_SIZE));
268 if (cntlr->buffer == NULL) {
269 HDF_LOGE("%s: alloc buffer fail", __func__);
270 return HDF_ERR_MALLOC_FAIL;
271 }
272 cntlr->bufferSize = ALIGN(HIFMC_DMA_ALIGN_SIZE, HIFMC_DMA_ALIGN_SIZE);
273 } else {
274 ret = HifmcCntlrInitOob(cntlr, cntlr->curDev);
275 if (ret != HDF_SUCCESS) {
276 return ret;
277 }
278
279 cntlr->buffer = OsalMemAllocAlign(HIFMC_DMA_ALIGN_SIZE,
280 ALIGN(cntlr->pageSize + cntlr->oobSize, HIFMC_DMA_ALIGN_SIZE));
281 if (cntlr->buffer == NULL) {
282 HDF_LOGE("%s: alloc buffer fail", __func__);
283 return HDF_ERR_MALLOC_FAIL;
284 }
285 cntlr->bufferSize = ALIGN(cntlr->pageSize + cntlr->oobSize, HIFMC_DMA_ALIGN_SIZE);
286 }
287 cntlr->dmaBuffer = cntlr->buffer;
288 HDF_LOGD("%s: cntlr flashType = %u", __func__, cntlr->flashType);
289 HDF_LOGD("%s: cntlr regBase=%p(phyBase:0x%x)", __func__, cntlr->regBase, cntlr->regBasePhy);
290 HDF_LOGD("%s: cntlr memBase=%p)", __func__, cntlr->memBase);
291 HDF_LOGD("%s: cntlr buffer=%p, dmaBuffer=0x%p)", __func__, cntlr->buffer, cntlr->dmaBuffer);
292 HDF_LOGD("%s: cntlr cfg=0x%x)", __func__, cntlr->cfg);
293 HDF_LOGD("%s: cntlr pageSize=%zu)", __func__, cntlr->pageSize);
294 HDF_LOGD("%s: cntlr oobSize=%zu)", __func__, cntlr->oobSize);
295 HDF_LOGD("%s: cntlr eccType=%d)", __func__, cntlr->eccType);
296 return HDF_SUCCESS;
297 }
298
HifmcCntlrUninit(struct HifmcCntlr * cntlr)299 static void HifmcCntlrUninit(struct HifmcCntlr *cntlr)
300 {
301 (void)OsalMutexDestroy(&cntlr->mutex);
302 }
303
HifmcCntlrReadId(struct HifmcCntlr * cntlr,uint8_t cs,uint8_t * id,size_t len)304 static int32_t HifmcCntlrReadId(struct HifmcCntlr *cntlr, uint8_t cs, uint8_t *id, size_t len)
305 {
306 if (cntlr->flashType == HIFMC_CFG_TYPE_SPI_NOR) {
307 return HifmcCntlrReadIdSpiNor(cntlr, cs, id, len);
308 } else {
309 return HifmcCntlrReadIdSpiNand(cntlr, cs, id, len);
310 }
311 }
312
HifmcCntlrInitSpiFlash(struct HifmcCntlr * cntlr,struct SpiFlash * spi)313 static int32_t HifmcCntlrInitSpiFlash(struct HifmcCntlr *cntlr, struct SpiFlash *spi)
314 {
315 if (cntlr->flashType == HIFMC_CFG_TYPE_SPI_NOR) {
316 return HifmcCntlrInitSpinorDevice(cntlr, spi);
317 } else {
318 return HifmcCntlrInitSpinandDevice(cntlr, spi);
319 }
320 }
321
HifmcCntlrMtdScan(struct HifmcCntlr * cntlr)322 static int32_t HifmcCntlrMtdScan(struct HifmcCntlr *cntlr)
323 {
324 int32_t ret;
325 struct SpiFlash *spi = NULL;
326
327 spi = (struct SpiFlash *)OsalMemCalloc(sizeof(*spi));
328 if (spi == NULL) {
329 HDF_LOGE("%s: alloc spi flash fail", __func__);
330 return HDF_ERR_MALLOC_FAIL;
331 }
332 spi->cs = 0; // default cs num
333 spi->mtd.cntlr = cntlr;
334
335 // read id
336 ret = HifmcCntlrReadId(cntlr, spi->cs, spi->mtd.id, sizeof(spi->mtd.id));
337 if (ret != HDF_SUCCESS) {
338 OsalMemFree(spi);
339 return ret;
340 }
341
342 // search flash info from ids table or read from hcs
343 ret = HifmcCntlrSearchDevInfo(cntlr, spi);
344 if (ret != HDF_SUCCESS) {
345 OsalMemFree(spi);
346 return ret;
347 }
348
349 // init spi flash device
350 ret = HifmcCntlrInitSpiFlash(cntlr, spi);
351 if (ret != HDF_SUCCESS) {
352 OsalMemFree(spi);
353 return ret;
354 }
355 cntlr->curDev = spi;
356
357 return HDF_SUCCESS;
358 }
359
HifmcCntlrShutDown(void)360 void HifmcCntlrShutDown(void)
361 {
362 if (gHifmc100Cntlr != NULL) {
363 (void)OsalMutexLock(&gHifmc100Cntlr->mutex);
364 }
365 }
366
HifmcInit(struct HdfDeviceObject * device)367 static int32_t HifmcInit(struct HdfDeviceObject *device)
368 {
369 int32_t ret;
370 struct HifmcCntlr *cntlr = NULL;
371
372 HDF_LOGI("%s: Enter", __func__);
373 if (device == NULL || device->property == NULL) {
374 HDF_LOGE("%s: device or property is NULL", __func__);
375 return HDF_ERR_INVALID_OBJECT;
376 }
377
378 cntlr = (struct HifmcCntlr *)OsalMemCalloc(sizeof(*cntlr));
379 if (cntlr == NULL) {
380 HDF_LOGE("%s: alloc controller fail", __func__);
381 return HDF_ERR_MALLOC_FAIL;
382 }
383 cntlr->drsNode = device->property;
384
385 ret = HifmcCntlrReadDrs(cntlr);
386 if (ret != HDF_SUCCESS) {
387 goto __OUT;
388 }
389
390 ret = HifmcCntlrInitBeforeScan(cntlr);
391 if (ret != HDF_SUCCESS) {
392 goto __OUT;
393 }
394
395 ret = HifmcCntlrMtdScan(cntlr);
396 if (ret != HDF_SUCCESS) {
397 goto __OUT;
398 }
399
400 ret = HifmcCntlrInitAfterScan(cntlr);
401 if (ret != HDF_SUCCESS) {
402 goto __OUT;
403 }
404
405 ret = SpiFlashAdd(cntlr->curDev);
406 if (ret != HDF_SUCCESS) {
407 goto __OUT;
408 }
409
410 gHifmc100Cntlr = cntlr;
411
412 #ifdef LOSCFG_SHELL
413 (void)osReHookFuncAdd((STORAGE_HOOK_FUNC)HifmcCntlrShutDown, NULL);
414 #endif
415
416 return HDF_SUCCESS;
417
418 __OUT:
419 if (cntlr->curDev != NULL) {
420 OsalMemFree(cntlr->curDev);
421 }
422 OsalMemFree(cntlr);
423 HDF_LOGI("%s: Exit, ret=%d", __func__, ret);
424 return ret;
425 }
426
HifmcRelease(struct HdfDeviceObject * device)427 static void HifmcRelease(struct HdfDeviceObject *device)
428 {
429 HDF_LOGI("%s: enter", __func__);
430
431 (void)device;
432 if (gHifmc100Cntlr == NULL) {
433 return;
434 }
435
436 if (gHifmc100Cntlr->curDev != NULL) {
437 SpiFlashDel(gHifmc100Cntlr->curDev);
438 OsalMemFree(gHifmc100Cntlr->curDev);
439 }
440
441 HifmcCntlrUninit(gHifmc100Cntlr);
442 OsalMemFree(gHifmc100Cntlr);
443 gHifmc100Cntlr = NULL;
444 }
445
446 struct HdfDriverEntry g_hifmc100DriverEntry = {
447 .moduleVersion = 1,
448 .Init = HifmcInit,
449 .Release = HifmcRelease,
450 .moduleName = "hifmc100_driver",
451 };
452 HDF_INIT(g_hifmc100DriverEntry);
453