162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2019, Linaro Limited 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/bitops.h> 762306a36Sopenharmony_ci#include <linux/regmap.h> 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include "tsens.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* ----- SROT ------ */ 1362306a36Sopenharmony_ci#define SROT_HW_VER_OFF 0x0000 1462306a36Sopenharmony_ci#define SROT_CTRL_OFF 0x0004 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* ----- TM ------ */ 1762306a36Sopenharmony_ci#define TM_INT_EN_OFF 0x0000 1862306a36Sopenharmony_ci#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 1962306a36Sopenharmony_ci#define TM_Sn_STATUS_OFF 0x0044 2062306a36Sopenharmony_ci#define TM_TRDY_OFF 0x0084 2162306a36Sopenharmony_ci#define TM_HIGH_LOW_INT_STATUS_OFF 0x0088 2262306a36Sopenharmony_ci#define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { 2562306a36Sopenharmony_ci .base_len = 8, 2662306a36Sopenharmony_ci .base_shift = 2, 2762306a36Sopenharmony_ci .sp_len = 6, 2862306a36Sopenharmony_ci .mode = { 4, 0 }, 2962306a36Sopenharmony_ci .invalid = { 4, 2 }, 3062306a36Sopenharmony_ci .base = { { 4, 3 }, { 4, 11 } }, 3162306a36Sopenharmony_ci .sp = { 3262306a36Sopenharmony_ci { { 0, 0 }, { 0, 6 } }, 3362306a36Sopenharmony_ci { { 0, 12 }, { 0, 18 } }, 3462306a36Sopenharmony_ci { { 0, 24 }, { 0, 30 } }, 3562306a36Sopenharmony_ci { { 1, 4 }, { 1, 10 } }, 3662306a36Sopenharmony_ci { { 1, 16 }, { 1, 22 } }, 3762306a36Sopenharmony_ci { { 2, 0 }, { 2, 6 } }, 3862306a36Sopenharmony_ci { { 2, 12 }, { 2, 18 } }, 3962306a36Sopenharmony_ci { { 2, 24 }, { 2, 30 } }, 4062306a36Sopenharmony_ci { { 3, 4 }, { 3, 10 } }, 4162306a36Sopenharmony_ci { { 3, 16 }, { 3, 22 } }, 4262306a36Sopenharmony_ci }, 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic int calibrate_v1(struct tsens_priv *priv) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci u32 p1[10], p2[10]; 4862306a36Sopenharmony_ci u32 *qfprom_cdata; 4962306a36Sopenharmony_ci int mode, ret; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci ret = tsens_calibrate_common(priv); 5262306a36Sopenharmony_ci if (!ret) 5362306a36Sopenharmony_ci return 0; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 5662306a36Sopenharmony_ci if (IS_ERR(qfprom_cdata)) 5762306a36Sopenharmony_ci return PTR_ERR(qfprom_cdata); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci mode = tsens_read_calibration_legacy(priv, &tsens_qcs404_nvmem, 6062306a36Sopenharmony_ci p1, p2, 6162306a36Sopenharmony_ci qfprom_cdata, NULL); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci compute_intercept_slope(priv, p1, p2, mode); 6462306a36Sopenharmony_ci kfree(qfprom_cdata); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return 0; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* v1.x: msm8956,8976,qcs404,405 */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic struct tsens_features tsens_v1_feat = { 7262306a36Sopenharmony_ci .ver_major = VER_1_X, 7362306a36Sopenharmony_ci .crit_int = 0, 7462306a36Sopenharmony_ci .combo_int = 0, 7562306a36Sopenharmony_ci .adc = 1, 7662306a36Sopenharmony_ci .srot_split = 1, 7762306a36Sopenharmony_ci .max_sensors = 11, 7862306a36Sopenharmony_ci .trip_min_temp = -40000, 7962306a36Sopenharmony_ci .trip_max_temp = 120000, 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { 8362306a36Sopenharmony_ci /* ----- SROT ------ */ 8462306a36Sopenharmony_ci /* VERSION */ 8562306a36Sopenharmony_ci [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31), 8662306a36Sopenharmony_ci [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27), 8762306a36Sopenharmony_ci [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15), 8862306a36Sopenharmony_ci /* CTRL_OFFSET */ 8962306a36Sopenharmony_ci [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), 9062306a36Sopenharmony_ci [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), 9162306a36Sopenharmony_ci [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13), 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* ----- TM ------ */ 9462306a36Sopenharmony_ci /* INTERRUPT ENABLE */ 9562306a36Sopenharmony_ci [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* UPPER/LOWER TEMPERATURE THRESHOLDS */ 9862306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(LOW_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 0, 9), 9962306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(UP_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19), 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* UPPER/LOWER INTERRUPTS [CLEAR/STATUS] */ 10262306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(LOW_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 20, 20), 10362306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(UP_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 21, 21), 10462306a36Sopenharmony_ci [LOW_INT_STATUS_0] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 0, 0), 10562306a36Sopenharmony_ci [LOW_INT_STATUS_1] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 1, 1), 10662306a36Sopenharmony_ci [LOW_INT_STATUS_2] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 2, 2), 10762306a36Sopenharmony_ci [LOW_INT_STATUS_3] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 3, 3), 10862306a36Sopenharmony_ci [LOW_INT_STATUS_4] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 4, 4), 10962306a36Sopenharmony_ci [LOW_INT_STATUS_5] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 5, 5), 11062306a36Sopenharmony_ci [LOW_INT_STATUS_6] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 6, 6), 11162306a36Sopenharmony_ci [LOW_INT_STATUS_7] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 7, 7), 11262306a36Sopenharmony_ci [UP_INT_STATUS_0] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 8, 8), 11362306a36Sopenharmony_ci [UP_INT_STATUS_1] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 9, 9), 11462306a36Sopenharmony_ci [UP_INT_STATUS_2] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 10, 10), 11562306a36Sopenharmony_ci [UP_INT_STATUS_3] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 11, 11), 11662306a36Sopenharmony_ci [UP_INT_STATUS_4] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 12, 12), 11762306a36Sopenharmony_ci [UP_INT_STATUS_5] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 13, 13), 11862306a36Sopenharmony_ci [UP_INT_STATUS_6] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 14, 14), 11962306a36Sopenharmony_ci [UP_INT_STATUS_7] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 15, 15), 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* NO CRITICAL INTERRUPT SUPPORT on v1 */ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* Sn_STATUS */ 12462306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), 12562306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14), 12662306a36Sopenharmony_ci /* xxx_STATUS bits: 1 == threshold violated */ 12762306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), 12862306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), 12962306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), 13062306a36Sopenharmony_ci /* No CRITICAL field on v1.x */ 13162306a36Sopenharmony_ci REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13), 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* TRDY: 1=ready, 0=in progress */ 13462306a36Sopenharmony_ci [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic int __init init_8956(struct tsens_priv *priv) { 13862306a36Sopenharmony_ci priv->sensor[0].slope = 3313; 13962306a36Sopenharmony_ci priv->sensor[1].slope = 3275; 14062306a36Sopenharmony_ci priv->sensor[2].slope = 3320; 14162306a36Sopenharmony_ci priv->sensor[3].slope = 3246; 14262306a36Sopenharmony_ci priv->sensor[4].slope = 3279; 14362306a36Sopenharmony_ci priv->sensor[5].slope = 3257; 14462306a36Sopenharmony_ci priv->sensor[6].slope = 3234; 14562306a36Sopenharmony_ci priv->sensor[7].slope = 3269; 14662306a36Sopenharmony_ci priv->sensor[8].slope = 3255; 14762306a36Sopenharmony_ci priv->sensor[9].slope = 3239; 14862306a36Sopenharmony_ci priv->sensor[10].slope = 3286; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return init_common(priv); 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic const struct tsens_ops ops_generic_v1 = { 15462306a36Sopenharmony_ci .init = init_common, 15562306a36Sopenharmony_ci .calibrate = calibrate_v1, 15662306a36Sopenharmony_ci .get_temp = get_temp_tsens_valid, 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistruct tsens_plat_data data_tsens_v1 = { 16062306a36Sopenharmony_ci .ops = &ops_generic_v1, 16162306a36Sopenharmony_ci .feat = &tsens_v1_feat, 16262306a36Sopenharmony_ci .fields = tsens_v1_regfields, 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic const struct tsens_ops ops_8956 = { 16662306a36Sopenharmony_ci .init = init_8956, 16762306a36Sopenharmony_ci .calibrate = tsens_calibrate_common, 16862306a36Sopenharmony_ci .get_temp = get_temp_tsens_valid, 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistruct tsens_plat_data data_8956 = { 17262306a36Sopenharmony_ci .num_sensors = 11, 17362306a36Sopenharmony_ci .ops = &ops_8956, 17462306a36Sopenharmony_ci .feat = &tsens_v1_feat, 17562306a36Sopenharmony_ci .fields = tsens_v1_regfields, 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic const struct tsens_ops ops_8976 = { 17962306a36Sopenharmony_ci .init = init_common, 18062306a36Sopenharmony_ci .calibrate = tsens_calibrate_common, 18162306a36Sopenharmony_ci .get_temp = get_temp_tsens_valid, 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistruct tsens_plat_data data_8976 = { 18562306a36Sopenharmony_ci .num_sensors = 11, 18662306a36Sopenharmony_ci .ops = &ops_8976, 18762306a36Sopenharmony_ci .feat = &tsens_v1_feat, 18862306a36Sopenharmony_ci .fields = tsens_v1_regfields, 18962306a36Sopenharmony_ci}; 190