• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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