0001
0002
0003
0004
0005
0006 #include <linux/platform_device.h>
0007 #include <linux/delay.h>
0008 #include <linux/bitops.h>
0009 #include <linux/regmap.h>
0010 #include <linux/thermal.h>
0011 #include "tsens.h"
0012
0013 #define CONFIG_ADDR 0x3640
0014 #define CONFIG_ADDR_8660 0x3620
0015
0016 #define CONFIG 0x9b
0017 #define CONFIG_MASK 0xf
0018 #define CONFIG_8660 1
0019 #define CONFIG_SHIFT_8660 28
0020 #define CONFIG_MASK_8660 (3 << CONFIG_SHIFT_8660)
0021
0022 #define CNTL_ADDR 0x3620
0023
0024 #define EN BIT(0)
0025 #define SW_RST BIT(1)
0026
0027 #define MEASURE_PERIOD BIT(18)
0028 #define SLP_CLK_ENA BIT(26)
0029 #define SLP_CLK_ENA_8660 BIT(24)
0030 #define SENSOR0_SHIFT 3
0031
0032 #define THRESHOLD_ADDR 0x3624
0033
0034 #define INT_STATUS_ADDR 0x363c
0035
0036 #define S0_STATUS_OFF 0x3628
0037 #define S1_STATUS_OFF 0x362c
0038 #define S2_STATUS_OFF 0x3630
0039 #define S3_STATUS_OFF 0x3634
0040 #define S4_STATUS_OFF 0x3638
0041 #define S5_STATUS_OFF 0x3664
0042 #define S6_STATUS_OFF 0x3668
0043 #define S7_STATUS_OFF 0x366c
0044 #define S8_STATUS_OFF 0x3670
0045 #define S9_STATUS_OFF 0x3674
0046 #define S10_STATUS_OFF 0x3678
0047
0048
0049 static u32 tsens_msm8960_slope[] = {
0050 826, 826, 804, 826,
0051 761, 782, 782, 849,
0052 782, 849, 782
0053 };
0054
0055 static int suspend_8960(struct tsens_priv *priv)
0056 {
0057 int ret;
0058 unsigned int mask;
0059 struct regmap *map = priv->tm_map;
0060
0061 ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
0062 if (ret)
0063 return ret;
0064
0065 ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
0066 if (ret)
0067 return ret;
0068
0069 if (priv->num_sensors > 1)
0070 mask = SLP_CLK_ENA | EN;
0071 else
0072 mask = SLP_CLK_ENA_8660 | EN;
0073
0074 ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
0075 if (ret)
0076 return ret;
0077
0078 return 0;
0079 }
0080
0081 static int resume_8960(struct tsens_priv *priv)
0082 {
0083 int ret;
0084 struct regmap *map = priv->tm_map;
0085
0086 ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
0087 if (ret)
0088 return ret;
0089
0090
0091
0092
0093
0094 if (priv->num_sensors > 1) {
0095 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
0096 if (ret)
0097 return ret;
0098 }
0099
0100 ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
0101 if (ret)
0102 return ret;
0103
0104 ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
0105 if (ret)
0106 return ret;
0107
0108 return 0;
0109 }
0110
0111 static int enable_8960(struct tsens_priv *priv, int id)
0112 {
0113 int ret;
0114 u32 reg, mask = BIT(id);
0115
0116 ret = regmap_read(priv->tm_map, CNTL_ADDR, ®);
0117 if (ret)
0118 return ret;
0119
0120
0121
0122
0123
0124
0125
0126
0127 if (id > 5)
0128 mask = GENMASK(10, 6);
0129
0130 mask <<= SENSOR0_SHIFT;
0131
0132
0133 if ((reg & mask) == mask)
0134 return 0;
0135
0136 ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
0137 if (ret)
0138 return ret;
0139
0140 reg |= MEASURE_PERIOD;
0141
0142 if (priv->num_sensors > 1)
0143 reg |= mask | SLP_CLK_ENA | EN;
0144 else
0145 reg |= mask | SLP_CLK_ENA_8660 | EN;
0146
0147 ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
0148 if (ret)
0149 return ret;
0150
0151 return 0;
0152 }
0153
0154 static void disable_8960(struct tsens_priv *priv)
0155 {
0156 int ret;
0157 u32 reg_cntl;
0158 u32 mask;
0159
0160 mask = GENMASK(priv->num_sensors - 1, 0);
0161 mask <<= SENSOR0_SHIFT;
0162 mask |= EN;
0163
0164 ret = regmap_read(priv->tm_map, CNTL_ADDR, ®_cntl);
0165 if (ret)
0166 return;
0167
0168 reg_cntl &= ~mask;
0169
0170 if (priv->num_sensors > 1)
0171 reg_cntl &= ~SLP_CLK_ENA;
0172 else
0173 reg_cntl &= ~SLP_CLK_ENA_8660;
0174
0175 regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
0176 }
0177
0178 static int calibrate_8960(struct tsens_priv *priv)
0179 {
0180 int i;
0181 char *data;
0182 u32 p1[11];
0183
0184 data = qfprom_read(priv->dev, "calib");
0185 if (IS_ERR(data))
0186 data = qfprom_read(priv->dev, "calib_backup");
0187 if (IS_ERR(data))
0188 return PTR_ERR(data);
0189
0190 for (i = 0; i < priv->num_sensors; i++) {
0191 p1[i] = data[i];
0192 priv->sensor[i].slope = tsens_msm8960_slope[i];
0193 }
0194
0195 compute_intercept_slope(priv, p1, NULL, ONE_PT_CALIB);
0196
0197 kfree(data);
0198
0199 return 0;
0200 }
0201
0202 static const struct reg_field tsens_8960_regfields[MAX_REGFIELDS] = {
0203
0204
0205
0206
0207 [TSENS_EN] = REG_FIELD(CNTL_ADDR, 0, 0),
0208 [TSENS_SW_RST] = REG_FIELD(CNTL_ADDR, 1, 1),
0209
0210 [SENSOR_EN] = REG_FIELD(CNTL_ADDR, 3, 7),
0211
0212
0213
0214
0215
0216
0217 [LOW_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 0, 7),
0218 [UP_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 8, 15),
0219
0220
0221
0222
0223
0224 [CRIT_THRESH_1] = REG_FIELD(THRESHOLD_ADDR, 16, 23),
0225 [CRIT_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 24, 31),
0226
0227
0228
0229 [LOW_INT_CLEAR_0] = REG_FIELD(CNTL_ADDR, 9, 9),
0230 [UP_INT_CLEAR_0] = REG_FIELD(CNTL_ADDR, 10, 10),
0231
0232
0233
0234
0235 [LAST_TEMP_0] = REG_FIELD(S0_STATUS_OFF, 0, 7),
0236 [LAST_TEMP_1] = REG_FIELD(S1_STATUS_OFF, 0, 7),
0237 [LAST_TEMP_2] = REG_FIELD(S2_STATUS_OFF, 0, 7),
0238 [LAST_TEMP_3] = REG_FIELD(S3_STATUS_OFF, 0, 7),
0239 [LAST_TEMP_4] = REG_FIELD(S4_STATUS_OFF, 0, 7),
0240 [LAST_TEMP_5] = REG_FIELD(S5_STATUS_OFF, 0, 7),
0241 [LAST_TEMP_6] = REG_FIELD(S6_STATUS_OFF, 0, 7),
0242 [LAST_TEMP_7] = REG_FIELD(S7_STATUS_OFF, 0, 7),
0243 [LAST_TEMP_8] = REG_FIELD(S8_STATUS_OFF, 0, 7),
0244 [LAST_TEMP_9] = REG_FIELD(S9_STATUS_OFF, 0, 7),
0245 [LAST_TEMP_10] = REG_FIELD(S10_STATUS_OFF, 0, 7),
0246
0247
0248
0249 [MIN_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 0, 0),
0250 [LOWER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 1, 1),
0251 [UPPER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 2, 2),
0252
0253 [MAX_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 3, 3),
0254
0255
0256 [TRDY] = REG_FIELD(INT_STATUS_ADDR, 7, 7),
0257 };
0258
0259 static const struct tsens_ops ops_8960 = {
0260 .init = init_common,
0261 .calibrate = calibrate_8960,
0262 .get_temp = get_temp_common,
0263 .enable = enable_8960,
0264 .disable = disable_8960,
0265 .suspend = suspend_8960,
0266 .resume = resume_8960,
0267 };
0268
0269 static struct tsens_features tsens_8960_feat = {
0270 .ver_major = VER_0,
0271 .crit_int = 0,
0272 .adc = 1,
0273 .srot_split = 0,
0274 .max_sensors = 11,
0275 };
0276
0277 struct tsens_plat_data data_8960 = {
0278 .num_sensors = 11,
0279 .ops = &ops_8960,
0280 .feat = &tsens_8960_feat,
0281 .fields = tsens_8960_regfields,
0282 };