Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
/*
 * 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;
}