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