1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 /* CSI Nor Flash implementation */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <drv/spiflash.h>
11 #include <aos/mtd.h>
12 #include <aos/mtdpart.h>
13 #include "hal_trace.h"
14 #include "hal_norflash.h"
15 #include "cmsis.h"
16
17
bes_flash_memcpy(void * dst,void * src,size_t num)18 static void * bes_flash_memcpy(void *dst, void *src, size_t num)
19 {
20 int offset1 = (4 - ((uint32)dst & 3)) & 3;
21 int offset2 = (4 - ((uint32)src & 3)) & 3;
22
23 if(offset1 != offset2) {
24 return memcpy(dst, src, num);
25 }
26
27 int wordnum = num > offset1 ? (num - offset1) /8 : 0;
28 int slice = num > offset1 ? (num-offset1) % 8 : 0;
29 char *pdst = (char *)dst;
30 char *psrc = (char *)src;
31 long long * pintsrc;
32 long long * pintdst;
33
34 while(offset1--) {
35 *pdst++ = *psrc++;
36 }
37
38 pintdst = (long long*)pdst;
39 pintsrc = (long long*)psrc;
40 while(wordnum--) {
41 *pintdst++ = *pintsrc++;
42 }
43
44 pdst = (char*)pintdst;
45 psrc = (char*)pintsrc;
46 while(slice--) {
47 *pdst++ = *psrc++;
48 }
49
50 return dst;
51 }
52
csi_spiflash_spi_init(csi_spiflash_t * spiflash,uint32_t spi_idx,void * spi_cs_callback)53 csi_error_t csi_spiflash_spi_init(csi_spiflash_t *spiflash, uint32_t spi_idx, void *spi_cs_callback)
54 {
55 if (spiflash == NULL) {
56 return CSI_ERROR;
57 }
58
59 spiflash->spi_qspi.spi.dev.idx = spi_idx;
60 spiflash->spi_qspi.spi.dev.reg_base = FLASH_NC_BASE;
61 spiflash->spi_cs_callback = spi_cs_callback;
62 return CSI_OK;
63 }
64
csi_spiflash_spi_uninit(csi_spiflash_t * spiflash)65 void csi_spiflash_spi_uninit(csi_spiflash_t *spiflash)
66 {
67 if (spiflash == NULL) {
68 return CSI_ERROR;
69 }
70
71 spiflash->spi_cs_callback = NULL;
72 return;
73 }
74
csi_spiflash_get_flash_info(csi_spiflash_t * spiflash,csi_spiflash_info_t * flash_info)75 csi_error_t csi_spiflash_get_flash_info(csi_spiflash_t *spiflash, csi_spiflash_info_t *flash_info)
76 {
77 enum HAL_NORFLASH_RET_T ret;
78 (void) spiflash;
79
80 if (flash_info == NULL) {
81 return CSI_ERROR;
82 }
83
84 ret = hal_norflash_get_size(HAL_NORFLASH_ID_0, &(flash_info->flash_size), NULL,
85 &(flash_info->page_size), &(flash_info->page_size));
86 if (ret != HAL_NORFLASH_OK) {
87 return CSI_ERROR;
88 }
89
90 return CSI_OK;
91 }
92
csi_spiflash_read(csi_spiflash_t * spiflash,uint32_t offset,void * data,uint32_t size)93 int32_t csi_spiflash_read(csi_spiflash_t *spiflash, uint32_t offset, void *data, uint32_t size)
94 {
95 volatile char *flashPointer = NULL;
96 uint32_t lock;
97
98 (void) spiflash;
99
100 if (data == NULL || size <= 0) {
101 return CSI_ERROR;
102 }
103
104 watchdog_feeddog();
105 lock = int_lock();
106 hal_norflash_disable_remap(HAL_NORFLASH_ID_0);
107
108 flashPointer = (volatile char *)(FLASH_NC_BASE + offset);
109 bes_flash_memcpy(data, (void *)flashPointer, size);
110
111 hal_norflash_re_enable_remap(HAL_NORFLASH_ID_0);
112 int_unlock(lock);
113
114 return size;
115 }
116
csi_spiflash_program(csi_spiflash_t * spiflash,uint32_t offset,const void * data,uint32_t size)117 int32_t csi_spiflash_program(csi_spiflash_t *spiflash, uint32_t offset, const void *data, uint32_t size)
118 {
119 int ret = 0;
120 uint32_t lock;
121
122 (void) spiflash;
123
124 if (data == NULL || size <= 0) {
125 return CSI_ERROR;
126 }
127
128 watchdog_feeddog();
129 lock = int_lock();
130 pmu_flash_write_config();
131 hal_norflash_disable_remap(HAL_NORFLASH_ID_0);
132
133 ret = hal_norflash_write(HAL_NORFLASH_ID_0, offset, data, size);
134 hal_norflash_re_enable_remap(HAL_NORFLASH_ID_0);
135 pmu_flash_read_config();
136 int_unlock(lock);
137
138 if (ret != HAL_NORFLASH_OK) {
139 TRACE("error %s %d, hal_norflash_write ret:%d", __func__, __LINE__, ret);
140 return CSI_ERROR;
141 }
142
143 return size;
144 }
145
csi_spiflash_erase(csi_spiflash_t * spiflash,uint32_t offset,uint32_t size)146 csi_error_t csi_spiflash_erase(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size)
147 {
148 int ret = 0;
149 uint32_t lock = 0;
150
151 (void) spiflash;
152
153 watchdog_feeddog();
154 lock = int_lock();
155 pmu_flash_write_config();
156 hal_norflash_disable_remap(HAL_NORFLASH_ID_0);
157
158 ret = hal_norflash_erase(HAL_NORFLASH_ID_0, offset, size);
159 hal_norflash_re_enable_remap(HAL_NORFLASH_ID_0);
160 pmu_flash_read_config();
161 int_unlock(lock);
162
163 if (ret != HAL_NORFLASH_OK) {
164 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
165 return CSI_ERROR;
166 }
167
168 return CSI_OK;
169 }
170
171 static aos_mtd_t g_mtd_nor_dev;
172
173 struct part_info {
174 uint32_t cnt;
175 struct mtd_part *part;
176 };
177
get_mtd_part(struct part_info * info)178 static int get_mtd_part(struct part_info *info)
179 {
180 mtd_partition_t *p;
181 struct mtd_part *parts;
182
183 parts = calloc(mtd_partitions_amount, sizeof(struct mtd_part));
184 if (parts == NULL) {
185 return -ENOMEM;
186 }
187
188 for (int i = 0; i < mtd_partitions_amount; i++) {
189 p = &mtd_partitions[i];
190 parts[i].name_std = p->partition_name_std;
191 parts[i].name = p->partition_name;
192 parts[i].offset = p->partition_start_addr;
193 parts[i].size = p->partition_length;
194 }
195
196 info->cnt = mtd_partitions_amount;
197 info->part = parts;
198 return 0;
199 }
200
csi_flash_init()201 int csi_flash_init()
202 {
203 struct part_info info = {0};
204 uint32_t blk_size = 4096; //sector size.
205 uint32_t page_size = 256;
206 int ret;
207
208 printf("%s:%d begin..\r\n", __func__, __LINE__);
209 if (get_mtd_part(&info)) {
210 printf("%s:%d get_mtd_part failed.\r\n", __func__, __LINE__);
211 return -1;
212 }
213
214 ret = aos_mtd_nor_init(&g_mtd_nor_dev, blk_size, page_size);
215 if (ret != 0) {
216 printf("%s:%d aos_mtd_nor_init failed, ret:%d\r\n", __func__, __LINE__, ret);
217 return -2;
218 }
219
220 ret = aos_mtd_register(&g_mtd_nor_dev, info.part, info.cnt);
221 if (ret < 0) {
222 printf("%s:%d aos_mtd_register failed, ret:%d\r\n", __func__, __LINE__, ret);
223 } else {
224 printf("%s:%d done.\r\n", __func__, __LINE__);
225 }
226
227 return ret;
228 }
229