1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
8 #include <linux/nvmem-consumer.h>
9 #include <linux/of_address.h>
10 #include <linux/of_platform.h>
11 #include <linux/platform_device.h>
12 #include <linux/regmap.h>
16 #define TSENS_EN BIT(0)
19 #define STATUS_OFFSET 0x30
20 #define SN_ADDR_OFFSET 0x4
21 #define SN_ST_TEMP_MASK 0x3ff
22 #define CAL_DEGC_PT1 30
23 #define CAL_DEGC_PT2 120
24 #define SLOPE_FACTOR 1000
25 #define SLOPE_DEFAULT 3200
27 char *qfprom_read(struct device
*dev
, const char *cname
)
29 struct nvmem_cell
*cell
;
33 cell
= nvmem_cell_get(dev
, cname
);
35 return ERR_CAST(cell
);
37 ret
= nvmem_cell_read(cell
, &data
);
44 * Use this function on devices where slope and offset calculations
45 * depend on calibration data read from qfprom. On others the slope
46 * and offset values are derived from tz->tzp->slope and tz->tzp->offset
49 void compute_intercept_slope(struct tsens_device
*tmdev
, u32
*p1
,
55 for (i
= 0; i
< tmdev
->num_sensors
; i
++) {
57 "sensor%d - data_point1:%#x data_point2:%#x\n",
60 tmdev
->sensor
[i
].slope
= SLOPE_DEFAULT
;
61 if (mode
== TWO_PT_CALIB
) {
63 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
64 * temp_120_degc - temp_30_degc (x2 - x1)
68 den
= CAL_DEGC_PT2
- CAL_DEGC_PT1
;
69 tmdev
->sensor
[i
].slope
= num
/ den
;
72 tmdev
->sensor
[i
].offset
= (p1
[i
] * SLOPE_FACTOR
) -
74 tmdev
->sensor
[i
].slope
);
75 dev_dbg(tmdev
->dev
, "offset:%d\n", tmdev
->sensor
[i
].offset
);
79 static inline int code_to_degc(u32 adc_code
, const struct tsens_sensor
*s
)
83 num
= (adc_code
* SLOPE_FACTOR
) - s
->offset
;
87 degc
= num
+ (den
/ 2);
89 degc
= num
- (den
/ 2);
98 int get_temp_common(struct tsens_device
*tmdev
, int id
, int *temp
)
100 struct tsens_sensor
*s
= &tmdev
->sensor
[id
];
102 unsigned int status_reg
;
103 int last_temp
= 0, ret
;
105 status_reg
= tmdev
->tm_offset
+ STATUS_OFFSET
+ s
->hw_id
* SN_ADDR_OFFSET
;
106 ret
= regmap_read(tmdev
->tm_map
, status_reg
, &code
);
109 last_temp
= code
& SN_ST_TEMP_MASK
;
111 *temp
= code_to_degc(last_temp
, s
) * 1000;
116 static const struct regmap_config tsens_config
= {
123 static const struct regmap_config tsens_srot_config
= {
130 int __init
init_common(struct tsens_device
*tmdev
)
132 void __iomem
*tm_base
, *srot_base
;
133 struct resource
*res
;
136 struct platform_device
*op
= of_find_device_by_node(tmdev
->dev
->of_node
);
137 u16 ctrl_offset
= tmdev
->reg_offsets
[SROT_CTRL_OFFSET
];
142 if (op
->num_resources
> 1) {
143 /* DT with separate SROT and TM address space */
144 tmdev
->tm_offset
= 0;
145 res
= platform_get_resource(op
, IORESOURCE_MEM
, 1);
146 srot_base
= devm_ioremap_resource(&op
->dev
, res
);
147 if (IS_ERR(srot_base
))
148 return PTR_ERR(srot_base
);
150 tmdev
->srot_map
= devm_regmap_init_mmio(tmdev
->dev
, srot_base
,
152 if (IS_ERR(tmdev
->srot_map
))
153 return PTR_ERR(tmdev
->srot_map
);
156 /* old DTs where SROT and TM were in a contiguous 2K block */
157 tmdev
->tm_offset
= 0x1000;
160 res
= platform_get_resource(op
, IORESOURCE_MEM
, 0);
161 tm_base
= devm_ioremap_resource(&op
->dev
, res
);
163 return PTR_ERR(tm_base
);
165 tmdev
->tm_map
= devm_regmap_init_mmio(tmdev
->dev
, tm_base
, &tsens_config
);
166 if (IS_ERR(tmdev
->tm_map
))
167 return PTR_ERR(tmdev
->tm_map
);
169 if (tmdev
->srot_map
) {
170 ret
= regmap_read(tmdev
->srot_map
, ctrl_offset
, &code
);
173 if (!(code
& TSENS_EN
)) {
174 dev_err(tmdev
->dev
, "tsens device is not enabled\n");