1 /*
2 * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3 * Copyright (c) 2015 iComm Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <ssv6200_reg.h>
18 #include <ssv6200_aux.h>
19 #include <linux/fs.h>
20 #include "dev.h"
21 #include "sar.h"
22
23 WIFI_FLASH_CCFG flash_cfg = {
24 //16bytes
25 0x6051, 0x3009, 0x20170519, 0x1, 0x0, 0x0,
26 { //16bytes
27 {0x47c000, 0x47c000, 0x47c000, 0x9, 0x1d, 0x0},
28 //16bytes
29 {0x79807980, 0x79807980, 0x79807980, 0x9, 0x1d, 0x0}
30 }
31 };
32 WIFI_FLASH_CCFG *pflash_cfg;
33
34 struct t_sar_info sar_info[] = {
35 { SAR_LVL_INVALID, 0x0047c000, NULL},
36 { SAR_LVL_INVALID, 0x79807980, NULL}
37 };
38
39 int sar_info_size = sizeof(sar_info) / sizeof(sar_info[0]);
40
flash_hexdump(void)41 void flash_hexdump(void)
42 {
43 unsigned i;
44 const u8 *buf = (const char *)pflash_cfg;
45 size_t len = sizeof(flash_cfg);
46 printk("-----------------------------\n");
47 printk("0x00h:");
48 if (buf == NULL) {
49 printk(" [NULL]");
50 } else {
51 for (i = 0; i < len; i++) {
52 printk(" %02x", buf[i]);
53 if ((i + 1) % 16 == 0) {
54 printk("\n");
55 if (i + 1 < len)
56 printk("0x%02xh:", i + 1);
57 }
58 }
59 }
60 printk("-----------------------------\n");
61 }
62
get_sar_lvl(u32 sar)63 static u8 get_sar_lvl(u32 sar)
64 {
65 static u32 prev_sar = 0;
66 int i;
67 u8 changed = 0x0;
68
69 if (sar == prev_sar)
70 return changed;
71
72 printk("[thermal_sar] %d\n", (int)sar);
73
74 for (i = 0; i < sar_info_size; i++) {
75 if (sar_info[i].lvl == SAR_LVL_INVALID) {//if driver loaded under LT/HT env, it would cause wrong settings at this time.
76 sar_info[i].lvl = SAR_LVL_RT;
77 sar_info[i].value = sar_info[i].p->rt;
78 changed |= BIT(i);
79 }
80 else if (sar_info[i].lvl == SAR_LVL_RT) {
81 if (sar < prev_sar) {
82 if (sar <= (u32)(sar_info[i].p->lt_ts - 2)) { //we need check if (g_tt_lt - 1) < SAR_MIN
83 sar_info[i].lvl = SAR_LVL_LT;
84 sar_info[i].value = sar_info[i].p->lt;
85 changed |= BIT(i);
86 }
87 }
88 else if (sar > prev_sar){
89 if (sar >= (u32)(sar_info[i].p->ht_ts + 2)) { //we need check if (g_tt_lt + 1) > SAR_MAX
90 sar_info[i].lvl = SAR_LVL_HT;
91 sar_info[i].value = sar_info[i].p->ht;
92 changed |= BIT(i);
93 }
94 }
95 }
96 else if (sar_info[i].lvl == SAR_LVL_LT) {
97 if (sar >= (u32)(sar_info[i].p->lt_ts + 2)) {
98 sar_info[i].lvl = SAR_LVL_RT;
99 sar_info[i].value = sar_info[i].p->rt;
100 changed |= BIT(i);
101 }
102 }
103 else if (sar_info[i].lvl == SAR_LVL_HT) {
104 if (sar <= (u32)(sar_info[i].p->ht_ts - 2)) {
105 sar_info[i].lvl = SAR_LVL_RT;
106 sar_info[i].value = sar_info[i].p->rt;
107 changed |= BIT(i);
108 }
109 }
110 }
111 if (changed) {
112 printk("changed: 0x%x\n", changed);
113 }
114 prev_sar = sar;
115 return changed;
116 }
117
sar_monitor(u32 curr_sar,struct ssv_softc * sc)118 void sar_monitor(u32 curr_sar, struct ssv_softc *sc)
119 {
120 //static u32 prev_sar_lvl = SAR_LVL_INVALID; //sar = 0, temparature < -25C
121 u8 changed;
122 changed = get_sar_lvl(curr_sar);
123
124 if (changed & BIT(SAR_TXGAIN_INDEX)) {
125 printk("TXGAIN: 0x%08x\n", sar_info[SAR_TXGAIN_INDEX].value);
126 SMAC_REG_WRITE(sc->sh, ADR_TX_GAIN_FACTOR, sar_info[SAR_TXGAIN_INDEX].value);
127 }
128 if (changed & BIT(SAR_XTAL_INDEX)) {
129 printk("XTAL: 0x%08x\n", sar_info[SAR_XTAL_INDEX].value);
130 SMAC_REG_WRITE(sc->sh, ADR_SYN_KVCO_XO_FINE_TUNE_CBANK, sar_info[SAR_XTAL_INDEX].value);
131 }
132 }
133
134 /*
135 SET_RG_SARADC_THERMAL(1); //ce010030[26]
136 SET_RG_EN_SARADC(1); //ce010030[30]
137 while(!GET_SAR_ADC_FSM_RDY); //ce010094[23]
138 sar_code = GET_RG_SARADC_BIT; //ce010094[21:16]
139 SET_RG_SARADC_THERMAL(0);
140 SET_RG_EN_SARADC(0);
141 */
thermal_monitor(struct work_struct * work)142 void thermal_monitor(struct work_struct *work)
143 {
144 struct ssv_softc *sc = container_of(work, struct ssv_softc, thermal_monitor_work.work);
145 u32 curr_sar;
146
147 u32 temp;
148 if (sc->ps_status == PWRSV_PREPARE) {
149 printk("sar PWRSV_PREPARE\n");
150 return;
151 }
152
153 mutex_lock(&sc->mutex);
154 SMAC_REG_READ(sc->sh, ADR_RX_11B_CCA_1, &temp);
155 if (temp == RX_11B_CCA_IN_SCAN) {
156 printk("in scan\n");
157 mutex_unlock(&sc->mutex);
158 queue_delayed_work(sc->thermal_wq, &sc->thermal_monitor_work, THERMAL_MONITOR_TIME);
159 return;
160 }
161 SMAC_REG_READ(sc->sh, ADR_RX_ADC_REGISTER, &temp);
162 //printk("ori %08x:%08x\n", ADR_RX_ADC_REGISTER, temp);
163 SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (1 << RG_SARADC_THERMAL_SFT),
164 RG_SARADC_THERMAL_MSK);
165 SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (1 << RG_EN_SARADC_SFT),
166 RG_EN_SARADC_MSK);
167
168 do {
169 msleep(1);
170 SMAC_REG_READ(sc->sh, ADR_READ_ONLY_FLAGS_1, &temp);
171 } while (((temp & SAR_ADC_FSM_RDY_MSK) >> SAR_ADC_FSM_RDY_SFT) != 1);
172 //printk("SAR_ADC_FSM_RDY_STAT %d\n", (temp & SAR_ADC_FSM_RDY_MSK) >> SAR_ADC_FSM_RDY_SFT);
173 curr_sar = (temp & RG_SARADC_BIT_MSK) >> RG_SARADC_BIT_SFT;
174 SMAC_REG_READ(sc->sh, ADR_RX_ADC_REGISTER, &temp);
175
176 //printk("new %08x:%08x\n", ADR_RX_ADC_REGISTER, temp);
177
178 SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (0 << RG_SARADC_THERMAL_SFT),
179 RG_SARADC_THERMAL_MSK);
180 SMAC_REG_SET_BITS(sc->sh, ADR_RX_ADC_REGISTER, (0 << RG_EN_SARADC_SFT),
181 RG_EN_SARADC_MSK);
182 sar_monitor(curr_sar, sc);
183
184 mutex_unlock(&sc->mutex);
185
186 queue_delayed_work(sc->thermal_wq, &sc->thermal_monitor_work, THERMAL_MONITOR_TIME);
187 }
188
get_flash_info(struct ssv_softc * sc)189 int get_flash_info(struct ssv_softc *sc)
190 {
191 struct file *fp = (struct file *)NULL;
192 mm_segment_t fs;
193 int i, ret;
194
195 pflash_cfg = &flash_cfg;
196
197 if (sc->sh->cfg.flash_bin_path[0] != 0x00) {
198 fp = filp_open(sc->sh->cfg.flash_bin_path, O_RDONLY, 0);
199 if (IS_ERR(fp) || fp == NULL) {
200 fp = filp_open(SEC_CFG_BIN_NAME, O_RDONLY, 0);
201 }
202 }
203 else{
204 fp = filp_open(DEFAULT_CFG_BIN_NAME, O_RDONLY, 0);
205 if (IS_ERR(fp) || fp == NULL) {
206 fp = filp_open(SEC_CFG_BIN_NAME, O_RDONLY, 0);
207 }
208 }
209 if (IS_ERR(fp) || fp == NULL) {
210 printk("flash_file %s not found, disable sar\n",DEFAULT_CFG_BIN_NAME);
211 //WARN_ON(1);
212 ret = 0;
213 return ret;
214 }
215
216 fs = get_fs();
217 set_fs(KERNEL_DS);
218 fp->f_op->read(fp, (char *)pflash_cfg, sizeof(flash_cfg), &fp->f_pos);
219 set_fs(fs);
220
221 filp_close(fp, NULL);
222 ret = 1;
223
224 flash_hexdump();
225 for (i = 0; i < sar_info_size; i++) {
226 sar_info[i].p = &flash_cfg.sar_rlh[i];
227 printk("rt = %x, lt = %x, ht = %x\n", sar_info[i].p->rt, sar_info[i].p->lt, sar_info[i].p->ht);
228 printk("lt_ts = %x, ht_ts = %x\n", sar_info[i].p->lt_ts, sar_info[i].p->ht_ts);
229 }
230 return ret;
231 }
232
233