1 /*
2 * Copyright (c) 2022 HPMicro
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 <hpm_clock_drv.h>
17 #include <stdio.h>
18 #include <los_interrupt.h>
19 #include "hpm_littlefs_drv.h"
20 #include "hpm_csr_regs.h"
21 #include "hpm_l1c_drv.h"
22
23 extern struct HpmLittlefsCfg g_hpmLittlefsCfgs[];
24
HpmLittlefsRead(int partition,UINT32 * offset,void * buf,UINT32 size)25 int HpmLittlefsRead(int partition, UINT32 *offset, void *buf, UINT32 size)
26 {
27 struct HpmLittleCtx *ctx = &g_hpmLittlefsCfgs[partition].ctx;
28 XPI_Type *base = (XPI_Type *)ctx->base;
29 uint32_t chipOffset = *offset;
30
31 uint32_t intSave = LOS_IntLock();
32 hpm_stat_t status = rom_xpi_nor_read(base, xpi_xfer_channel_auto,
33 &ctx->xpiNorConfig, (uint32_t *)buf, chipOffset, size);
34 __asm volatile("fence.i");
35 LOS_IntRestore(intSave);
36 if (status != status_success) {
37 printf("[%s]: read addr: %u, size: %u failed!!!\n", ctx->mountPoint, chipOffset, size);
38 return -1;
39 }
40 return 0;
41 }
42
43
HpmLittlefsProg(int partition,UINT32 * offset,const void * buf,UINT32 size)44 int HpmLittlefsProg(int partition, UINT32 *offset, const void *buf, UINT32 size)
45 {
46 struct HpmLittleCtx *ctx = &g_hpmLittlefsCfgs[partition].ctx;
47 XPI_Type *base = (XPI_Type *)ctx->base;
48 uint32_t chipOffset = *offset;
49
50 uint32_t intSave = LOS_IntLock();
51 hpm_stat_t status = rom_xpi_nor_program(base, xpi_xfer_channel_auto,
52 &ctx->xpiNorConfig, (const uint32_t *)buf, chipOffset, size);
53
54 __asm volatile("fence.i"); /* mandatory, very important!!! */
55 LOS_IntRestore(intSave);
56
57 if (status != status_success) {
58 printf("[%s]: program addr: %u, size: %u failed!!!\n", ctx->mountPoint, chipOffset, size);
59 return -1;
60 }
61 return 0;
62 }
63
HpmLittlefsErase(int partition,UINT32 offset,UINT32 size)64 int HpmLittlefsErase(int partition, UINT32 offset, UINT32 size)
65 {
66 struct HpmLittleCtx *ctx = &g_hpmLittlefsCfgs[partition].ctx;
67 XPI_Type *base = (XPI_Type *)ctx->base;
68 uint32_t chipOffset = offset;
69
70 uint32_t intSave = LOS_IntLock();
71 hpm_stat_t status = rom_xpi_nor_erase_sector(base, xpi_xfer_channel_auto, &ctx->xpiNorConfig, chipOffset);
72 __asm volatile("fence.i"); /* mandatory, very important!!! */
73 LOS_IntRestore(intSave);
74 if (status != status_success) {
75 printf("[%s]: erase addr: %u, size: %u failed!!!\n", ctx->mountPoint, chipOffset, size);
76 return -1;
77 }
78
79 return 0;
80 }
81
82
83 #define HPMICRO_FLASH_SELFTEST_ENABLE 0
84
85 #if HPMICRO_FLASH_SELFTEST_ENABLE == 1
86
87 static uint8_t rbuf[4096];
88 static uint8_t wbuf[4096];
89
SelfTest(struct HpmLittlefsCfg * lfsPart)90 static void SelfTest(struct HpmLittlefsCfg *lfsPart)
91 {
92 struct HpmLittleCtx *ctx = &lfsPart->ctx;
93 struct PartitionCfg *cfg = &lfsPart->cfg;
94
95 printf("[%s]: Self Test Start\n", ctx->mountPoint);
96
97 uint32_t block = 0;
98 uint32_t start = 0;
99 uint32_t testSize = (cfg->blockSize > sizeof(wbuf)) ? sizeof(wbuf) : cfg->blockSize;
100 printf("[%s]: Self Test testSize: %u\n", ctx->mountPoint, testSize);
101
102 for (int i = 0; i < testSize; i++) {
103 wbuf[i] = i & 0xff;
104 }
105
106 uint32_t rsetp = cfg->readSize;
107 uint32_t wsetp = cfg->writeSize;
108
109 for (block = 0; block < cfg->blockCount; block++) {
110 HpmLittlefsErase(cfg->partNo, ctx->startOffset + block * cfg->blockSize, cfg->blockSize);
111 uint32_t offset;
112 for (start = 0; start < testSize; start += wsetp) {
113 offset = ctx->startOffset + block * cfg->blockSize + start;
114 HpmLittlefsProg(cfg->partNo, (UINT32 *)&offset, (const void *)(wbuf + start), wsetp);
115 }
116
117 for (start = 0; start < testSize; start += rsetp) {
118 offset = ctx->startOffset + block * cfg->blockSize + start;
119 HpmLittlefsRead(cfg->partNo, (UINT32 *)&offset, (void *)(rbuf + start), rsetp);
120 }
121
122 for (int i = 0; i < testSize; i++) {
123 if (wbuf[i] != rbuf[i]) {
124 printf("%d: wbuf(%u) != rbuf(%u)\n", i, wbuf[i], rbuf[i]);
125 }
126 }
127
128 int isEqu = memcmp(wbuf, rbuf, testSize);
129 if (isEqu) {
130 printf("[%s]: block: %u fail\n", ctx->mountPoint, block);
131 break;
132 } else {
133 printf("[%s]: block: %u pass\n", ctx->mountPoint, block);
134 }
135 }
136 }
137 #endif
138
HpmLittlefsDriverInit(struct HpmLittlefsCfg * lfsPart)139 int HpmLittlefsDriverInit(struct HpmLittlefsCfg *lfsPart)
140 {
141 struct HpmLittleCtx *ctx = &lfsPart->ctx;
142 struct PartitionCfg *cfg = &lfsPart->cfg;
143 XPI_Type *base = (XPI_Type *)ctx->base;
144
145 if (ctx->isInited) {
146 return 0;
147 }
148 ctx->isInited = 1;
149
150 printf("hpm lfs: mountPoint: %s\n", ctx->mountPoint);
151 printf("hpm lfs: startOffset: %u\n", ctx->startOffset);
152 printf("hpm lfs: len: %u\n", ctx->len);
153
154 xpi_nor_config_option_t option;
155 option.header.U = 0xfcf90001U;
156 option.option0.U = 0x00000005U;
157 option.option1.U = 0x00001000U;
158 uint32_t blockSize;
159 uint32_t blockCount;
160 uint32_t intSave = LOS_IntLock();
161 hpm_stat_t status = rom_xpi_nor_auto_config(base, &ctx->xpiNorConfig, &option);
162 rom_xpi_nor_get_property(base, &ctx->xpiNorConfig, xpi_nor_property_sector_size, &blockSize);
163 __asm volatile("fence.i");
164 LOS_IntRestore(intSave);
165 if (status != status_success) {
166 printf("Error: rom_xpi_nor_auto_config\n");
167 while (1);
168 }
169
170 blockCount = ctx->len / blockSize;
171 printf("hpm lfs: blockCount: %u\n", blockCount);
172 printf("hpm lfs: blockSize: %u\n", blockSize);
173 printf("------------------------------------------\n");
174
175 cfg->blockSize = blockSize;
176 cfg->blockCount = blockCount;
177 #if HPMICRO_FLASH_SELFTEST_ENABLE == 1
178 SelfTest(lfsPart);
179 #endif
180
181 return 0;
182 }
183
184
185