1 #include <stdint.h>
2 #include <stdio.h>
3
4 #include <hal_cmd.h>
5 #include <hal_timer.h>
6 #include <sunxi_hal_thermal.h>
7 #include <sunxi_hal_common.h>
8 #include <hal_log.h>
9
10 #if 0
11 #define THS_DBG(fmt,arg...) printf("THS:" fmt, ##arg)
12 #else
13 #define THS_DBG(fmt,arg...) do{}while(0)
14 #endif
15
16 extern int hal_efuse_get_thermal_cdata(unsigned char *buffer);
17
18 /* Temp Unit: millidegree Celsius */
hal_ths_reg2temp(int reg)19 static int hal_ths_reg2temp(int reg)
20 {
21 THS_DBG("OFFSET:%d[0x%x], SCALE:%d[0x%x], reg:%d[0x%x]\n", OFFSET, OFFSET, SCALE, SCALE, reg, reg);
22
23 return (reg + OFFSET) * SCALE;
24 }
25
hal_ths_calibrate(short int * buf,unsigned int len)26 static void hal_ths_calibrate(short int *buf, unsigned int len)
27 {
28 unsigned int i;
29 int ft_temp;
30
31 if (!buf[0] || len < 2 + 2 * THS_NUM)
32 return;
33
34 ft_temp = buf[0] & FT_TEMP_MASK;
35
36 for (i = 0; i < THS_NUM; i++) {
37 int reg = (int)buf[i + 1];
38 int sensor_temp = hal_ths_reg2temp(reg);
39 int delta, cdata, calib_offest;
40
41 /*
42 * To calculate the calibration value:
43 *
44 * X(in Celsius) = Ts - ft_temp
45 * delta = X * 10000 / TEMP_TO_REG
46 * cdata = CALIBRATE_DEFAULT - delta
47 *
48 * cdata: calibration value
49 */
50 delta = (sensor_temp - ft_temp * 100) * 10 / TEMP_TO_REG;
51 cdata = CALIBRATE_DEFAULT - delta;
52
53 THS_DBG("sensor_temp:%d[0x%x], ft_temp:%d[0x%x], TEMP_TO_REG:%d[0x%x],"
54 "delta:%d[0x%x], CALIBRATE_DEFAULT:%d[0x%x], cdata:%d[0x%x]\n",
55 sensor_temp, sensor_temp, ft_temp, ft_temp, TEMP_TO_REG, TEMP_TO_REG,
56 delta, delta, CALIBRATE_DEFAULT, CALIBRATE_DEFAULT, cdata, cdata);
57
58 if (cdata & ~TEMP_CALIB_MASK) {
59 /*
60 * Calibration value more than 12-bit, but calibration
61 * register is 12-bit. In this case, ths hardware can
62 * still work without calibration, although the data
63 * won't be so accurate.
64 */
65 continue;
66 }
67
68 calib_offest = THS_CALIB + (i / 2) * 0x4;
69
70 THS_DBG("calib_offest:%d[0x%x], THS_CALIB:%d[0x%x]\n", calib_offest, calib_offest, THS_CALIB, THS_CALIB);
71
72 if (i % 2) {
73 hal_writel((hal_readl((unsigned long)THS_CALIB) & TEMP_CALIB_MASK) | (cdata << 16), (unsigned long)calib_offest);
74 } else {
75 hal_writel(cdata, (unsigned long)calib_offest);
76 }
77 }
78 }
79
80
hal_ths_init(void)81 int hal_ths_init(void)
82 {
83 int ret = 0;
84 char buffer[8] = {0};
85
86 //TODO: clk init
87 hal_writel(0x10001, (unsigned long)0x020019fc);
88
89 /*
90 * clkin = 24MHz
91 * T acquire = clkin / (x + 1)
92 * = 20us
93 */
94 hal_log_err("0x%x, 0x%x, 0x%x, 0x%x", THS_EN, THS_CTL, THS_MFC, THS_PCTL);
95 hal_writel(THS_CTRL_T_ACQ(479), (unsigned long)THS_CTL);
96 /* average over 4 samples */
97 hal_writel(THS_FILTER_EN | THS_FILTER_TYPE(1), (unsigned long)THS_MFC);
98 /* period = (x + 1) * 4096 / clkin; ~10ms */
99 hal_writel(THS_PC_TEMP_PERIOD(58), (unsigned long)THS_PCTL);
100 /* enable sensor */
101 hal_writel(THS_NUM, (unsigned long)THS_EN);
102
103 ret = hal_efuse_get_thermal_cdata(buffer);
104 if (ret < 0) {
105 printf("get thermal calibration data failed.\n");
106 return ret;
107 }
108
109 hal_ths_calibrate((short int *)buffer, 8);
110 return ret ;
111
112 }
113
hal_ths_uninit(void)114 int hal_ths_uninit(void)
115 {
116 hal_writel(0x0, (unsigned long)0x020019fc);
117
118 return 0;
119 }
120
hal_ths_get_temp(unsigned int num,int * temp)121 int hal_ths_get_temp(unsigned int num, int *temp)
122 {
123 uint32_t val;
124
125 val = hal_readl((unsigned long)THS_DATA + 0x4 * num);
126 THS_DBG("num:%d[0x%x], val:%d[0x%x]\n", num, num, val, val);
127
128 /* ths have no data yet */
129 if (!val)
130 return -1;
131
132 *temp = hal_ths_reg2temp(val);
133
134 return 0;
135 }
136
137
138