cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tsens-8960.c (6884B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/platform_device.h>
      7#include <linux/delay.h>
      8#include <linux/bitops.h>
      9#include <linux/regmap.h>
     10#include <linux/thermal.h>
     11#include "tsens.h"
     12
     13#define CONFIG_ADDR		0x3640
     14#define CONFIG_ADDR_8660	0x3620
     15/* CONFIG_ADDR bitmasks */
     16#define CONFIG			0x9b
     17#define CONFIG_MASK		0xf
     18#define CONFIG_8660		1
     19#define CONFIG_SHIFT_8660	28
     20#define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
     21
     22#define CNTL_ADDR		0x3620
     23/* CNTL_ADDR bitmasks */
     24#define EN			BIT(0)
     25#define SW_RST			BIT(1)
     26
     27#define MEASURE_PERIOD		BIT(18)
     28#define SLP_CLK_ENA		BIT(26)
     29#define SLP_CLK_ENA_8660	BIT(24)
     30#define SENSOR0_SHIFT		3
     31
     32#define THRESHOLD_ADDR		0x3624
     33
     34#define INT_STATUS_ADDR		0x363c
     35
     36#define S0_STATUS_OFF		0x3628
     37#define S1_STATUS_OFF		0x362c
     38#define S2_STATUS_OFF		0x3630
     39#define S3_STATUS_OFF		0x3634
     40#define S4_STATUS_OFF		0x3638
     41#define S5_STATUS_OFF		0x3664  /* Sensors 5-10 found on apq8064/msm8960 */
     42#define S6_STATUS_OFF		0x3668
     43#define S7_STATUS_OFF		0x366c
     44#define S8_STATUS_OFF		0x3670
     45#define S9_STATUS_OFF		0x3674
     46#define S10_STATUS_OFF		0x3678
     47
     48/* Original slope - 350 to compensate mC to C inaccuracy */
     49static u32 tsens_msm8960_slope[] = {
     50			826, 826, 804, 826,
     51			761, 782, 782, 849,
     52			782, 849, 782
     53			};
     54
     55static int suspend_8960(struct tsens_priv *priv)
     56{
     57	int ret;
     58	unsigned int mask;
     59	struct regmap *map = priv->tm_map;
     60
     61	ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
     62	if (ret)
     63		return ret;
     64
     65	ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
     66	if (ret)
     67		return ret;
     68
     69	if (priv->num_sensors > 1)
     70		mask = SLP_CLK_ENA | EN;
     71	else
     72		mask = SLP_CLK_ENA_8660 | EN;
     73
     74	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
     75	if (ret)
     76		return ret;
     77
     78	return 0;
     79}
     80
     81static int resume_8960(struct tsens_priv *priv)
     82{
     83	int ret;
     84	struct regmap *map = priv->tm_map;
     85
     86	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
     87	if (ret)
     88		return ret;
     89
     90	/*
     91	 * Separate CONFIG restore is not needed only for 8660 as
     92	 * config is part of CTRL Addr and its restored as such
     93	 */
     94	if (priv->num_sensors > 1) {
     95		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
     96		if (ret)
     97			return ret;
     98	}
     99
    100	ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
    101	if (ret)
    102		return ret;
    103
    104	ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
    105	if (ret)
    106		return ret;
    107
    108	return 0;
    109}
    110
    111static int enable_8960(struct tsens_priv *priv, int id)
    112{
    113	int ret;
    114	u32 reg, mask = BIT(id);
    115
    116	ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
    117	if (ret)
    118		return ret;
    119
    120	/* HARDWARE BUG:
    121	 * On platforms with more than 6 sensors, all remaining sensors
    122	 * must be enabled together, otherwise undefined results are expected.
    123	 * (Sensor 6-7 disabled, Sensor 3 disabled...) In the original driver,
    124	 * all the sensors are enabled in one step hence this bug is not
    125	 * triggered.
    126	 */
    127	if (id > 5)
    128		mask = GENMASK(10, 6);
    129
    130	mask <<= SENSOR0_SHIFT;
    131
    132	/* Sensors already enabled. Skip. */
    133	if ((reg & mask) == mask)
    134		return 0;
    135
    136	ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
    137	if (ret)
    138		return ret;
    139
    140	reg |= MEASURE_PERIOD;
    141
    142	if (priv->num_sensors > 1)
    143		reg |= mask | SLP_CLK_ENA | EN;
    144	else
    145		reg |= mask | SLP_CLK_ENA_8660 | EN;
    146
    147	ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
    148	if (ret)
    149		return ret;
    150
    151	return 0;
    152}
    153
    154static void disable_8960(struct tsens_priv *priv)
    155{
    156	int ret;
    157	u32 reg_cntl;
    158	u32 mask;
    159
    160	mask = GENMASK(priv->num_sensors - 1, 0);
    161	mask <<= SENSOR0_SHIFT;
    162	mask |= EN;
    163
    164	ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
    165	if (ret)
    166		return;
    167
    168	reg_cntl &= ~mask;
    169
    170	if (priv->num_sensors > 1)
    171		reg_cntl &= ~SLP_CLK_ENA;
    172	else
    173		reg_cntl &= ~SLP_CLK_ENA_8660;
    174
    175	regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
    176}
    177
    178static int calibrate_8960(struct tsens_priv *priv)
    179{
    180	int i;
    181	char *data;
    182	u32 p1[11];
    183
    184	data = qfprom_read(priv->dev, "calib");
    185	if (IS_ERR(data))
    186		data = qfprom_read(priv->dev, "calib_backup");
    187	if (IS_ERR(data))
    188		return PTR_ERR(data);
    189
    190	for (i = 0; i < priv->num_sensors; i++) {
    191		p1[i] = data[i];
    192		priv->sensor[i].slope = tsens_msm8960_slope[i];
    193	}
    194
    195	compute_intercept_slope(priv, p1, NULL, ONE_PT_CALIB);
    196
    197	kfree(data);
    198
    199	return 0;
    200}
    201
    202static const struct reg_field tsens_8960_regfields[MAX_REGFIELDS] = {
    203	/* ----- SROT ------ */
    204	/* No VERSION information */
    205
    206	/* CNTL */
    207	[TSENS_EN]     = REG_FIELD(CNTL_ADDR,  0, 0),
    208	[TSENS_SW_RST] = REG_FIELD(CNTL_ADDR,  1, 1),
    209	/* 8960 has 5 sensors, 8660 has 11, we only handle 5 */
    210	[SENSOR_EN]    = REG_FIELD(CNTL_ADDR,  3, 7),
    211
    212	/* ----- TM ------ */
    213	/* INTERRUPT ENABLE */
    214	/* NO INTERRUPT ENABLE */
    215
    216	/* Single UPPER/LOWER TEMPERATURE THRESHOLD for all sensors */
    217	[LOW_THRESH_0]   = REG_FIELD(THRESHOLD_ADDR,  0,  7),
    218	[UP_THRESH_0]    = REG_FIELD(THRESHOLD_ADDR,  8, 15),
    219	/* MIN_THRESH_0 and MAX_THRESH_0 are not present in the regfield
    220	 * Recycle CRIT_THRESH_0 and 1 to set the required regs to hardcoded temp
    221	 * MIN_THRESH_0 -> CRIT_THRESH_1
    222	 * MAX_THRESH_0 -> CRIT_THRESH_0
    223	 */
    224	[CRIT_THRESH_1]   = REG_FIELD(THRESHOLD_ADDR, 16, 23),
    225	[CRIT_THRESH_0]   = REG_FIELD(THRESHOLD_ADDR, 24, 31),
    226
    227	/* UPPER/LOWER INTERRUPT [CLEAR/STATUS] */
    228	/* 1 == clear, 0 == normal operation */
    229	[LOW_INT_CLEAR_0]   = REG_FIELD(CNTL_ADDR,  9,  9),
    230	[UP_INT_CLEAR_0]    = REG_FIELD(CNTL_ADDR, 10, 10),
    231
    232	/* NO CRITICAL INTERRUPT SUPPORT on 8960 */
    233
    234	/* Sn_STATUS */
    235	[LAST_TEMP_0]  = REG_FIELD(S0_STATUS_OFF,  0,  7),
    236	[LAST_TEMP_1]  = REG_FIELD(S1_STATUS_OFF,  0,  7),
    237	[LAST_TEMP_2]  = REG_FIELD(S2_STATUS_OFF,  0,  7),
    238	[LAST_TEMP_3]  = REG_FIELD(S3_STATUS_OFF,  0,  7),
    239	[LAST_TEMP_4]  = REG_FIELD(S4_STATUS_OFF,  0,  7),
    240	[LAST_TEMP_5]  = REG_FIELD(S5_STATUS_OFF,  0,  7),
    241	[LAST_TEMP_6]  = REG_FIELD(S6_STATUS_OFF,  0,  7),
    242	[LAST_TEMP_7]  = REG_FIELD(S7_STATUS_OFF,  0,  7),
    243	[LAST_TEMP_8]  = REG_FIELD(S8_STATUS_OFF,  0,  7),
    244	[LAST_TEMP_9]  = REG_FIELD(S9_STATUS_OFF,  0,  7),
    245	[LAST_TEMP_10] = REG_FIELD(S10_STATUS_OFF, 0,  7),
    246
    247	/* No VALID field on 8960 */
    248	/* TSENS_INT_STATUS bits: 1 == threshold violated */
    249	[MIN_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 0, 0),
    250	[LOWER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 1, 1),
    251	[UPPER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 2, 2),
    252	/* No CRITICAL field on 8960 */
    253	[MAX_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 3, 3),
    254
    255	/* TRDY: 1=ready, 0=in progress */
    256	[TRDY] = REG_FIELD(INT_STATUS_ADDR, 7, 7),
    257};
    258
    259static const struct tsens_ops ops_8960 = {
    260	.init		= init_common,
    261	.calibrate	= calibrate_8960,
    262	.get_temp	= get_temp_common,
    263	.enable		= enable_8960,
    264	.disable	= disable_8960,
    265	.suspend	= suspend_8960,
    266	.resume		= resume_8960,
    267};
    268
    269static struct tsens_features tsens_8960_feat = {
    270	.ver_major	= VER_0,
    271	.crit_int	= 0,
    272	.adc		= 1,
    273	.srot_split	= 0,
    274	.max_sensors	= 11,
    275};
    276
    277struct tsens_plat_data data_8960 = {
    278	.num_sensors	= 11,
    279	.ops		= &ops_8960,
    280	.feat		= &tsens_8960_feat,
    281	.fields		= tsens_8960_regfields,
    282};