Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2019, Linaro Limited
  4 */
  5
  6#include <linux/bitops.h>
  7#include <linux/regmap.h>
  8#include <linux/delay.h>
  9#include "tsens.h"
 10
 11/* ----- SROT ------ */
 12#define SROT_HW_VER_OFF	0x0000
 13#define SROT_CTRL_OFF		0x0004
 14
 15/* ----- TM ------ */
 16#define TM_INT_EN_OFF				0x0000
 17#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF	0x0004
 18#define TM_Sn_STATUS_OFF			0x0044
 19#define TM_TRDY_OFF				0x0084
 20
 21/* eeprom layout data for qcs404/405 (v1) */
 22#define BASE0_MASK	0x000007f8
 23#define BASE1_MASK	0x0007f800
 24#define BASE0_SHIFT	3
 25#define BASE1_SHIFT	11
 26
 27#define S0_P1_MASK	0x0000003f
 28#define S1_P1_MASK	0x0003f000
 29#define S2_P1_MASK	0x3f000000
 30#define S3_P1_MASK	0x000003f0
 31#define S4_P1_MASK	0x003f0000
 32#define S5_P1_MASK	0x0000003f
 33#define S6_P1_MASK	0x0003f000
 34#define S7_P1_MASK	0x3f000000
 35#define S8_P1_MASK	0x000003f0
 36#define S9_P1_MASK	0x003f0000
 37
 38#define S0_P2_MASK	0x00000fc0
 39#define S1_P2_MASK	0x00fc0000
 40#define S2_P2_MASK_1_0	0xc0000000
 41#define S2_P2_MASK_5_2	0x0000000f
 42#define S3_P2_MASK	0x0000fc00
 43#define S4_P2_MASK	0x0fc00000
 44#define S5_P2_MASK	0x00000fc0
 45#define S6_P2_MASK	0x00fc0000
 46#define S7_P2_MASK_1_0	0xc0000000
 47#define S7_P2_MASK_5_2	0x0000000f
 48#define S8_P2_MASK	0x0000fc00
 49#define S9_P2_MASK	0x0fc00000
 50
 51#define S0_P1_SHIFT	0
 52#define S0_P2_SHIFT	6
 53#define S1_P1_SHIFT	12
 54#define S1_P2_SHIFT	18
 55#define S2_P1_SHIFT	24
 56#define S2_P2_SHIFT_1_0	30
 57
 58#define S2_P2_SHIFT_5_2	0
 59#define S3_P1_SHIFT	4
 60#define S3_P2_SHIFT	10
 61#define S4_P1_SHIFT	16
 62#define S4_P2_SHIFT	22
 63
 64#define S5_P1_SHIFT	0
 65#define S5_P2_SHIFT	6
 66#define S6_P1_SHIFT	12
 67#define S6_P2_SHIFT	18
 68#define S7_P1_SHIFT	24
 69#define S7_P2_SHIFT_1_0	30
 70
 71#define S7_P2_SHIFT_5_2	0
 72#define S8_P1_SHIFT	4
 73#define S8_P2_SHIFT	10
 74#define S9_P1_SHIFT	16
 75#define S9_P2_SHIFT	22
 76
 77#define CAL_SEL_MASK	7
 78#define CAL_SEL_SHIFT	0
 79
 80static int calibrate_v1(struct tsens_priv *priv)
 81{
 82	u32 base0 = 0, base1 = 0;
 83	u32 p1[10], p2[10];
 84	u32 mode = 0, lsb = 0, msb = 0;
 85	u32 *qfprom_cdata;
 86	int i;
 87
 88	qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
 89	if (IS_ERR(qfprom_cdata))
 90		return PTR_ERR(qfprom_cdata);
 91
 92	mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
 93	dev_dbg(priv->dev, "calibration mode is %d\n", mode);
 94
 95	switch (mode) {
 96	case TWO_PT_CALIB:
 97		base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
 98		p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
 99		p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
100		/* This value is split over two registers, 2 bits and 4 bits */
101		lsb   = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
102		msb   = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
103		p2[2] = msb << 2 | lsb;
104		p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
105		p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
106		p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
107		p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
108		/* This value is split over two registers, 2 bits and 4 bits */
109		lsb   = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
110		msb   = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
111		p2[7] = msb << 2 | lsb;
112		p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
113		p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
114		for (i = 0; i < priv->num_sensors; i++)
115			p2[i] = ((base1 + p2[i]) << 2);
116		/* Fall through */
117	case ONE_PT_CALIB2:
118		base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
119		p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
120		p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
121		p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
122		p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
123		p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
124		p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
125		p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
126		p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
127		p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
128		p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
129		for (i = 0; i < priv->num_sensors; i++)
130			p1[i] = (((base0) + p1[i]) << 2);
131		break;
132	default:
133		for (i = 0; i < priv->num_sensors; i++) {
134			p1[i] = 500;
135			p2[i] = 780;
136		}
137		break;
138	}
139
140	compute_intercept_slope(priv, p1, p2, mode);
141	kfree(qfprom_cdata);
142
143	return 0;
144}
145
146/* v1.x: qcs404,405 */
147
148static const struct tsens_features tsens_v1_feat = {
149	.ver_major	= VER_1_X,
150	.crit_int	= 0,
151	.adc		= 1,
152	.srot_split	= 1,
153	.max_sensors	= 11,
154};
155
156static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
157	/* ----- SROT ------ */
158	/* VERSION */
159	[VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
160	[VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
161	[VER_STEP]  = REG_FIELD(SROT_HW_VER_OFF,  0, 15),
162	/* CTRL_OFFSET */
163	[TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF, 0,  0),
164	[TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1,  1),
165	[SENSOR_EN]    = REG_FIELD(SROT_CTRL_OFF, 3, 13),
166
167	/* ----- TM ------ */
168	/* INTERRUPT ENABLE */
169	[INT_EN]     = REG_FIELD(TM_INT_EN_OFF, 0, 0),
170
171	/* Sn_STATUS */
172	REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP,    TM_Sn_STATUS_OFF,  0,  9),
173	REG_FIELD_FOR_EACH_SENSOR11(VALID,        TM_Sn_STATUS_OFF, 14, 14),
174	REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS,   TM_Sn_STATUS_OFF, 10, 10),
175	REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
176	REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
177	/* No CRITICAL field on v1.x */
178	REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS,   TM_Sn_STATUS_OFF, 13, 13),
179
180	/* TRDY: 1=ready, 0=in progress */
181	[TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
182};
183
184static const struct tsens_ops ops_generic_v1 = {
185	.init		= init_common,
186	.calibrate	= calibrate_v1,
187	.get_temp	= get_temp_tsens_valid,
188};
189
190const struct tsens_plat_data data_tsens_v1 = {
191	.ops		= &ops_generic_v1,
192	.feat		= &tsens_v1_feat,
193	.fields	= tsens_v1_regfields,
194};