123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- /********************************************************************************
- * USDK(ZS283A)
- * Module: SYSTEM
- * Copyright(c) 2003-2017 Actions Semiconductor,
- * All Rights Reserved.
- *
- * History:
- * <author> <time> <version > <desc>
- ********************************************************************************/
- /*!
- * \file compensation.c
- * \brief
- * \author
- * \version 1.0
- * \date
- *******************************************************************************/
- #include <init.h>
- #include <kernel.h>
- #include <string.h>
- #include <compensation.h>
- #include <soc_atp.h>
- #include <drivers/nvram_config.h>
- #include <soc.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #define SYS_LOG_DOMAIN "comp"
- #ifndef SYS_LOG_LEVEL
- #define SYS_LOG_LEVEL CONFIG_SYS_LOG_DEFAULT_LEVEL
- #endif
- #include <logging/log.h>
- //2*8=16bit
- #define MAX_EFUSE_CAP_RECORD (CONFIG_COMPENSATION_FREQ_INDEX_NUM)
- typedef struct
- {
- uint32_t value[MAX_EFUSE_CAP_RECORD];
- } cap_value_t;
- #if defined(CONFIG_SOC_SERIES_WOODPECKERFPGA)
- #define HOSC_CALIB_SIM
- #endif
- #ifdef HOSC_CALIB_SIM
- static uint8_t hosc_val[MAX_EFUSE_CAP_RECORD];
- static int soc_get_hosc_calib_sim(int id, unsigned char *calib_val)
- {
- *calib_val = hosc_val[id];
- return 0;
- }
- static int soc_set_hosc_calib_sim(int id, unsigned char calib_val)
- {
- hosc_val[id] = calib_val;
- return 0;
- }
- #endif
- static uint32_t read_efuse_freq_value(uint32_t *read_cap_value, int *index)
- {
- int i;
- cap_value_t cap_value;
- for (i = 0; i < MAX_EFUSE_CAP_RECORD; i++) {
- #ifndef HOSC_CALIB_SIM
- soc_atp_get_hosc_calib(i, (unsigned int *)(&cap_value.value[i]));
- #else
- soc_get_hosc_calib_sim(i, (unsigned int *)(&cap_value.value[i]));
- #endif
- }
- // the latter value is the newer efuse and return the last value which modified.
- for (i = 0; i < MAX_EFUSE_CAP_RECORD; i++) {
- if (cap_value.value[i] == 0) {
- break;
- }
- }
- //efuse that never written
- if (i == 0) {
- *read_cap_value = 0xff;
- *index = 0xff;
- } else {
- *read_cap_value = cap_value.value[i - 1];
- *index = i - 1;
- }
- return 0;
- }
- static int32_t read_efuse_freq_compensation(uint32_t *cap_value, int *index)
- {
- uint32_t trim_cap_value;
- read_efuse_freq_value(&trim_cap_value, index);
- if (*index != 0xff) {
- *cap_value = trim_cap_value;
- }
- return 0;
- }
- static int32_t spi_nor_freq_compensation_param_read(uint32_t *trim_cap)
- {
- uint32_t val ;
- int ret = nvram_config_get("BT_CFO_VAL", (void *) &val, 4);
- if (ret > 0){
- printk("nvram cap_val=%d\n", val);
- *trim_cap = val;
- }
- return ret;
- }
- int32_t freq_compensation_read(uint32_t *trim_cap, uint32_t mode)
- {
- int ret_val, ret_val_nvram;
- int index;
- uint32_t trim_cap_value_bak = 0;
- ret_val_nvram = spi_nor_freq_compensation_param_read(&trim_cap_value_bak);
- #ifdef CONFIG_COMPENSATION_HOSC_CAP_NVRAM_PRIORITY
- if (ret_val_nvram > 0) {
- // update the norflash parameters
- *trim_cap = trim_cap_value_bak;
- // the parameter partition is valid
- ret_val = TRIM_CAP_READ_NO_ERROR;
- return ret_val;
- }
- #endif
- ret_val = read_efuse_freq_compensation(trim_cap, &index);
- if (index == 0xff) {
- if (ret_val_nvram > 0) {
- // update the norflash parameters
- *trim_cap = trim_cap_value_bak;
- } else {
- // update the default value
- *trim_cap = CONFIG_COMPENSATION_DEFAULT_HOSC_CAP;
- }
- // the parameter partition is valid.
- ret_val = TRIM_CAP_READ_NO_ERROR;
- } else if (index < (MAX_EFUSE_CAP_RECORD - 1)) {
- // if efuse value is already valid and there is also a space to write, return the frequency offset value.
- ret_val = TRIM_CAP_READ_NO_ERROR;
- } else {
- if (mode == RW_TRIM_CAP_EFUSE) {
- if (*trim_cap == 0xff) {
- // update the default value
- *trim_cap = CONFIG_COMPENSATION_DEFAULT_HOSC_CAP;
- }
- // the parameter partition is valid.
- ret_val = TRIM_CAP_READ_NO_ERROR;
- } else {
- if (ret_val_nvram > 0) {
- // update the norflash parameters
- *trim_cap = trim_cap_value_bak;
- }
- // the parameter partition is valid.
- ret_val = TRIM_CAP_READ_NO_ERROR;
- }
- }
- return ret_val;
- }
- #ifndef CONFIG_COMPENSATION_HOSC_CAP_NVRAM_PRIORITY
- static int32_t write_efuse_new_value(int new_value, int old_index)
- {
- int new_index;
- int ret_val;
- if (old_index != 0xff) {
- new_index = old_index + 1;
- } else {
- new_index = 0;
- }
- if (new_index < MAX_EFUSE_CAP_RECORD) {
- //ret_val = soc_set_hosc_calib_sim(new_index, new_value);
- ret_val = -2;
- } else {
- return -2;
- }
- return ret_val;
- }
- static int32_t write_efuse_freq_compensation(uint32_t *cap_value)
- {
- int trim_cap_value;
- int index;
- int old_cap_value;
- // only write the least 8bits
- trim_cap_value = (*cap_value) & 0xff;
- read_efuse_freq_value(&old_cap_value, &index);
- if (index != 0xff) {
- if (old_cap_value == trim_cap_value) {
- return 0;
- } else {
- // add a new frequency offset value
- //efuse has already full
- if (index == (MAX_EFUSE_CAP_RECORD - 1)) {
- return -2;
- } else {
- return write_efuse_new_value(trim_cap_value, index);
- }
- }
- } else {
- //efuse that never been written
- return write_efuse_new_value(trim_cap_value, index);
- }
- }
- #endif
- static int32_t spi_nor_freq_compensation_param_write(uint32_t *trim_cap)
- {
- #ifdef CONFIG_PROPERTY
- return nvram_config_set_factory("BT_CFO_VAL", trim_cap, 4);
- #else
- return 0;
- #endif
- }
- int32_t freq_compensation_write(uint32_t *trim_cap, uint32_t mode)
- {
- int ret_val;
- // total 2 symmetrical bytes
- *trim_cap &= 0xffff;
- ret_val = spi_nor_freq_compensation_param_write(trim_cap);
- #ifdef CONFIG_COMPENSATION_HOSC_CAP_NVRAM_PRIORITY
- // write norflash
- ret_val = spi_nor_freq_compensation_param_write(trim_cap);
- if (ret_val == 0) {
- ret_val = TRIM_CAP_WRITE_NO_ERROR;
- } else {
- ret_val = TRIM_CAP_WRITE_ERR_HW;
- }
- #else
- ret_val = write_efuse_freq_compensation(trim_cap);
- if (mode == RW_TRIM_CAP_SNOR) {
- //efuse has no space
- if (ret_val == -2) {
- //write norflash
- ret_val = spi_nor_freq_compensation_param_write(trim_cap);
- if (ret_val == 0) {
- ret_val = TRIM_CAP_WRITE_NO_ERROR;
- } else {
- ret_val = TRIM_CAP_WRITE_ERR_HW;
- }
- } else if (ret_val == -1) {
- ret_val = TRIM_CAP_WRITE_ERR_HW;
- } else {
- ret_val = TRIM_CAP_WRITE_NO_ERROR;
- }
- } else {
- //efuse has no space
- if (ret_val == -2) {
- ret_val = TRIM_CAP_WRITE_ERR_NO_RESOURSE;
- } else if (ret_val == -1) {
- ret_val = TRIM_CAP_WRITE_ERR_HW;
- } else {
- ret_val = TRIM_CAP_WRITE_NO_ERROR;
- }
- }
- #endif
- return ret_val;
- }
- int freq_compensation_get_cap(uint32_t *cap)
- {
- uint32_t cap_adjust = 0;
- int ret_val;
- ret_val = freq_compensation_read(&cap_adjust, RW_TRIM_CAP_SNOR);
- if (ret_val != TRIM_CAP_READ_NO_ERROR) {
- *cap = CONFIG_COMPENSATION_DEFAULT_HOSC_CAP;
- }
- else{
- *cap = cap_adjust;
- }
- return ret_val;
- }
|