sctp: walk the list of asoc safely
[linux/fpc-iii.git] / drivers / thermal / qcom / tsens-common.c
blob6207d8d923513a377e0ebcbf19279b1c8e249876
1 /*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include <linux/err.h>
16 #include <linux/io.h>
17 #include <linux/nvmem-consumer.h>
18 #include <linux/of_address.h>
19 #include <linux/of_platform.h>
20 #include <linux/platform_device.h>
21 #include <linux/regmap.h>
22 #include "tsens.h"
24 #define S0_ST_ADDR 0x1030
25 #define SN_ADDR_OFFSET 0x4
26 #define SN_ST_TEMP_MASK 0x3ff
27 #define CAL_DEGC_PT1 30
28 #define CAL_DEGC_PT2 120
29 #define SLOPE_FACTOR 1000
30 #define SLOPE_DEFAULT 3200
32 char *qfprom_read(struct device *dev, const char *cname)
34 struct nvmem_cell *cell;
35 ssize_t data;
36 char *ret;
38 cell = nvmem_cell_get(dev, cname);
39 if (IS_ERR(cell))
40 return ERR_CAST(cell);
42 ret = nvmem_cell_read(cell, &data);
43 nvmem_cell_put(cell);
45 return ret;
49 * Use this function on devices where slope and offset calculations
50 * depend on calibration data read from qfprom. On others the slope
51 * and offset values are derived from tz->tzp->slope and tz->tzp->offset
52 * resp.
54 void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
55 u32 *p2, u32 mode)
57 int i;
58 int num, den;
60 for (i = 0; i < tmdev->num_sensors; i++) {
61 dev_dbg(tmdev->dev,
62 "sensor%d - data_point1:%#x data_point2:%#x\n",
63 i, p1[i], p2[i]);
65 tmdev->sensor[i].slope = SLOPE_DEFAULT;
66 if (mode == TWO_PT_CALIB) {
68 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
69 * temp_120_degc - temp_30_degc (x2 - x1)
71 num = p2[i] - p1[i];
72 num *= SLOPE_FACTOR;
73 den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
74 tmdev->sensor[i].slope = num / den;
77 tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
78 (CAL_DEGC_PT1 *
79 tmdev->sensor[i].slope);
80 dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
84 static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
86 int degc, num, den;
88 num = (adc_code * SLOPE_FACTOR) - s->offset;
89 den = s->slope;
91 if (num > 0)
92 degc = num + (den / 2);
93 else if (num < 0)
94 degc = num - (den / 2);
95 else
96 degc = num;
98 degc /= den;
100 return degc;
103 int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
105 struct tsens_sensor *s = &tmdev->sensor[id];
106 u32 code;
107 unsigned int status_reg;
108 int last_temp = 0, ret;
110 status_reg = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET;
111 ret = regmap_read(tmdev->map, status_reg, &code);
112 if (ret)
113 return ret;
114 last_temp = code & SN_ST_TEMP_MASK;
116 *temp = code_to_degc(last_temp, s) * 1000;
118 return 0;
121 static const struct regmap_config tsens_config = {
122 .reg_bits = 32,
123 .val_bits = 32,
124 .reg_stride = 4,
127 int __init init_common(struct tsens_device *tmdev)
129 void __iomem *base;
130 struct resource *res;
131 struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node);
133 if (!op)
134 return -EINVAL;
136 /* The driver only uses the TM register address space for now */
137 if (op->num_resources > 1) {
138 tmdev->tm_offset = 0;
139 } else {
140 /* old DTs where SROT and TM were in a contiguous 2K block */
141 tmdev->tm_offset = 0x1000;
144 res = platform_get_resource(op, IORESOURCE_MEM, 0);
145 base = devm_ioremap_resource(&op->dev, res);
146 if (IS_ERR(base))
147 return PTR_ERR(base);
149 tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config);
150 if (IS_ERR(tmdev->map))
151 return PTR_ERR(tmdev->map);
153 return 0;