190 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2019, Linaro Limited4 */5 6#include <linux/bitops.h>7#include <linux/regmap.h>8#include <linux/delay.h>9#include <linux/slab.h>10#include "tsens.h"11 12/* ----- SROT ------ */13#define SROT_HW_VER_OFF 0x000014#define SROT_CTRL_OFF 0x000415 16/* ----- TM ------ */17#define TM_INT_EN_OFF 0x000018#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x000419#define TM_Sn_STATUS_OFF 0x004420#define TM_TRDY_OFF 0x008421#define TM_HIGH_LOW_INT_STATUS_OFF 0x008822#define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x009023 24static struct tsens_legacy_calibration_format tsens_qcs404_nvmem = {25 .base_len = 8,26 .base_shift = 2,27 .sp_len = 6,28 .mode = { 4, 0 },29 .invalid = { 4, 2 },30 .base = { { 4, 3 }, { 4, 11 } },31 .sp = {32 { { 0, 0 }, { 0, 6 } },33 { { 0, 12 }, { 0, 18 } },34 { { 0, 24 }, { 0, 30 } },35 { { 1, 4 }, { 1, 10 } },36 { { 1, 16 }, { 1, 22 } },37 { { 2, 0 }, { 2, 6 } },38 { { 2, 12 }, { 2, 18 } },39 { { 2, 24 }, { 2, 30 } },40 { { 3, 4 }, { 3, 10 } },41 { { 3, 16 }, { 3, 22 } },42 },43};44 45static int calibrate_v1(struct tsens_priv *priv)46{47 u32 p1[10], p2[10];48 u32 *qfprom_cdata;49 int mode, ret;50 51 ret = tsens_calibrate_common(priv);52 if (!ret)53 return 0;54 55 qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");56 if (IS_ERR(qfprom_cdata))57 return PTR_ERR(qfprom_cdata);58 59 mode = tsens_read_calibration_legacy(priv, &tsens_qcs404_nvmem,60 p1, p2,61 qfprom_cdata, NULL);62 63 compute_intercept_slope(priv, p1, p2, mode);64 kfree(qfprom_cdata);65 66 return 0;67}68 69/* v1.x: msm8956,8976,qcs404,405 */70 71static struct tsens_features tsens_v1_feat = {72 .ver_major = VER_1_X,73 .crit_int = 0,74 .combo_int = 0,75 .adc = 1,76 .srot_split = 1,77 .max_sensors = 11,78 .trip_min_temp = -40000,79 .trip_max_temp = 120000,80};81 82static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {83 /* ----- SROT ------ */84 /* VERSION */85 [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),86 [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),87 [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),88 /* CTRL_OFFSET */89 [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),90 [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),91 [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),92 93 /* ----- TM ------ */94 /* INTERRUPT ENABLE */95 [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),96 97 /* UPPER/LOWER TEMPERATURE THRESHOLDS */98 REG_FIELD_FOR_EACH_SENSOR11(LOW_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 0, 9),99 REG_FIELD_FOR_EACH_SENSOR11(UP_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19),100 101 /* UPPER/LOWER INTERRUPTS [CLEAR/STATUS] */102 REG_FIELD_FOR_EACH_SENSOR11(LOW_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 20, 20),103 REG_FIELD_FOR_EACH_SENSOR11(UP_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 21, 21),104 [LOW_INT_STATUS_0] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 0, 0),105 [LOW_INT_STATUS_1] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 1, 1),106 [LOW_INT_STATUS_2] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 2, 2),107 [LOW_INT_STATUS_3] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 3, 3),108 [LOW_INT_STATUS_4] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 4, 4),109 [LOW_INT_STATUS_5] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 5, 5),110 [LOW_INT_STATUS_6] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 6, 6),111 [LOW_INT_STATUS_7] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 7, 7),112 [UP_INT_STATUS_0] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 8, 8),113 [UP_INT_STATUS_1] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 9, 9),114 [UP_INT_STATUS_2] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 10, 10),115 [UP_INT_STATUS_3] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 11, 11),116 [UP_INT_STATUS_4] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 12, 12),117 [UP_INT_STATUS_5] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 13, 13),118 [UP_INT_STATUS_6] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 14, 14),119 [UP_INT_STATUS_7] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 15, 15),120 121 /* NO CRITICAL INTERRUPT SUPPORT on v1 */122 123 /* Sn_STATUS */124 REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9),125 REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14),126 /* xxx_STATUS bits: 1 == threshold violated */127 REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10),128 REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),129 REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),130 /* No CRITICAL field on v1.x */131 REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13),132 133 /* TRDY: 1=ready, 0=in progress */134 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),135};136 137static int __init init_8956(struct tsens_priv *priv) {138 priv->sensor[0].slope = 3313;139 priv->sensor[1].slope = 3275;140 priv->sensor[2].slope = 3320;141 priv->sensor[3].slope = 3246;142 priv->sensor[4].slope = 3279;143 priv->sensor[5].slope = 3257;144 priv->sensor[6].slope = 3234;145 priv->sensor[7].slope = 3269;146 priv->sensor[8].slope = 3255;147 priv->sensor[9].slope = 3239;148 priv->sensor[10].slope = 3286;149 150 return init_common(priv);151}152 153static const struct tsens_ops ops_generic_v1 = {154 .init = init_common,155 .calibrate = calibrate_v1,156 .get_temp = get_temp_tsens_valid,157};158 159struct tsens_plat_data data_tsens_v1 = {160 .ops = &ops_generic_v1,161 .feat = &tsens_v1_feat,162 .fields = tsens_v1_regfields,163};164 165static const struct tsens_ops ops_8956 = {166 .init = init_8956,167 .calibrate = tsens_calibrate_common,168 .get_temp = get_temp_tsens_valid,169};170 171struct tsens_plat_data data_8956 = {172 .num_sensors = 11,173 .ops = &ops_8956,174 .feat = &tsens_v1_feat,175 .fields = tsens_v1_regfields,176};177 178static const struct tsens_ops ops_8976 = {179 .init = init_common,180 .calibrate = tsens_calibrate_common,181 .get_temp = get_temp_tsens_valid,182};183 184struct tsens_plat_data data_8976 = {185 .num_sensors = 11,186 .ops = &ops_8976,187 .feat = &tsens_v1_feat,188 .fields = tsens_v1_regfields,189};190