blob: dec8880534fbb87d22d9c1a80c8d3b73935594eb [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * mediatek-mcupm-cpufreq.c - MCUPM based CPUFreq Driver
4 *
5 * Copyright (c) 2020 MediaTek Inc.
6 * Wei-Chia Su <Wei-Chia.Su@mediatek.com>
7 */
8
9#include <linux/clk.h>
10#include <linux/cpu.h>
11#include <linux/cpufreq.h>
12#include <linux/cpumask.h>
13#include <linux/energy_model.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18#include <linux/of_device.h>
19#include <linux/of_platform.h>
20#include <linux/platform_device.h>
21#include <linux/pm_opp.h>
22#include <linux/proc_fs.h>
23#include <linux/seq_file.h>
24#include <linux/regulator/consumer.h>
25#include <linux/soc/mediatek/mtk_tinysys_ipi.h>
26#include <linux/uaccess.h>
27#include <mcupm_ipi_id.h>
28#include <mcupm_driver.h>
29#include <linux/delay.h>
30#include <linux/nvmem-consumer.h>
31
32#define OFFS_WFI_S 0x037c
33#define DVFS_D_LEN (4)
34#define CSRAM_SIZE 0x1400
35#define OFFS_LOG_S 0x03d0
36#define DBG_REPO_NUM (CSRAM_SIZE / sizeof(u32))
37#define REPO_I_LOG_S (OFFS_LOG_S / sizeof(u32))
38#define ENTRY_EACH_LOG 5
39#define VMIN_PREDICT_ENABLE (0)
40#define NR_PI_VF 6
41#define MAX_NR_FREQ 32
42#define MIN_SIZE_SN_DUMP_CPE (7)
43#define NUM_SN_CPU (8)
44#define SIZE_SN_MCUSYS_REG (10)
45#define SIZE_SN_DUMP_SENSOR (64)
46#define IDX_HW_RES_SN (18)
47#define DEVINFO_IDX_0 0xC8
48#define DEVINFO_HRID_0 0x30
49#define EEMSN_CSRAM_BASE 0x0011BC00
50#define LOW_TEMP_OFF (8)
51#define HIGH_TEMP_OFF (3)
52#define AGING_VAL_CPU (0x6)
53#define EEM_TAG "[CPU][EEM]"
54#define SUPPORT_PICACHU (1)
55#if SUPPORT_PICACHU
56#define PICACHU_SIG (0xA5)
57#define PICACHU_SIGNATURE_SHIFT_BIT (24)
58#define EEM_PHY_SPARE0 0x11278F20
59#endif
60#undef BIT
61#define BIT(bit) (1U << (bit))
62
63#define eem_read(addr) __raw_readl((void __iomem *)(addr))
64
65#define PROC_FOPS_RW(name) \
66 static int name ## _proc_open(struct inode *inode, struct file *file) \
67{ \
68 return single_open(file, name ## _proc_show, PDE_DATA(inode)); \
69} \
70static const struct file_operations name ## _proc_fops = { \
71 .owner = THIS_MODULE, \
72 .open = name ## _proc_open, \
73 .read = seq_read, \
74 .llseek = seq_lseek, \
75 .release = single_release, \
76 .write = name ## _proc_write, \
77}
78
79#define PROC_FOPS_RO(name) \
80static int name##_proc_open(struct inode *inode, struct file *file) \
81{ \
82 return single_open(file, name##_proc_show, PDE_DATA(inode)); \
83} \
84static const struct file_operations name##_proc_fops = { \
85 .owner = THIS_MODULE, \
86 .open = name##_proc_open, \
87 .read = seq_read, \
88 .llseek = seq_lseek, \
89 .release = single_release, \
90}
91
92#define PROC_ENTRY(name) {__stringify(name), &name ## _proc_fops}
93#define PROC_ENTRY_DATA(name) {__stringify(name), &name ## _proc_fops, g_ ## name}
94
95enum mt_cpu_dvfs_id {
96 MT_CPU_DVFS_LL,
97 MT_CPU_DVFS_CCI,
98
99 NR_MT_CPU_DVFS,
100};
101
102enum eem_phase {
103 EEM_PHASE_INIT01,
104 EEM_PHASE_INIT02,
105 EEM_PHASE_MON,
106 EEM_PHASE_SEN,
107
108 NR_EEM_PHASE,
109};
110
111enum eem_features {
112 FEA_INIT01 = BIT(EEM_PHASE_INIT01),
113 FEA_INIT02 = BIT(EEM_PHASE_INIT02),
114 FEA_MON = BIT(EEM_PHASE_MON),
115 FEA_SEN = BIT(EEM_PHASE_SEN),
116};
117
118enum {
119 IPI_EEMSN_SHARERAM_INIT,
120 IPI_EEMSN_INIT,
121 IPI_EEMSN_PROBE,
122 IPI_EEMSN_INIT01,
123 IPI_EEMSN_GET_EEM_VOLT,
124 IPI_EEMSN_INIT02,
125 IPI_EEMSN_DEBUG_PROC_WRITE,
126 IPI_EEMSN_SEND_UPOWER_TBL_REF,
127 IPI_EEMSN_CUR_VOLT_PROC_SHOW,
128 IPI_EEMSN_DUMP_PROC_SHOW,
129 IPI_EEMSN_AGING_DUMP_PROC_SHOW,
130 IPI_EEMSN_OFFSET_PROC_WRITE,
131 IPI_EEMSN_SNAGING_PROC_WRITE,
132 IPI_EEMSN_LOGEN_PROC_SHOW,
133 IPI_EEMSN_LOGEN_PROC_WRITE,
134 IPI_EEMSN_EN_PROC_SHOW,
135 IPI_EEMSN_EN_PROC_WRITE,
136 IPI_EEMSN_SNEN_PROC_SHOW,
137 IPI_EEMSN_SNEN_PROC_WRITE,
138 IPI_EEMSN_FAKE_SN_INIT_ISR,
139 IPI_EEMSN_FORCE_SN_SENSING,
140 IPI_EEMSN_PULL_DATA,
141 IPI_EEMSN_FAKE_SN_SENSING_ISR,
142 NR_EEMSN_IPI,
143};
144
145enum eemsn_det_id {
146 EEMSN_DET_L,
147 EEMSN_DET_CCI,
148
149 NR_EEMSN_DET,
150};
151
152enum sn_det_id {
153 SN_DET_L = 0,
154
155 NR_SN_DET,
156};
157
158enum cpu_dvfs_ipi_type {
159 IPI_DVFS_INIT,
160 NR_DVFS_IPI,
161};
162
163static void __iomem *csram_base;
164u32 *g_dbg_repo;
165int ipi_ackdata;
166unsigned char ctrl_agingload_enable;
167static struct eemsn_dbg_log *eemsn_log;
168unsigned int seq;
169static LIST_HEAD(dvfs_info_list);
170struct nvmem_device *nvmem_dev;
171struct cdvfs_data {
172 unsigned int cmd;
173 union {
174 struct {
175 unsigned int arg[3];
176 } set_fv;
177 } u;
178};
179
180struct mtk_cpu_dvfs_info {
181 struct cpumask cpus;
182 struct device *cpu_dev;
183 struct list_head list_head;
184 struct mutex lock;
185 void __iomem *csram_base;
186};
187
188static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
189{
190 struct mtk_cpu_dvfs_info *info;
191 struct list_head *list;
192
193 list_for_each(list, &dvfs_info_list) {
194 info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
195 if (cpumask_test_cpu(cpu, &info->cpus))
196 return info;
197 }
198 return NULL;
199}
200
201static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
202 unsigned int index)
203{
204 struct mtk_cpu_dvfs_info *info = policy->driver_data;
205 unsigned int cluster_id = policy->cpu / 4;
206
207 writel_relaxed(index, info->csram_base + (OFFS_WFI_S + (cluster_id * 4))
208 );
209 arch_set_freq_scale(policy->related_cpus,
210 policy->freq_table[index].frequency,
211 policy->cpuinfo.max_freq);
212
213 return 0;
214}
215
216static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
217{
218 struct device *cpu_dev;
219 int ret;
220
221 cpu_dev = get_cpu_device(cpu);
222 if (!cpu_dev)
223 return -ENODEV;
224
225 ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
226 if (ret)
227 goto out_free_resources;
228
229 ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
230 if (ret)
231 goto out_free_resources;
232
233 info->cpu_dev = cpu_dev;
234 mutex_init(&info->lock);
235
236 return 0;
237
238out_free_resources:
239 return ret;
240}
241
242static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
243{
244 dev_pm_opp_of_cpumask_remove_table(&info->cpus);
245}
246
247static int mtk_cpufreq_init(struct cpufreq_policy *policy)
248{
249 struct mtk_cpu_dvfs_info *info;
250 struct cpufreq_frequency_table *freq_table;
251 struct em_data_callback em_cb = EM_DATA_CB(of_dev_pm_opp_get_cpu_power);
252 int ret;
253
254 info = mtk_cpu_dvfs_info_lookup(policy->cpu);
255 if (!info)
256 return -EINVAL;
257
258 ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
259 if (ret)
260 return -EINVAL;
261
262 ret = dev_pm_opp_get_opp_count(info->cpu_dev);
263 if (ret <= 0) {
264 ret = -EINVAL;
265 goto out_free_cpufreq_table;
266 }
267
268 cpumask_copy(policy->cpus, &info->cpus);
269 em_register_perf_domain(policy->cpus, ret, &em_cb);
270 policy->driver_data = info;
271 policy->freq_table = freq_table;
272 policy->transition_delay_us = 1000; /* us */
273
274 return 0;
275
276out_free_cpufreq_table:
277 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
278
279 return ret;
280}
281
282static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
283{
284 struct mtk_cpu_dvfs_info *info = policy->driver_data;
285
286 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
287
288 return 0;
289}
290
291static struct cpufreq_driver mtk_cpufreq_driver = {
292 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
293 CPUFREQ_HAVE_GOVERNOR_PER_POLICY | CPUFREQ_IS_COOLING_DEV,
294 .verify = cpufreq_generic_frequency_table_verify,
295 .target_index = mtk_cpufreq_set_target,
296 .init = mtk_cpufreq_init,
297 .exit = mtk_cpufreq_exit,
298 .name = "mtk-cpufreq",
299 .attr = cpufreq_generic_attr,
300};
301
302struct A_Tused_VT {
303 unsigned int A_Tused_SVT:8;
304 unsigned int A_Tused_LVT:8;
305 unsigned int A_Tused_ULVT:8;
306 unsigned int A_Tused_RSV0:8;
307};
308
309struct dvfs_vf_tbl {
310 unsigned short pi_freq_tbl[NR_PI_VF];
311 unsigned char pi_volt_tbl[NR_PI_VF];
312 unsigned char pi_vf_num;
313};
314
315struct sensing_stru {
316#if defined(VMIN_PREDICT_ENABLE)
317 uint64_t CPE_Vmin_HW;
318#endif
319 unsigned int SN_Vmin;
320 int CPE_Vmin;
321 unsigned int cur_volt;
322#if !VMIN_PREDICT_ENABLE
323 /* unsigned int count_cur_volt_HT; */
324 int Sensor_Volt_HT;
325 int Sensor_Volt_RT;
326 int8_t CPE_temp;
327 int8_t SN_temp;
328 unsigned char T_SVT_current;
329#endif
330 unsigned short cur_temp;
331 unsigned char cur_oppidx;
332 unsigned char dst_volt_pmic;
333};
334
335struct eemsn_log_det {
336 unsigned char mc50flag;
337 unsigned char features;
338 int8_t volt_clamp;
339 int8_t volt_offset;
340};
341
342struct eemsn_vlog_det {
343 unsigned int temp;
344 unsigned short freq_tbl[MAX_NR_FREQ];
345 unsigned short volt_tbl_pmic[MAX_NR_FREQ];
346 unsigned char volt_tbl_orig[MAX_NR_FREQ];
347 unsigned char volt_tbl_init2[MAX_NR_FREQ];
348 /* unsigned char volt_tbl[NR_FREQ]; */
349 unsigned char num_freq_tbl;
350 unsigned char lock;
351 unsigned char turn_pt;
352 enum eemsn_det_id det_id;
353};
354
355struct eemsn_devinfo {
356 /* M_HW_RES0 0x11c1_0580 */
357 unsigned int FT_PGM:8;
358 unsigned int FT_BIN:4;
359 unsigned int RSV0_1:20;
360
361 /* M_HW_RES1 */
362 unsigned int CPU_B_MTDES:8;
363 unsigned int CPU_B_INITEN:1;
364 unsigned int CPU_B_MONEN:1;
365 unsigned int CPU_B_DVFS_LOW:3;
366 unsigned int CPU_B_SPEC:3;
367 unsigned int CPU_B_BDES:8;
368 unsigned int CPU_B_MDES:8;
369
370 /* M_HW_RES2 */
371 unsigned int CPU_B_HI_MTDES:8;
372 unsigned int CPU_B_HI_INITEN:1;
373 unsigned int CPU_B_HI_MONEN:1;
374 unsigned int CPU_B_HI_DVFS_LOW:3;
375 unsigned int CPU_B_HI_SPEC:3;
376 unsigned int CPU_B_HI_BDES:8;
377 unsigned int CPU_B_HI_MDES:8;
378
379 /* M_HW_RES3 */
380 unsigned int CPU_B_LO_MTDES:8;
381 unsigned int CPU_B_LO_INITEN:1;
382 unsigned int CPU_B_LO_MONEN:1;
383 unsigned int CPU_B_LO_DVFS_LOW:3;
384 unsigned int CPU_B_LO_SPEC:3;
385 unsigned int CPU_B_LO_BDES:8;
386 unsigned int CPU_B_LO_MDES:8;
387
388 /* M_HW_RES4 */
389 unsigned int CCI_LO_MTDES:8;
390 unsigned int CCI_LO_INITEN:1;
391 unsigned int CCI_LO_MONEN:1;
392 unsigned int CCI_LO_DVFS_LOW:3;
393 unsigned int CCI_LO_SPEC:3;
394 unsigned int CCI_LO_BDES:8;
395 unsigned int CCI_LO_MDES:8;
396
397 /* M_HW_RES5 */
398 unsigned int CPU_L_MTDES:8;
399 unsigned int CPU_L_INITEN:1;
400 unsigned int CPU_L_MONEN:1;
401 unsigned int CPU_L_DVFS_LOW:3;
402 unsigned int CPU_L_SPEC:3;
403 unsigned int CPU_L_BDES:8;
404 unsigned int CPU_L_MDES:8;
405
406 /* M_HW_RES6 */
407 unsigned int CPU_L_HI_MTDES:8;
408 unsigned int CPU_L_HI_INITEN:1;
409 unsigned int CPU_L_HI__MONEN:1;
410 unsigned int CPU_L_HI_DVFS_LOW:3;
411 unsigned int CPU_L_HI_SPEC:3;
412 unsigned int CPU_L_HI_BDES:8;
413 unsigned int CPU_L_HI_MDES:8;
414
415 /* M_HW_RES7 */
416 unsigned int CPU_B_HI_DCBDET:8;
417 unsigned int CPU_B_HI_DCMDET:8;
418 unsigned int CPU_B_DCBDET:8;
419 unsigned int CPU_B_DCMDET:8;
420
421 /* M_HW_RES8 */
422 unsigned int CCI_LO_DCBDET:8;
423 unsigned int CCI_LO_DCMDET:8;
424 unsigned int CCI_HI_DCBDET:8;
425 unsigned int CCI_HI_DCMDET:8;
426
427 /* M_HW_RES */
428 unsigned int CPU_L_LO_MTDES:8;
429 unsigned int CPU_L_LO_INITEN:1;
430 unsigned int CPU_L_LO_MONEN:1;
431 unsigned int CPU_L_LO_DVFS_LOW:3;
432 unsigned int CPU_L_LO_SPEC:3;
433 unsigned int CPU_L_LO_BDES:8;
434 unsigned int CPU_L_LO_MDES:8;
435
436 /* M_HW_RES */
437 unsigned int CCI_HI_MTDES:8;
438 unsigned int CCI_HI_INITEN:1;
439 unsigned int CCI_HI_MONEN:1;
440 unsigned int CCI_HI_DVFS_LOW:3;
441 unsigned int CCI_HI_SPEC:3;
442 unsigned int CCI_HI_BDES:8;
443 unsigned int CCI_HI_MDES:8;
444
445 /* M_HW_RES9 */
446 unsigned int GPU_HI_MTDES:8;
447 unsigned int GPU_HI_INITEN:1;
448 unsigned int GPU_HI_MONEN:1;
449 unsigned int GPU_HI_DVFS_LOW:3;
450 unsigned int GPU_HI_SPEC:3;
451 unsigned int GPU_HI_BDES:8;
452 unsigned int GPU_HI_MDES:8;
453
454 /* M_HW_RES10 */
455 unsigned int GPU_LO_MTDES:8;
456 unsigned int GPU_LO_INITEN:1;
457 unsigned int GPU_LO_MONEN:1;
458 unsigned int GPU_LO_DVFS_LOW:3;
459 unsigned int GPU_LO_SPEC:3;
460 unsigned int GPU_LO_BDES:8;
461 unsigned int GPU_LO_MDES:8;
462
463 /* M_HW_RES11 */
464 unsigned int MD_VMODEM:32;
465
466 /* M_HW_RES12 */
467 unsigned int MD_VNR:32;
468
469 /* M_HW_RES14 */
470 unsigned int CPU_L_DCBDET:8;
471 unsigned int CPU_L_DCMDET:8;
472 unsigned int CPU_B_LO_DCBDET:8;
473 unsigned int CPU_B_LO_DCMDET:8;
474
475 /* M_HW_RES15 */
476 unsigned int CPU_L_LO_DCBDET:8;
477 unsigned int CPU_L_LO_DCMDET:8;
478 unsigned int CPU_L_HI_DCBDET:8;
479 unsigned int CPU_L_HI_DCMDET:8;
480
481 /* M_HW_RES17 */
482 unsigned int GPU_LO_DCBDET:8;
483 unsigned int GPU_LO_DCMDET:8;
484 unsigned int GPU_HI_DCBDET:8;
485 unsigned int GPU_HI_DCMDET:8;
486
487 /* M_HW_RES21 */
488 unsigned int BCPU_A_T0_SVT:8;
489 unsigned int BCPU_A_T0_LVT:8;
490 unsigned int BCPU_A_T0_ULVT:8;
491 unsigned int LCPU_A_T0_SVT:8;
492
493 /* M_HW_RES22 */
494 unsigned int LCPU_A_T0_LVT:8;
495 unsigned int LCPU_A_T0_ULVT:8;
496 unsigned int RES22_RSV:16;
497
498 /* M_HW_RES23 */
499 unsigned int FINAL_VMIN_BCPU:8;
500 unsigned int FINAL_VMIN_LCPU:8;
501 unsigned int ATE_TEMP:8;
502 unsigned int SN_PATTERN:4;
503 unsigned int SN_VERSION:4;
504
505 /* M_HW_RES24 */
506 unsigned int T_SVT_HV_BCPU:8;
507 unsigned int T_SVT_LV_BCPU:8;
508 unsigned int T_SVT_HV_LCPU:8;
509 unsigned int T_SVT_LV_LCPU:8;
510
511 /* M_HW_RES25 */
512 unsigned int T_SVT_HV_BCPU_RT:8;
513 unsigned int T_SVT_LV_BCPU_RT:8;
514 unsigned int T_SVT_HV_LCPU_RT:8;
515 unsigned int T_SVT_LV_LCPU_RT:8;
516
517 /* M_HW_RES26 */
518 unsigned int FPC_RECORVERY_BCPU:8;
519 unsigned int CPE_VMIN_BCPU:8;
520 unsigned int FPC_RECORVERY_LCPU:8;
521 unsigned int CPE_VMIN_LCPU:8;
522};
523
524struct sn_log_data {
525 unsigned long long timestamp;
526 unsigned int reg_dump_cpe[MIN_SIZE_SN_DUMP_CPE];
527 unsigned int reg_dump_sndata[SIZE_SN_DUMP_SENSOR];
528 unsigned int reg_dump_sn_cpu[NUM_SN_CPU][SIZE_SN_MCUSYS_REG];
529 struct sensing_stru sd[NR_SN_DET];
530 unsigned int footprint[NR_SN_DET];
531 unsigned int allfp;
532#if VMIN_PREDICT_ENABLE
533 unsigned int sn_cpe_vop;
534#endif
535};
536
537struct sn_log_cal_data {
538 int64_t cpe_init_aging;
539 struct A_Tused_VT atvt;
540 int TEMP_CAL;
541 int volt_cross;
542 short CPE_Aging;
543 int8_t sn_aging;
544 int8_t delta_vc;
545 uint8_t T_SVT_HV_RT;
546 uint8_t T_SVT_LV_RT;
547};
548
549struct sn_param {
550 int Param_A_Tused_SVT;
551 int Param_A_Tused_LVT;
552 int Param_A_Tused_ULVT;
553 int Param_A_T0_SVT;
554 int Param_A_T0_LVT;
555 int Param_A_T0_ULVT;
556 int Param_ATE_temp;
557 int Param_temp;
558 int Param_INTERCEPTION;
559 int8_t A_GB;
560 int8_t sn_temp_threshold;
561 int8_t Default_Aging;
562 int8_t threshold_H;
563 int8_t threshold_L;
564
565 unsigned char T_GB;
566
567 /* Formula for CPE_Vmin (Vmin prediction) */
568 unsigned char CPE_GB;
569 unsigned char MSSV_GB;
570
571};
572
573struct eemsn_log {
574 struct dvfs_vf_tbl vf_tbl_det[NR_EEMSN_DET];
575 unsigned char eemsn_enable;
576 unsigned char sn_enable;
577 unsigned char ctrl_aging_Enable;
578 struct eemsn_log_det det_log[NR_EEMSN_DET];
579};
580
581struct eemsn_det {
582 int64_t cpe_init_aging;
583 int temp; /* det temperature */
584
585 /* dvfs */
586 unsigned int cur_volt;
587 unsigned int *p_sn_cpu_coef;
588 struct sn_param *p_sn_cpu_param;
589 enum eemsn_det_id det_id;
590
591 unsigned int volt_tbl_pmic[MAX_NR_FREQ]; /* pmic value */
592
593 /* for PMIC */
594 unsigned short eemsn_v_base;
595 unsigned short eemsn_step;
596 unsigned short pmic_base;
597 unsigned short pmic_step;
598 short cpe_volt_total_mar;
599
600 /* dvfs */
601 unsigned short freq_tbl[MAX_NR_FREQ];
602 unsigned char volt_tbl_init2[MAX_NR_FREQ]; /* eem value */
603 unsigned char volt_tbl_orig[MAX_NR_FREQ]; /* pmic value */
604 unsigned char dst_volt_pmic;
605 unsigned char volt_tbl0_min; /* pmic value */
606
607 unsigned char features; /* enum eemsn_features */
608 unsigned char cur_phase;
609 unsigned char cur_oppidx;
610
611 const char *name;
612
613 unsigned char disabled; /* Disabled by error or sysfs */
614 unsigned char num_freq_tbl;
615
616 unsigned char turn_pt;
617 unsigned char vmin_high;
618 unsigned char vmin_mid;
619 int8_t delta_vc;
620 int8_t sn_aging;
621 int8_t volt_offset;
622 int8_t volt_clamp;
623 /* int volt_offset:8; */
624 unsigned int delta_ir:4;
625 unsigned int delta_vdppm:5;
626};
627
628struct eemsn_dbg_log {
629 struct dvfs_vf_tbl vf_tbl_det[NR_EEMSN_DET];
630 unsigned char eemsn_enable;
631 unsigned char sn_enable;
632 unsigned char ctrl_aging_Enable;
633 struct eemsn_log_det det_log[NR_EEMSN_DET];
634 struct eemsn_vlog_det det_vlog[NR_EEMSN_DET];
635 struct sn_log_data sn_log;
636 struct sn_log_cal_data sn_cal_data[NR_SN_DET];
637 struct sn_param sn_cpu_param[NR_SN_DET];
638 struct eemsn_devinfo efuse_devinfo;
639 unsigned int efuse_sv;
640 unsigned int efuse_sv2;
641 unsigned int picachu_sn_mem_base_phys;
642 unsigned char init2_v_ready;
643 unsigned char init_vboot_done;
644 unsigned char segCode;
645 unsigned char lock;
646};
647
648
649struct eem_ipi_data {
650 unsigned int cmd;
651 union {
652 struct {
653 unsigned int arg[3];
654 } data;
655 } u;
656};
657
658#define det_to_id(det) ((det) - &eemsn_detectors[0])
659
660struct eemsn_det eemsn_detectors[NR_EEMSN_DET] = {
661 [EEMSN_DET_L] = {
662 .name = "EEM_DET_L",
663 .det_id = EEMSN_DET_L,
664 .features = FEA_INIT01 | FEA_INIT02 | FEA_MON | FEA_SEN,
665 .volt_offset = 0,
666 },
667 [EEMSN_DET_CCI] = {
668 .name = "EEM_DET_CCI",
669 .det_id = EEMSN_DET_CCI,
670 .features = FEA_INIT02 | FEA_MON,
671 .volt_offset = 0,
672 },
673};
674
675#define for_each_det(det) \
676 for (det = eemsn_detectors; \
677 det < (eemsn_detectors + ARRAY_SIZE(eemsn_detectors)); \
678 det++)
679
680static unsigned int eem_to_cpueb(unsigned int cmd,
681 struct eem_ipi_data *eem_data)
682{
683 unsigned int ret;
684
685 pr_debug("to_cpueb, cmd:%d\n", cmd);
686 eem_data->cmd = cmd;
687
688 ret = mtk_ipi_send_compl(&mcupm_ipidev, CH_S_EEMSN,
689 /*IPI_SEND_WAIT*/IPI_SEND_POLLING, eem_data,
690 sizeof(struct eem_ipi_data)/MBOX_SLOT_SIZE, 2000);
691
692 return ret;
693}
694
695unsigned int detid_to_dvfsid(struct eemsn_det *det)
696{
697 unsigned int cpudvfsindex;
698 enum eemsn_det_id detid = det_to_id(det);
699
700 if (detid == EEMSN_DET_L)
701 cpudvfsindex = MT_CPU_DVFS_LL;
702 else
703 cpudvfsindex = MT_CPU_DVFS_CCI;
704
705 pr_debug("[%s] id:%d, cpudvfsindex:%d\n", __func__,
706 detid, cpudvfsindex);
707
708 return cpudvfsindex;
709}
710
711static int dbg_repo_proc_show(struct seq_file *m, void *v)
712{
713 int i;
714 u32 *repo = m->private;
715 char ch;
716
717 for (i = 0; i < DBG_REPO_NUM; i++) {
718 if (i >= REPO_I_LOG_S && (i - REPO_I_LOG_S) %
719 ENTRY_EACH_LOG == 0)
720 ch = ':'; /* timestamp */
721 else
722 ch = '.';
723
724 seq_printf(m, "%4d%c%08x%c",
725 i, ch, repo[i], i % 4 == 3 ? '\n' : ' ');
726 }
727
728 return 0;
729}
730/*
731 * ===============================================
732 * PROCFS interface for debugging
733 * ===============================================
734 */
735
736/*
737 * show current EEM stauts
738 */
739static int eem_debug_proc_show(struct seq_file *m, void *v)
740{
741 struct eemsn_det *det = (struct eemsn_det *)m->private;
742
743 /* FIXME: EEMEN sometimes is disabled temp */
744 seq_printf(m, "[%s] %s\n",
745 ((char *)(det->name) + 8),
746 det->disabled ? "disabled" : "enable"
747 );
748
749 return 0;
750}
751
752/*
753 * set EEM status by procfs interface
754 */
755static ssize_t eem_debug_proc_write(struct file *file,
756 const char __user *buffer, size_t count, loff_t *pos)
757{
758 int ret;
759 int enabled = 0;
760 char *buf = (char *) __get_free_page(GFP_USER);
761 struct eemsn_det *det = (struct eemsn_det *)PDE_DATA(file_inode(file));
762 struct eem_ipi_data eem_data;
763 int ipi_ret = 0;
764
765 if (!buf)
766 return -ENOMEM;
767
768 ret = -EINVAL;
769
770 if (count >= PAGE_SIZE)
771 goto out;
772
773 ret = -EFAULT;
774
775 if (copy_from_user(buf, buffer, count))
776 goto out;
777
778 buf[count] = '\0';
779
780 if (!kstrtoint(buf, 10, &enabled)) {
781 ret = 0;
782 memset(&eem_data, 0, sizeof(struct eem_ipi_data));
783 eem_data.u.data.arg[0] = det_to_id(det);
784 eem_data.u.data.arg[1] = enabled;
785 ipi_ret = eem_to_cpueb(IPI_EEMSN_DEBUG_PROC_WRITE, &eem_data);
786 det->disabled = enabled;
787
788 } else
789 ret = -EINVAL;
790
791out:
792 free_page((unsigned long)buf);
793
794 return (ret < 0) ? ret : count;
795}
796
797static int eem_aging_dump_proc_show(struct seq_file *m, void *v)
798{
799 struct eem_ipi_data eem_data;
800 int ipi_ret = 0;
801
802 memset(&eem_data, 0, sizeof(struct eem_ipi_data));
803 ipi_ret = eem_to_cpueb(IPI_EEMSN_AGING_DUMP_PROC_SHOW, &eem_data);
804 seq_printf(m, "ipi_ret:%d\n", ipi_ret);
805
806 return 0;
807}
808
809static int eem_dump_proc_show(struct seq_file *m, void *v)
810{
811 struct eem_ipi_data eem_data;
812 unsigned int ipi_ret = 0;
813
814 memset(&eem_data, 0, sizeof(struct eem_ipi_data));
815 ipi_ret = eem_to_cpueb(IPI_EEMSN_DUMP_PROC_SHOW, &eem_data);
816 seq_printf(m, "ipi_ret:%d\n", ipi_ret);
817
818 return 0;
819}
820
821static int eem_hrid_proc_show(struct seq_file *m, void *v)
822{
823 unsigned int i;
824 int devinfo = 0;
825
826 for (i = 0; i < 4; i++) {
827 nvmem_device_read(nvmem_dev, DEVINFO_HRID_0 + 0x4 * i, sizeof(__u32), &devinfo);
828 seq_printf(m, "%s[HRID][%d]: 0x%08X\n", EEM_TAG, i, devinfo);
829 }
830
831 return 0;
832}
833
834static int eem_efuse_proc_show(struct seq_file *m, void *v)
835{
836 unsigned int i;
837 int devinfo = 0;
838 for (i = 0; i < 25; i++) {
839 nvmem_device_read(nvmem_dev, DEVINFO_IDX_0 + 0x4 * i, sizeof(__u32), &devinfo);
840 seq_printf(m, "%s[PTP_DUMP] ORIG_RES%d: 0x%08X\n", EEM_TAG, i, devinfo);
841 }
842
843 return 0;
844}
845
846static int eem_mar_proc_show(struct seq_file *m, void *v)
847{
848 seq_printf(m, "%s[CPU_L][HIGH] 1:%d, 2:%d, 3:%d, 5:%d\n",
849 EEM_TAG, LOW_TEMP_OFF, 0,
850 HIGH_TEMP_OFF, AGING_VAL_CPU);
851
852 seq_printf(m, "%s[CPU_CCI][HIGH] 1:%d, 2:%d, 3:%d, 5:%d\n",
853 EEM_TAG, LOW_TEMP_OFF, 0,
854 HIGH_TEMP_OFF, AGING_VAL_CPU);
855
856 return 0;
857}
858
859static int eem_force_sensing_proc_show(struct seq_file *m, void *v)
860{
861 struct eem_ipi_data eem_data;
862 unsigned int ipi_ret = 0;
863
864 memset(&eem_data, 0, sizeof(struct eem_ipi_data));
865 ipi_ret = eem_to_cpueb(IPI_EEMSN_FORCE_SN_SENSING, &eem_data);
866 seq_printf(m, "ret:%d\n", ipi_ret);
867
868 return 0;
869}
870
871static int eem_pull_data_proc_show(struct seq_file *m, void *v)
872{
873 struct eem_ipi_data eem_data;
874 unsigned int ipi_ret = 0;
875
876 memset(&eem_data, 0, sizeof(struct eem_ipi_data));
877 ipi_ret = eem_to_cpueb(IPI_EEMSN_PULL_DATA, &eem_data);
878 seq_printf(m, "ret:%d\n", ipi_ret);
879
880 return 0;
881}
882
883/*
884 * show EEM offset
885 */
886static int eem_offset_proc_show(struct seq_file *m, void *v)
887{
888 struct eemsn_det *det = (struct eemsn_det *)m->private;
889
890 seq_printf(m, "%d\n", det->volt_offset);
891
892 return 0;
893}
894
895/*
896 * set EEM offset by procfs
897 */
898static ssize_t eem_offset_proc_write(struct file *file,
899 const char __user *buffer, size_t count, loff_t *pos)
900{
901 int ret;
902 char *buf = (char *) __get_free_page(GFP_USER);
903 int offset = 0;
904 struct eemsn_det *det = (struct eemsn_det *)PDE_DATA(file_inode(file));
905 unsigned int ipi_ret = 0;
906 struct eem_ipi_data eem_data;
907
908 if (!buf)
909 return -ENOMEM;
910
911 ret = -EINVAL;
912
913 if (count >= PAGE_SIZE)
914 goto out;
915
916 ret = -EFAULT;
917
918 if (copy_from_user(buf, buffer, count))
919 goto out;
920
921 buf[count] = '\0';
922
923 if (!kstrtoint(buf, 10, &offset)) {
924 ret = 0;
925 memset(&eem_data, 0, sizeof(struct eem_ipi_data));
926 eem_data.u.data.arg[0] = det_to_id(det);
927 eem_data.u.data.arg[1] = offset;
928 ipi_ret = eem_to_cpueb(IPI_EEMSN_OFFSET_PROC_WRITE, &eem_data);
929 /* to show in eem_offset_proc_show */
930 det->volt_offset = (signed char)offset;
931 pr_debug("set volt_offset %d(%d)\n", offset, det->volt_offset);
932 } else {
933 ret = -EINVAL;
934 pr_debug("bad argument_1!! argument should be \"0\"\n");
935 }
936
937out:
938 free_page((unsigned long)buf);
939
940 return (ret < 0) ? ret : count;
941}
942
943#if SUPPORT_PICACHU
944static void get_picachu_efuse(void)
945{
946 /* int *val; */
947 phys_addr_t picachu_mem_base_phys;
948 phys_addr_t picachu_mem_size;
949 phys_addr_t picachu_mem_base_virt = 0;
950 unsigned int sig;
951 void __iomem *addr_ptr;
952 void __iomem *spare1phys;
953
954 /* val = (int *)&eem_devinfo; */
955
956 picachu_mem_size = 0x80000;
957 spare1phys = ioremap(EEM_PHY_SPARE0, 0);
958 picachu_mem_base_phys = eem_read(spare1phys);
959 if ((void __iomem *)picachu_mem_base_phys != NULL)
960 picachu_mem_base_virt =
961 (phys_addr_t)(uintptr_t)ioremap_wc(
962 picachu_mem_base_phys,
963 picachu_mem_size);
964
965#if 0
966 eem_error("phys:0x%llx, size:0x%llx, virt:0x%llx\n",
967 (unsigned long long)picachu_mem_base_phys,
968 (unsigned long long)picachu_mem_size,
969 (unsigned long long)picachu_mem_base_virt);
970#endif
971 if ((void __iomem *)(picachu_mem_base_virt) != NULL) {
972 /* 0x60000 was reserved for eem efuse using */
973 addr_ptr = (void __iomem *)(picachu_mem_base_virt
974 + 0x60000);
975
976 /* check signature */
977 sig = (eem_read(addr_ptr) >>
978 PICACHU_SIGNATURE_SHIFT_BIT) & 0xff;
979
980 if (sig == PICACHU_SIG) {
981 ctrl_agingload_enable = eem_read(addr_ptr) & 0x1;
982 addr_ptr += 4;
983 memcpy(eemsn_log->vf_tbl_det,
984 addr_ptr, sizeof(eemsn_log->vf_tbl_det));
985
986#if 0
987 /* check efuse data */
988 for (i = 1; i < cnt; i++) {
989 if (((i == 3) || (i == 4) || (i == 7)) &&
990 (eem_read(addr_ptr + i * 4) == 0)) {
991 eem_error("Wrong PI-OD%d: 0x%x\n",
992 i, eem_read(addr_ptr + i * 4));
993 return;
994 }
995 }
996
997 for (i = 1; i < cnt; i++)
998 val[i] = eem_read(addr_ptr + i * 4);
999#endif
1000 }
1001 }
1002}
1003
1004#endif
1005
1006/*
1007 * All
1008 */
1009PROC_FOPS_RO(dbg_repo);
1010PROC_FOPS_RW(eem_debug);
1011PROC_FOPS_RW(eem_offset);
1012PROC_FOPS_RO(eem_dump);
1013PROC_FOPS_RO(eem_aging_dump);
1014PROC_FOPS_RO(eem_hrid);
1015PROC_FOPS_RO(eem_efuse);
1016PROC_FOPS_RO(eem_mar);
1017PROC_FOPS_RO(eem_force_sensing);
1018PROC_FOPS_RO(eem_pull_data);
1019
1020static int __init mtk_cpufreq_preinit(void)
1021{
1022 struct cdvfs_data eem_data;
1023 int err = 0;
1024 phys_addr_t eem_log_phy_addr, eem_log_virt_addr;
1025
1026 err = mtk_ipi_register(&mcupm_ipidev, CH_S_EEMSN, NULL, NULL,
1027 (void *) &ipi_ackdata);
1028 if (err != 0) {
1029 pr_info("%s error ret:%d\n", __func__, err);
1030 return 0;
1031 }
1032
1033 eem_log_phy_addr =
1034 mcupm_reserve_mem_get_phys(MCUPM_EEMSN_MEM_ID);
1035 eem_log_virt_addr =
1036 mcupm_reserve_mem_get_virt(MCUPM_EEMSN_MEM_ID);
1037
1038 if (eem_log_virt_addr != 0)
1039 eemsn_log = (struct eemsn_dbg_log *)eem_log_virt_addr;
1040 else
1041 pr_info("mcupm_reserve_mem_get_virt fail\n");
1042
1043 memset(&eem_data, 0, sizeof(struct cdvfs_data));
1044 eem_data.u.set_fv.arg[0] = eem_log_phy_addr;
1045 eem_data.u.set_fv.arg[1] = sizeof(struct eemsn_log);
1046
1047 /* eemsn_log->efuse_sv = eem_read(EEM_TEMPSPARE1); */
1048
1049#if SUPPORT_PICACHU
1050 get_picachu_efuse();
1051#endif
1052
1053#if defined(MC50_LOAD)
1054 /* force set freq table */
1055 memcpy(eemsn_log->vf_tbl_det,
1056 mc50_tbl, sizeof(eemsn_log->vf_tbl_det));
1057#endif
1058
1059 eem_data.cmd = IPI_EEMSN_SHARERAM_INIT;
1060
1061#if 0 /* TODO: wait mtk efsue ready */
1062 mtk_ipi_send_compl(&mcupm_ipidev, CH_S_EEMSN,
1063 /*IPI_SEND_WAIT*/IPI_SEND_POLLING, &eem_data,
1064 sizeof(struct cdvfs_data)/MBOX_SLOT_SIZE, 2000);
1065#endif
1066 return 0;
1067}
1068
1069static int create_cpufreq_debug_fs(void)
1070{
1071 int i;
1072 struct proc_dir_entry *dir = NULL;
1073 struct proc_dir_entry *eem_dir = NULL;
1074 struct proc_dir_entry *det_dir = NULL;
1075 struct eemsn_det *det;
1076
1077 struct pentry {
1078 const char *name;
1079 const struct file_operations *fops;
1080 void *data;
1081 };
1082
1083 struct pentry det_entries[] = {
1084 PROC_ENTRY(eem_debug),
1085 PROC_ENTRY(eem_offset),
1086 };
1087 struct pentry eem_entries[] = {
1088 PROC_ENTRY(eem_dump),
1089 PROC_ENTRY(eem_aging_dump),
1090 PROC_ENTRY(eem_hrid),
1091 PROC_ENTRY(eem_efuse),
1092 PROC_ENTRY(eem_mar),
1093 PROC_ENTRY(eem_force_sensing),
1094 PROC_ENTRY(eem_pull_data),
1095 };
1096
1097 dir = proc_mkdir("cpuhvfs", NULL);
1098 if (!dir)
1099 return -ENOMEM;
1100
1101 if (!proc_create_data("dbg_repo", 0664, dir, &dbg_repo_proc_fops, csram_base))
1102 return -EIO;
1103
1104 eem_dir = proc_mkdir("eem", NULL);
1105 for (i = 0; i < ARRAY_SIZE(eem_entries); i++)
1106 if(!proc_create(eem_entries[i].name, 0664, eem_dir, eem_entries[i].fops))
1107 return -3;
1108
1109 for_each_det(det) {
1110 if(det->features == 0)
1111 continue;
1112
1113 det_dir = proc_mkdir(det->name, eem_dir);
1114 if (!det_dir)
1115 return -2;
1116
1117 for(i = 0 ; i<ARRAY_SIZE(det_entries); i++)
1118 if(!proc_create_data(det_entries[i].name, 0644, det_dir, det_entries[i].fops, det))
1119 return -3;
1120 }
1121
1122 return 0;
1123}
1124
1125static int get_devinfo(struct platform_device *pdev)
1126{
1127#if 0 /* TODO: wait mtk efsue ready */
1128 int *val, ret = 1, i = 0, devinfo = 0;
1129
1130 val = (int *)&eemsn_log->efuse_devinfo;
1131
1132 nvmem_dev = nvmem_device_get(&pdev->dev, "mtk_efuse");
1133 if (IS_ERR(nvmem_dev))
1134 return PTR_ERR(nvmem_dev);
1135
1136 for (i = 0; i < 12; i++) {
1137 ret = nvmem_device_read(nvmem_dev, DEVINFO_IDX_0 + 0x4 * i, sizeof(__u32), &devinfo);
1138 if (ret != sizeof(__u32)) {
1139 ret = -EINVAL;
1140 goto release_nvmem;
1141 }
1142 val[i]= devinfo;
1143 }
1144
1145 ret = 1;
1146
1147release_nvmem:
1148 nvmem_device_put(nvmem_dev);
1149
1150 return ret;
1151#else
1152 return 1;
1153#endif
1154}
1155
1156static int mtk_cpufreq_probe(struct platform_device *pdev)
1157{
1158 struct mtk_cpu_dvfs_info *info;
1159 struct list_head *list, *tmp;
1160 int cpu, ret;
1161 struct cdvfs_data cdvfs_d;
1162 uint32_t cpufreq_buf[4];
1163
1164 ret = mtk_ipi_register(&mcupm_ipidev, CH_S_CPU_DVFS, NULL, NULL,
1165 (void *) &cpufreq_buf);
1166 if (ret)
1167 return -EINVAL;
1168
1169 cdvfs_d.cmd = IPI_DVFS_INIT;
1170 cdvfs_d.u.set_fv.arg[0] = 0;
1171 ret = mtk_ipi_send_compl(&mcupm_ipidev, CH_S_CPU_DVFS,
1172 IPI_SEND_POLLING, &cdvfs_d,
1173 sizeof(struct cdvfs_data)/MBOX_SLOT_SIZE,
1174 2000);
1175 if (ret)
1176 return 0;
1177
1178 mtk_cpufreq_preinit();
1179
1180 ret = get_devinfo(pdev);
1181 if(ret <= 0)
1182 return ret;
1183
1184 for_each_possible_cpu(cpu) {
1185 info = mtk_cpu_dvfs_info_lookup(cpu);
1186 if (info)
1187 continue;
1188
1189 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
1190 if (!info) {
1191 ret = -ENOMEM;
1192 goto release_dvfs_info_list;
1193 }
1194
1195 info->csram_base = of_iomap(pdev->dev.of_node, 0);
1196 if (!info->csram_base) {
1197 ret = -ENOMEM;
1198 goto release_dvfs_info_list;
1199 }
1200
1201 ret = mtk_cpu_dvfs_info_init(info, cpu);
1202 if (ret)
1203 goto release_dvfs_info_list;
1204
1205 list_add(&info->list_head, &dvfs_info_list);
1206 }
1207
1208 ret = cpufreq_register_driver(&mtk_cpufreq_driver);
1209 if (ret)
1210 goto release_dvfs_info_list;
1211
1212 csram_base = of_iomap(pdev->dev.of_node, 0);
1213 create_cpufreq_debug_fs();
1214
1215 return 0;
1216
1217release_dvfs_info_list:
1218 list_for_each_safe(list, tmp, &dvfs_info_list) {
1219 info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
1220 mtk_cpu_dvfs_info_release(info);
1221 list_del(list);
1222 }
1223
1224 return ret;
1225}
1226
1227static const struct of_device_id mtk_cpufreq_machines[] = {
1228 { .compatible = "mediatek,mcupm-dvfsp", },
1229 { }
1230};
1231
1232MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
1233
1234static struct platform_driver mtk_cpufreq_platdrv = {
1235 .probe = mtk_cpufreq_probe,
1236 .driver = {
1237 .name = "dvfsp",
1238 .of_match_table = of_match_ptr(mtk_cpufreq_machines),
1239 },
1240};
1241module_platform_driver(mtk_cpufreq_platdrv);
1242
1243MODULE_AUTHOR("Wei-Chia Su <Wei-Chia.Su@mediatek.com>");
1244MODULE_DESCRIPTION("Medaitek MCUPM CPUFreq Platform driver");
1245MODULE_LICENSE("GPL v2");