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