1 /* This is all about APIs for/from other modules */
2 
3 #include <string.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <pthread.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <hal_timer.h>
10 #include <sunxi_hal_common.h>
11 
12 #ifdef CONFIG_COMPONENTS_AW_BLKPART
13 #include <blkpart.h>
14 #include <part_efi.h>
15 #endif
16 
17 #include "inter.h"
18 
19 #ifdef CONFIG_COMPONENTS_AW_BLKPART
20 struct syspart {
21     char name[MAX_BLKNAME_LEN];
22     u32 bytes;
23 };
24 
25 static const struct syspart syspart[] = {
26     /* contain boot0 and gpt, gpt offset is (128-16)k */
27     {"boot0", 128 * 1024},
28 };
29 
30 static struct blkpart norblk;
31 #endif
32 
33 static sunxi_hal_spinor_info hal_spinor_info = {0};
34 
hal_spinor_get_version(int32_t dev)35 sunxi_hal_version_t hal_spinor_get_version(int32_t dev)
36 {
37     sunxi_hal_version_t ver;
38     HAL_ARG_UNUSED(dev);
39 
40     ver.api = SUNXI_HAL_SPINOR_API_VERSION;
41     ver.drv = SUNXI_HAL_SPINOR_DRV_VERSION;
42     return ver;
43 }
44 
hal_spinor_get_capabilities(void)45 sunxi_hal_spinor_capabilities_t hal_spinor_get_capabilities(void)
46 {
47     sunxi_hal_spinor_capabilities_t cap;
48 
49     cap.event_ready = 1;
50     cap.data_width = 1;
51     cap.erase_chip = 1;
52     cap.reserved = 0;
53 
54     return cap;
55 }
56 
57 #ifdef CONFIG_COMPONENTS_AW_BLKPART
nor_get_gpt(char * buf,int len)58 static int nor_get_gpt(char *buf, int len)
59 {
60     if (len < GPT_TABLE_SIZE) {
61         SPINOR_ERR("buf too small for gpt\n");
62         return -EINVAL;
63     }
64 
65     return nor_read(GPT_ADDRESS, buf, GPT_TABLE_SIZE);
66 }
67 
68 #ifdef CONFIG_RESERVE_IMAGE_PART
69 
70 typedef struct sbrom_toc1_head_info
71 {
72     char name[16]   ;   //user can modify
73     uint32_t  magic ;   //must equal TOC_U32_MAGIC
74     uint32_t  add_sum   ;
75 
76     uint32_t  serial_num    ;   //user can modify
77     uint32_t  status        ;   //user can modify,such as TOC_MAIN_INFO_STATUS_ENCRYP_NOT_USED
78 
79     uint32_t  items_nr; //total entry number
80     uint32_t  valid_len;
81     uint32_t  version_main; //only one byte
82     uint32_t  version_sub;   //two bytes
83     uint32_t  reserved[3];  //reserved for future
84 
85     uint32_t  end;
86 }__attribute__((aligned(1))) sbrom_toc1_head_info_t;
87 
88 /*
89  * get_rtos_toc_package_size: get rtos toc package size
90  * @param gpt_buf: gpt table buf
91  * @param name   : gpt entry name
92  * @param page_bytes: page size
93  * @return value : toc pageage size
94  */
get_rtos_toc_package_size(void * gpt_buf,char * name,int page_bytes)95 int get_rtos_toc_package_size(void *gpt_buf, char *name, int page_bytes)
96 {
97     unsigned int len = 0x0;
98     unsigned int sectors = 0;
99     unsigned int start_sector = 0;
100     int toc_offset = 0;
101     int ret = -1;
102 
103     char *buf = malloc(page_bytes);
104     if (!buf)
105         return -1;
106     memset(buf, 0, page_bytes);
107 
108     ret = get_part_info_by_name(gpt_buf, name, &start_sector, &sectors);
109     if (ret)
110         goto out;
111 
112     toc_offset = start_sector << 9;
113     ret = nor_read(toc_offset, buf, page_bytes);
114     if (ret)
115         goto out;
116 
117     sbrom_toc1_head_info_t *head = (sbrom_toc1_head_info_t *)buf;
118     if (strncmp(head->name, "sunxi-", 6))
119         goto out;
120 
121 #define ALIGN_UP(size, align) (((size) + (align) - 1) & ~((align) - 1))
122     len = ALIGN_UP(head->valid_len, page_bytes);
123 
124 out:
125     free(buf);
126 
127     return len;
128 }
129 
130 /*
131  * get_rtos_offset: get rtos offset
132  * @param gpt_buf: gpt table buf
133  * @param name   : gpt entry name
134  * @return value : rtos part offset
135  */
get_rtos_offset(void * gpt_buf,char * name)136 int get_rtos_offset(void *gpt_buf, char *name)
137 {
138     unsigned int sectors = 0;
139     unsigned int start_sector = 0;
140     int ret = -1;
141 
142     ret = get_part_info_by_name(gpt_buf, name, &start_sector, &sectors);
143     if (ret)
144         goto out;
145 
146     ret = start_sector << 9;
147 out:
148 
149     return ret;
150 }
151 
152 #endif
153 
nor_blkpart_init(void)154 static int nor_blkpart_init(void)
155 {
156     int ret, index;
157     char *gpt_buf;
158     struct nor_flash *nor;
159     struct gpt_part *gpt_part;
160     struct part *part;
161 
162     nor = get_nor_flash();
163     if (!nor || !nor->info)
164         return -EBUSY;
165 
166     gpt_buf = malloc(GPT_TABLE_SIZE);
167     if (!gpt_buf) {
168         ret = -ENOMEM;
169         goto err;
170     }
171     memset(gpt_buf, 0, GPT_TABLE_SIZE);
172 
173     ret = nor_get_gpt(gpt_buf, GPT_TABLE_SIZE);
174     if (ret) {
175         SPINOR_ERR("get gpt from nor flash failed - %d\n", ret);
176         goto err;
177     }
178 
179     memset(&norblk, 0, sizeof(struct blkpart));
180     norblk.name = "nor";
181     norblk.page_bytes = nor->page_size;
182 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
183     norblk.erase = nor_cache_erase;
184     norblk.program = nor_cache_write;
185     norblk.read = nor_cache_read;
186     norblk.sync = nor_cache_sync;
187 #else
188     norblk.erase = nor_erase;
189     norblk.program = nor_write;
190     norblk.read = nor_read;
191     norblk.sync = NULL;
192 #endif
193     norblk.noncache_erase = nor_erase;
194     norblk.noncache_program = nor_write;
195     norblk.noncache_read = nor_read;
196     norblk.total_bytes = nor->total_size;
197     norblk.blk_bytes = nor->blk_size;
198 
199     ret = gpt_part_cnt(gpt_buf);
200     if (ret < 0) {
201         SPINOR_ERR("get part count from gpt failed\n");
202         goto err;
203     }
204 #ifdef CONFIG_RESERVE_IMAGE_PART
205     norblk.n_parts = ret + ARRAY_SIZE(syspart) + 2;
206 #else
207     norblk.n_parts = ret + ARRAY_SIZE(syspart);
208 #endif
209     norblk.parts = malloc(norblk.n_parts * sizeof(struct part));
210     if (!norblk.parts)
211         goto err;
212     SPINOR_INFO("total %u part\n", norblk.n_parts);
213 
214     for (index = 0; index < ARRAY_SIZE(syspart); index++) {
215         part = &norblk.parts[index];
216         part->bytes = syspart[index].bytes;
217         part->off = BLKPART_OFF_APPEND;
218         strcpy(part->name, syspart[index].name);
219     }
220 
221     foreach_gpt_part(gpt_buf, gpt_part) {
222         part = &norblk.parts[index++];
223         part->bytes = gpt_part->sects << SECTOR_SHIFT;
224         part->off = BLKPART_OFF_APPEND;
225         snprintf(part->name, MAX_BLKNAME_LEN, "%s", gpt_part->name);
226 #ifdef CONFIG_RESERVE_IMAGE_PART
227         if (!strcmp("rtosA", part->name) || !strcmp("rtosB", part->name)) {
228             int rtos_index = index - 1;
229             struct part *last_part = part;
230             int toc_package_size = get_rtos_toc_package_size(gpt_buf, last_part->name, norblk.page_bytes);
231             int rtos_offset = get_rtos_offset(gpt_buf, last_part->name);
232             if (toc_package_size > 0 && rtos_offset > 0) {
233                 part = &norblk.parts[index++];
234                 part->bytes = norblk.parts[rtos_index].bytes - toc_package_size;
235                 part->off = rtos_offset + toc_package_size;
236                 if (!strcmp("rtosA", last_part->name))
237                     snprintf(part->name, MAX_BLKNAME_LEN, "%s", "reserveA");
238                 else
239                     snprintf(part->name, MAX_BLKNAME_LEN, "%s", "reserveB");
240             } else {
241                 norblk.n_parts --;
242             }
243         }
244 #endif
245     }
246     norblk.parts[--index].bytes = BLKPART_SIZ_FULL;
247 
248     ret = add_blkpart(&norblk);
249     if (ret)
250         goto free_parts;
251 
252     /* check bytes align */
253     for (index = 0; index < norblk.n_parts; index++) {
254         part = &norblk.parts[index];
255         if (part->bytes % nor->blk_size) {
256             SPINOR_ERR("part %s with bytes %u should align to block size %u\n",
257                     part->name, part->bytes, nor->blk_size);
258             goto del_blk;
259         }
260     }
261 
262     free(gpt_buf);
263     return 0;
264 
265 del_blk:
266     del_blkpart(&norblk);
267 free_parts:
268     free(norblk.parts);
269 err:
270     free(gpt_buf);
271     SPINOR_ERR("init blkpart for nor failed - %d\n", ret);
272     return ret;
273 }
274 
hal_spinor_init(sunxi_hal_spinor_signal_event_t cb_event)275 int32_t hal_spinor_init(sunxi_hal_spinor_signal_event_t cb_event)
276 {
277     int ret;
278 
279     ret = nor_init();
280     if (ret)
281         return ret;
282 
283     return nor_blkpart_init();
284 }
285 #else
hal_spinor_init(sunxi_hal_spinor_signal_event_t cb_event)286 int32_t hal_spinor_init(sunxi_hal_spinor_signal_event_t cb_event)
287 {
288     return nor_init();
289 }
290 #endif
291 
hal_spinor_deinit(void)292 int32_t hal_spinor_deinit(void)
293 {
294     hal_spinor_sync();
295     return nor_deinit();
296 }
297 
hal_spinor_power_control(sunxi_hal_power_state_e state)298 int32_t hal_spinor_power_control(sunxi_hal_power_state_e state)
299 {
300     return SUNXI_HAL_OK;
301 }
302 
hal_spinor_read_data(uint32_t addr,void * buf,uint32_t cnt)303 int32_t hal_spinor_read_data(uint32_t addr, void *buf, uint32_t cnt)
304 {
305 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
306     return nor_cache_read(addr, buf, cnt);
307 #else
308     return nor_read(addr, (void *)buf, cnt);
309 #endif
310 }
311 
hal_spinor_program_data(uint32_t addr,const void * buf,uint32_t cnt)312 int32_t hal_spinor_program_data(uint32_t addr, const void *buf, uint32_t cnt)
313 {
314 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
315     return nor_cache_write(addr, (void *)buf, cnt);
316 #else
317     return nor_write(addr, (void *)buf, cnt);
318 #endif
319 }
320 
hal_spinor_sync(void)321 int32_t hal_spinor_sync(void)
322 {
323 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
324     return nor_cache_sync();
325 #else
326     return 0;
327 #endif
328 }
329 
hal_spinor_erase_sector(uint32_t addr,uint32_t size)330 int32_t hal_spinor_erase_sector(uint32_t addr, uint32_t size)
331 {
332 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
333     return nor_cache_erase(addr, size);
334 #else
335     return nor_erase(addr, size);
336 #endif
337 }
338 
hal_spinor_erase_chip(void)339 int32_t hal_spinor_erase_chip(void)
340 {
341     struct nor_flash *nor = get_nor_flash();
342 
343 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
344     nor_cache_sync();
345 #endif
346     return nor_erase(0, nor->total_size);
347 }
348 
hal_spinor_get_status(void)349 sunxi_hal_spinor_status_t hal_spinor_get_status(void)
350 {
351     sunxi_hal_spinor_status_t spinor_status = {0, 0, 0};
352 
353     return spinor_status;
354 }
355 
hal_spinor_get_info(void)356 sunxi_hal_spinor_info *hal_spinor_get_info(void)
357 {
358     struct nor_flash *nor = get_nor_flash();
359 
360     if (!nor->info)
361         return NULL;
362 
363     hal_spinor_info.sector_size = nor->blk_size;
364     hal_spinor_info.sector_count = nor->total_size / nor->blk_size;
365     hal_spinor_info.page_size = nor->page_size;
366     hal_spinor_info.program_unit = nor->page_size;
367     return &hal_spinor_info;
368 }
369 
hal_spinor_signal_event(uint32_t event)370 void hal_spinor_signal_event(uint32_t event)
371 {
372     return;
373 }
374 
hal_spinor_control(int32_t dev,uint32_t command,uint32_t arg)375 int32_t hal_spinor_control(int32_t dev, uint32_t command, uint32_t arg)
376 {
377     return SUNXI_HAL_OK;
378 }
379