6 #include "appl_eeprom.h"
8 #ifdef CONFIG_OC_I2C_DRV_SYSLESS
10 extern i2c_drv_t i2c_drv;
13 #include "distore_simple.h"
16 extern UL_LOG_CUST(ulogd_distore)
18 #ifdef APPL_WITH_TIMEPROG_EEPROM_STORE
20 extern timeprog_t appl_timeprog_eeprom_identifier;
23 #ifdef CONFIG_OC_I2C_DRV_SYSLESS
25 void *(*const appl_distore_reserve_ram)(size_t size);
27 typedef struct appl_distore_eeprom_context_t
32 const distore_des_array_t *des;
35 volatile unsigned char check4change;
36 unsigned char gen_cnt;
37 unsigned short area_start;
38 unsigned short area_size;
40 appl_eeprom_chip_context_t *chip;
41 } appl_distore_eeprom_context_t;
43 ssize_t appl_distore_eeprom_wrfnc(void *context, const void *buf, size_t count)
45 appl_distore_eeprom_context_t *c = (appl_distore_eeprom_context_t *) context;
47 if (c->limit - c->pos < count)
50 if (memcmp((char *) c->buf + c->pos, buf, count))
53 memcpy((char *) c->buf + c->pos, buf, count);
58 ssize_t appl_distore_eeprom_rdfnc(void *context, void *buf, size_t count)
60 appl_distore_eeprom_context_t *c = (appl_distore_eeprom_context_t *) context;
62 if (c->limit - c->pos < count)
65 memcpy(buf, (char *) c->buf + c->pos, count);
70 unsigned int appl_distore_eeprom_chksum(void *data, size_t size)
72 unsigned int chksum = 0x1234;
73 unsigned char *p = data;
77 chksum = (*p ^ chksum) + (*p << 8) + 1;
84 int appl_distore_eeprom_load(appl_distore_eeprom_context_t *c)
86 const distore_des_array_t *des = c->des;
87 unsigned char u[DISTORE_EEPROM_HEADER_SIZE];
89 unsigned int chksum, load_chksum;
91 unsigned char area_bad[2] = {0, 0};
92 unsigned char area_gen_cnt[2];
93 unsigned int area_limit[2];
102 for (area_act = 0; area_act < 2; area_act++)
104 ma = c->area_start + c->area_size * area_act;
106 if (appl_eeprom_chip_load(c->chip, ma, u, DISTORE_EEPROM_HEADER_SIZE) < 0)
111 if (u[0] != DISTORE_EEPROM_SIGNATURE)
113 area_bad[area_act] = 1;
114 ul_logmsg("appl_distore_eeprom_load area %d has bad signature\n", area_act);
118 area_gen_cnt[area_act] = u[1];
119 area_limit[area_act] = u[4] | ((unsigned int) u[5] << 8);
121 if (c->area_size < area_limit[area_act])
123 area_bad[area_act] = 1;
124 ul_logmsg("appl_distore_eeprom_load area %d size 0x%lx < stored size 0x%lx\n", area_act,
125 (unsigned long) c->area_size, (unsigned long) area_limit[area_act]);
129 ul_logdeb("appl_distore_eeprom_load area %d gen_cnt is 0x%x stored size 0x%lx\n",
130 area_act, u[1], (unsigned long) area_limit[area_act]);
135 if ((ul_cyclic_gt(area_gen_cnt[1], area_gen_cnt[0]) && !area_bad[1]) || area_bad[0])
138 for (; 1; area_bad[area_act] = 1, area_act = area_act ^ 1)
140 if (area_bad[area_act])
142 ul_logmsg("appl_distore_eeprom_load no valid area found\n");
146 c->limit = area_limit[area_act];
148 ma = c->area_start + c->area_size * area_act;
150 if (appl_eeprom_chip_load(c->chip, ma, c->buf, c->limit) < 0)
155 chksum = appl_distore_eeprom_chksum((unsigned char *) c->buf + 4, c->limit - 4);
156 load_chksum = * ((unsigned char *) c->buf + 2);
157 load_chksum |= * ((unsigned char *) c->buf + 3) << 8;
159 if ((chksum ^ load_chksum) & 0xffff)
161 ul_logmsg("appl_distore_eeprom_load area %d has bad checksum (0x%04x != 0x%04x)\n",
162 area_act, chksum & 0xffff, load_chksum);
166 c->write2nd = area_act ^ 1;
167 c->gen_cnt = area_gen_cnt[area_act];
168 ul_logdeb("appl_distore_eeprom_load reading data from %d area\n", area_act);
170 c->pos = DISTORE_EEPROM_HEADER_SIZE;
172 res = distore_load_data(des, appl_distore_eeprom_rdfnc, c,
173 DISTORE_LOAD_IGNORE_UNKNOWN | DISTORE_LOAD_IGNORE_WRITE_ERR);
177 ul_logmsg("appl_distore_eeprom_load data decode from %d area failed\n", area_act);
182 ul_logmsg("appl_distore_eeprom_load decoded from %d area\n", area_act);
191 int appl_distore_eeprom_init(appl_distore_eeprom_context_t *c)
193 const distore_des_array_t *des = c->des;
199 sz = distore_count_maxsize(des);
204 if (sz + DISTORE_EEPROM_HEADER_SIZE >= c->area_size)
206 ul_logerr("appl_distore max_size %ld > EEPROM target area %ld\n",
207 (unsigned long) sz, (unsigned long) c->area_size);
211 if (appl_distore_reserve_ram != NULL)
212 c->buf = appl_distore_reserve_ram(c->area_size);
215 c->buf = malloc(c->area_size);
219 ul_logerr("appl_distore_eeprom_init RAM allocation failed\n");
223 memset(c->buf, 0, c->area_size > 16 ? 16 : c->area_size);
225 c->limit = c->area_size;
230 int appl_distore_eeprom_store(appl_distore_eeprom_context_t *c, int forced)
234 unsigned char u[DISTORE_EEPROM_HEADER_SIZE];
235 const distore_des_array_t *des = c->des;
240 if (c->chip->tx_inpr > 0)
245 c->pos = DISTORE_EEPROM_HEADER_SIZE;
246 c->limit = c->area_size;
250 res = distore_store_data(des, appl_distore_eeprom_wrfnc, c);
257 if (!c->changed && !forced)
262 /* The length of the data is part of the area covered by checksum */
263 u[4] = c->limit & 0xff;
264 u[5] = c->limit >> 8;
266 appl_distore_eeprom_wrfnc(c, u + 4, 2);
268 chksum = appl_distore_eeprom_chksum((unsigned char *) c->buf + 4, c->limit - 4);
270 u[0] = DISTORE_EEPROM_SIGNATURE;
271 u[1] = (c->gen_cnt + 1) & 0xff;
272 u[2] = chksum & 0xff;
273 u[3] = (chksum >> 8) & 0xff;
276 appl_distore_eeprom_wrfnc(c, u, DISTORE_EEPROM_HEADER_SIZE);
283 #endif /*CONFIG_OC_I2C_DRV_SYSLESS*/
285 #ifdef APPL_WITH_DISTORE_EEPROM_USER
286 extern const distore_des_array_t appl_distore_eeprom_user_des;
288 appl_eeprom_chip_context_t appl_eeprom_chip_context =
290 .page_size = DISTORE_EEPROM_PAGE,
292 .i2c_addr = DISTORE_EEPROM_I2C_ADDR,
295 appl_distore_eeprom_context_t appl_distore_eeprom_user_context =
297 .des = &appl_distore_eeprom_user_des,
298 .area_start = DISTORE_EEPROM_USER_START,
299 .area_size = DISTORE_EEPROM_USER_SIZE,
300 .chip = &appl_eeprom_chip_context,
303 int appl_distore_eeprom_user_finish_callback(struct appl_eeprom_chip_context_t *chip,
304 void *context, int result)
306 appl_distore_eeprom_context_t *c = (appl_distore_eeprom_context_t *) context;
308 ul_loginf("finished distore save with result %d\n", result);
312 c->write2nd = (c->write2nd ^ 1) & 1;
319 #ifdef APPL_WITH_TIMEPROG_EEPROM_STORE
320 int appl_timeprog_eeprom_store_finish_callback(struct appl_eeprom_chip_context_t *chip,
321 void *context, int result)
323 timeprog_t *timeprog = (timeprog_t *) context;
325 ul_loginf("finished timeprog save with result %d\n", result);
327 timeprog->save_rq_state = (result >= 0) ? 0 : -1;
331 #endif /*APPL_WITH_TIMEPROG_EEPROM_STORE*/
333 int appl_distore_user_change_check(void)
337 appl_distore_eeprom_context_t *c = &appl_distore_eeprom_user_context;
338 appl_eeprom_chip_context_t *chip = c->chip;
339 int transfer_pend_fl = 0;
341 if (chip->tx_inpr > 0)
344 #ifdef APPL_WITH_TIMEPROG_EEPROM_STORE
346 if (chip->opstate == APPL_EEPROM_ST_IDLE)
348 timeprog_t *timeprog = &appl_timeprog_eeprom_identifier;
350 if (timeprog->save_rq_state)
352 long size_to_store = timeprog_size_to_store(timeprog);
355 if ((size_to_store > 0) && (size_to_store <= TIMEPROG_EEPROM_STORE_SIZE))
357 res = appl_eeprom_chip_write_transfer_setup(chip, timeprog->region_start,
358 TIMEPROG_EEPROM_STORE_START, size_to_store,
359 appl_timeprog_eeprom_store_finish_callback, timeprog);
364 timeprog->save_rq_state = -1;
369 transfer_pend_fl = 1;
370 timeprog_stored_size = size_to_store;
375 #endif /*APPL_WITH_TIMEPROG_EEPROM_STORE*/
377 if (c->check4change && !transfer_pend_fl)
379 res = appl_distore_eeprom_store(c, 0);
391 appl_eeprom_chip_write_transfer_setup(chip, c->buf, ma, c->limit,
392 appl_distore_eeprom_user_finish_callback, c);
396 if (chip->opstate == APPL_EEPROM_ST_IDLE)
399 return appl_eeprom_chip_process(chip);
402 int appl_distore_user_set_check4change(void)
404 appl_distore_eeprom_context_t *c = &appl_distore_eeprom_user_context;
411 int appl_distore_user_restore(void)
413 appl_distore_eeprom_context_t *c = &appl_distore_eeprom_user_context;
415 return appl_distore_eeprom_load(c);
418 #ifdef APPL_WITH_TIMEPROG_EEPROM_STORE
419 int appl_timeprog_eeprom_restore(void)
421 appl_distore_eeprom_context_t *c = &appl_distore_eeprom_user_context;
422 appl_eeprom_chip_context_t *chip = c->chip;
423 timeprog_t *timeprog = &appl_timeprog_eeprom_identifier;
424 long sz = timeprog_stored_size;
426 if ((timeprog->region_limit == NULL) || (timeprog->region_start == NULL))
429 if ((sz <= 0) || (sz > (char *) timeprog->region_limit - (char *) timeprog->region_start))
432 if (sz > TIMEPROG_EEPROM_STORE_SIZE)
435 timeprog->preprocess_state = TIMEPROG_PPST_MODIFIED;
438 if (appl_eeprom_chip_load(chip, TIMEPROG_EEPROM_STORE_START, timeprog->region_start, sz) < 0)
440 size_t region_size = timeprog->region_limit - timeprog->region_start;
441 memset(timeprog->region_start, 0, region_size);
448 if (!timeprog_actual_is_empty(timeprog))
449 timeprog_end_and_prepare(timeprog);
453 #endif /*APPL_WITH_TIMEPROG_EEPROM_STORE*/
456 int appl_distore_init(void)
458 appl_distore_eeprom_context_t *c = &appl_distore_eeprom_user_context;
460 if (appl_eeprom_chip_init(c->chip) < 0)
465 return appl_distore_eeprom_init(c);
468 #endif /* APPL_WITH_DISTORE_EEPROM_USER */