/*
|
* Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
|
* Copyright (c) 2015 iComm Corporation
|
*
|
* This program is free software: you can redistribute it and/or modify
|
* it under the terms of the GNU General Public License as published by
|
* the Free Software Foundation, either version 3 of the License, or
|
* (at your option) any later version.
|
* This program is distributed in the hope that it will be useful, but
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* See the GNU General Public License for more details.
|
* You should have received a copy of the GNU General Public License
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
*/
|
|
#include <ssv6200_reg.h>
|
#include <ssv6200_aux.h>
|
#include <linux/fs.h>
|
#include "dev.h"
|
#include "sar.h"
|
|
WIFI_FLASH_CCFG flash_cfg = {
|
//16bytes
|
0x6051, 0x3009, 0x20170519, 0x1, 0x0, 0x0,
|
{ //16bytes
|
{0x47c000, 0x47c000, 0x47c000, 0x9, 0x1d, 0x0},
|
//16bytes
|
{0x79807980, 0x79807980, 0x79807980, 0x9, 0x1d, 0x0}
|
}
|
};
|
WIFI_FLASH_CCFG *pflash_cfg;
|
|
struct t_sar_info sar_info[] = {
|
{ SAR_LVL_INVALID, 0x0047c000, NULL},
|
{ SAR_LVL_INVALID, 0x79807980, NULL}
|
};
|
|
int sar_info_size = sizeof(sar_info) / sizeof(sar_info[0]);
|
|
void flash_hexdump(void)
|
{
|
unsigned i;
|
const u8 *buf = (const char *)pflash_cfg;
|
size_t len = sizeof(flash_cfg);
|
printk("-----------------------------\n");
|
printk("0x00h:");
|
if (buf == NULL) {
|
printk(" [NULL]");
|
} else {
|
for (i = 0; i < len; i++) {
|
printk(" %02x", buf[i]);
|
if ((i + 1) % 16 == 0) {
|
printk("\n");
|
if (i + 1 < len)
|
printk("0x%02xh:", i + 1);
|
}
|
}
|
}
|
printk("-----------------------------\n");
|
}
|
|
static u8 get_sar_lvl(u32 sar)
|
{
|
static u32 prev_sar = 0;
|
int i;
|
u8 changed = 0x0;
|
|
if (sar == prev_sar)
|
return changed;
|
|
printk("[thermal_sar] %d\n", (int)sar);
|
|
for (i = 0; i < sar_info_size; i++) {
|
if (sar_info[i].lvl == SAR_LVL_INVALID) {//if driver loaded under LT/HT env, it would cause wrong settings at this time.
|
sar_info[i].lvl = SAR_LVL_RT;
|
sar_info[i].value = sar_info[i].p->rt;
|
changed |= BIT(i);
|
}
|
else if (sar_info[i].lvl == SAR_LVL_RT) {
|
if (sar < prev_sar) {
|
if (sar <= (u32)(sar_info[i].p->lt_ts - 2)) { //we need check if (g_tt_lt - 1) < SAR_MIN
|
sar_info[i].lvl = SAR_LVL_LT;
|
sar_info[i].value = sar_info[i].p->lt;
|
changed |= BIT(i);
|
}
|
}
|
else if (sar > prev_sar){
|
if (sar >= (u32)(sar_info[i].p->ht_ts + 2)) { //we need check if (g_tt_lt + 1) > SAR_MAX
|
sar_info[i].lvl = SAR_LVL_HT;
|
sar_info[i].value = sar_info[i].p->ht;
|
changed |= BIT(i);
|
}
|
}
|
}
|
else if (sar_info[i].lvl == SAR_LVL_LT) {
|
if (sar >= (u32)(sar_info[i].p->lt_ts + 2)) {
|
sar_info[i].lvl = SAR_LVL_RT;
|
sar_info[i].value = sar_info[i].p->rt;
|
changed |= BIT(i);
|
}
|
}
|
else if (sar_info[i].lvl == SAR_LVL_HT) {
|
if (sar <= (u32)(sar_info[i].p->ht_ts - 2)) {
|
sar_info[i].lvl = SAR_LVL_RT;
|
sar_info[i].value = sar_info[i].p->rt;
|
changed |= BIT(i);
|
}
|
}
|
}
|
if (changed) {
|
printk("changed: 0x%x\n", changed);
|
}
|
prev_sar = sar;
|
return changed;
|
}
|
|
void sar_monitor(u32 curr_sar, struct ssv_softc *sc)
|
{
|
//static u32 prev_sar_lvl = SAR_LVL_INVALID; //sar = 0, temparature < -25C
|
u8 changed;
|
changed = get_sar_lvl(curr_sar);
|
|
if (changed & BIT(SAR_TXGAIN_INDEX)) {
|
printk("TXGAIN: 0x%08x\n", sar_info[SAR_TXGAIN_INDEX].value);
|
SMAC_REG_WRITE(sc->sh, ADR_TX_GAIN_FACTOR, sar_info[SAR_TXGAIN_INDEX].value);
|
}
|
if (changed & BIT(SAR_XTAL_INDEX)) {
|
printk("XTAL: 0x%08x\n", sar_info[SAR_XTAL_INDEX].value);
|
SMAC_REG_WRITE(sc->sh, ADR_SYN_KVCO_XO_FINE_TUNE_CBANK, sar_info[SAR_XTAL_INDEX].value);
|
}
|
}
|
|
/*
|
SET_RG_SARADC_THERMAL(1); //ce010030[26]
|
SET_RG_EN_SARADC(1); //ce010030[30]
|
while(!GET_SAR_ADC_FSM_RDY); //ce010094[23]
|
sar_code = GET_RG_SARADC_BIT; //ce010094[21:16]
|
SET_RG_SARADC_THERMAL(0);
|
SET_RG_EN_SARADC(0);
|
*/
|
void thermal_monitor(struct work_struct *work)
|
{
|
struct ssv_softc *sc = container_of(work, struct ssv_softc, thermal_monitor_work.work);
|
u32 curr_sar;
|
|
u32 temp;
|
if (sc->ps_status == PWRSV_PREPARE) {
|
printk("sar PWRSV_PREPARE\n");
|
return;
|
}
|
|
mutex_lock(&sc->mutex);
|
SMAC_REG_READ(sc->sh, ADR_RX_11B_CCA_1, &temp);
|
if (temp == RX_11B_CCA_IN_SCAN) {
|
printk("in scan\n");
|
mutex_unlock(&sc->mutex);
|
queue_delayed_work(sc->thermal_wq, &sc->thermal_monitor_work, THERMAL_MONITOR_TIME);
|
return;
|
}
|
SMAC_REG_READ(sc->sh, ADR_RX_ADC_REGISTER, &temp);
|
//printk("ori %08x:%08x\n", ADR_RX_ADC_REGISTER, temp);
|
SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (1 << RG_SARADC_THERMAL_SFT),
|
RG_SARADC_THERMAL_MSK);
|
SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (1 << RG_EN_SARADC_SFT),
|
RG_EN_SARADC_MSK);
|
|
do {
|
msleep(1);
|
SMAC_REG_READ(sc->sh, ADR_READ_ONLY_FLAGS_1, &temp);
|
} while (((temp & SAR_ADC_FSM_RDY_MSK) >> SAR_ADC_FSM_RDY_SFT) != 1);
|
//printk("SAR_ADC_FSM_RDY_STAT %d\n", (temp & SAR_ADC_FSM_RDY_MSK) >> SAR_ADC_FSM_RDY_SFT);
|
curr_sar = (temp & RG_SARADC_BIT_MSK) >> RG_SARADC_BIT_SFT;
|
SMAC_REG_READ(sc->sh, ADR_RX_ADC_REGISTER, &temp);
|
|
//printk("new %08x:%08x\n", ADR_RX_ADC_REGISTER, temp);
|
|
SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (0 << RG_SARADC_THERMAL_SFT),
|
RG_SARADC_THERMAL_MSK);
|
SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (0 << RG_EN_SARADC_SFT),
|
RG_EN_SARADC_MSK);
|
sar_monitor(curr_sar, sc);
|
|
mutex_unlock(&sc->mutex);
|
|
queue_delayed_work(sc->thermal_wq, &sc->thermal_monitor_work, THERMAL_MONITOR_TIME);
|
}
|
|
int get_flash_info(struct ssv_softc *sc)
|
{
|
struct file *fp = (struct file *)NULL;
|
mm_segment_t fs;
|
int i, ret;
|
|
pflash_cfg = &flash_cfg;
|
|
if (sc->sh->cfg.flash_bin_path[0] != 0x00) {
|
fp = filp_open(sc->sh->cfg.flash_bin_path, O_RDONLY, 0);
|
if (IS_ERR(fp) || fp == NULL) {
|
fp = filp_open(SEC_CFG_BIN_NAME, O_RDONLY, 0);
|
}
|
}
|
else{
|
fp = filp_open(DEFAULT_CFG_BIN_NAME, O_RDONLY, 0);
|
if (IS_ERR(fp) || fp == NULL) {
|
fp = filp_open(SEC_CFG_BIN_NAME, O_RDONLY, 0);
|
}
|
}
|
if (IS_ERR(fp) || fp == NULL) {
|
printk("flash_file %s not found, disable sar\n",DEFAULT_CFG_BIN_NAME);
|
//WARN_ON(1);
|
ret = 0;
|
return ret;
|
}
|
|
fs = get_fs();
|
set_fs(KERNEL_DS);
|
fp->f_op->read(fp, (char *)pflash_cfg, sizeof(flash_cfg), &fp->f_pos);
|
set_fs(fs);
|
|
filp_close(fp, NULL);
|
ret = 1;
|
|
flash_hexdump();
|
for (i = 0; i < sar_info_size; i++) {
|
sar_info[i].p = &flash_cfg.sar_rlh[i];
|
printk("rt = %x, lt = %x, ht = %x\n", sar_info[i].p->rt, sar_info[i].p->lt, sar_info[i].p->ht);
|
printk("lt_ts = %x, ht_ts = %x\n", sar_info[i].p->lt_ts, sar_info[i].p->ht_ts);
|
}
|
return ret;
|
}
|