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, §ors);
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, §ors);
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