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

sprd_thermal.c (14232B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2020 Spreadtrum Communications Inc.
      3
      4#include <linux/clk.h>
      5#include <linux/io.h>
      6#include <linux/iopoll.h>
      7#include <linux/module.h>
      8#include <linux/nvmem-consumer.h>
      9#include <linux/of_device.h>
     10#include <linux/platform_device.h>
     11#include <linux/slab.h>
     12#include <linux/thermal.h>
     13
     14#define SPRD_THM_CTL			0x0
     15#define SPRD_THM_INT_EN			0x4
     16#define SPRD_THM_INT_STS		0x8
     17#define SPRD_THM_INT_RAW_STS		0xc
     18#define SPRD_THM_DET_PERIOD		0x10
     19#define SPRD_THM_INT_CLR		0x14
     20#define SPRD_THM_INT_CLR_ST		0x18
     21#define SPRD_THM_MON_PERIOD		0x4c
     22#define SPRD_THM_MON_CTL		0x50
     23#define SPRD_THM_INTERNAL_STS1		0x54
     24#define SPRD_THM_RAW_READ_MSK		0x3ff
     25
     26#define SPRD_THM_OFFSET(id)		((id) * 0x4)
     27#define SPRD_THM_TEMP(id)		(SPRD_THM_OFFSET(id) + 0x5c)
     28#define SPRD_THM_THRES(id)		(SPRD_THM_OFFSET(id) + 0x2c)
     29
     30#define SPRD_THM_SEN(id)		BIT((id) + 2)
     31#define SPRD_THM_SEN_OVERHEAT_EN(id)	BIT((id) + 8)
     32#define SPRD_THM_SEN_OVERHEAT_ALARM_EN(id)	BIT((id) + 0)
     33
     34/* bits definitions for register THM_CTL */
     35#define SPRD_THM_SET_RDY_ST		BIT(13)
     36#define SPRD_THM_SET_RDY		BIT(12)
     37#define SPRD_THM_MON_EN			BIT(1)
     38#define SPRD_THM_EN			BIT(0)
     39
     40/* bits definitions for register THM_INT_CTL */
     41#define SPRD_THM_BIT_INT_EN		BIT(26)
     42#define SPRD_THM_OVERHEAT_EN		BIT(25)
     43#define SPRD_THM_OTP_TRIP_SHIFT		10
     44
     45/* bits definitions for register SPRD_THM_INTERNAL_STS1 */
     46#define SPRD_THM_TEMPER_RDY		BIT(0)
     47
     48#define SPRD_THM_DET_PERIOD_DATA	0x800
     49#define SPRD_THM_DET_PERIOD_MASK	GENMASK(19, 0)
     50#define SPRD_THM_MON_MODE		0x7
     51#define SPRD_THM_MON_MODE_MASK		GENMASK(3, 0)
     52#define SPRD_THM_MON_PERIOD_DATA	0x10
     53#define SPRD_THM_MON_PERIOD_MASK	GENMASK(15, 0)
     54#define SPRD_THM_THRES_MASK		GENMASK(19, 0)
     55#define SPRD_THM_INT_CLR_MASK		GENMASK(24, 0)
     56
     57/* thermal sensor calibration parameters */
     58#define SPRD_THM_TEMP_LOW		-40000
     59#define SPRD_THM_TEMP_HIGH		120000
     60#define SPRD_THM_OTP_TEMP		120000
     61#define SPRD_THM_HOT_TEMP		75000
     62#define SPRD_THM_RAW_DATA_LOW		0
     63#define SPRD_THM_RAW_DATA_HIGH		1000
     64#define SPRD_THM_SEN_NUM		8
     65#define SPRD_THM_DT_OFFSET		24
     66#define SPRD_THM_RATION_OFFSET		17
     67#define SPRD_THM_RATION_SIGN		16
     68
     69#define SPRD_THM_RDYST_POLLING_TIME	10
     70#define SPRD_THM_RDYST_TIMEOUT		700
     71#define SPRD_THM_TEMP_READY_POLL_TIME	10000
     72#define SPRD_THM_TEMP_READY_TIMEOUT	600000
     73#define SPRD_THM_MAX_SENSOR		8
     74
     75struct sprd_thermal_sensor {
     76	struct thermal_zone_device *tzd;
     77	struct sprd_thermal_data *data;
     78	struct device *dev;
     79	int cal_slope;
     80	int cal_offset;
     81	int id;
     82};
     83
     84struct sprd_thermal_data {
     85	const struct sprd_thm_variant_data *var_data;
     86	struct sprd_thermal_sensor *sensor[SPRD_THM_MAX_SENSOR];
     87	struct clk *clk;
     88	void __iomem *base;
     89	u32 ratio_off;
     90	int ratio_sign;
     91	int nr_sensors;
     92};
     93
     94/*
     95 * The conversion between ADC and temperature is based on linear relationship,
     96 * and use idea_k to specify the slope and ideal_b to specify the offset.
     97 *
     98 * Since different Spreadtrum SoCs have different ideal_k and ideal_b,
     99 * we should save ideal_k and ideal_b in the device data structure.
    100 */
    101struct sprd_thm_variant_data {
    102	u32 ideal_k;
    103	u32 ideal_b;
    104};
    105
    106static const struct sprd_thm_variant_data ums512_data = {
    107	.ideal_k = 262,
    108	.ideal_b = 66400,
    109};
    110
    111static inline void sprd_thm_update_bits(void __iomem *reg, u32 mask, u32 val)
    112{
    113	u32 tmp, orig;
    114
    115	orig = readl(reg);
    116	tmp = orig & ~mask;
    117	tmp |= val & mask;
    118	writel(tmp, reg);
    119}
    120
    121static int sprd_thm_cal_read(struct device_node *np, const char *cell_id,
    122			     u32 *val)
    123{
    124	struct nvmem_cell *cell;
    125	void *buf;
    126	size_t len;
    127
    128	cell = of_nvmem_cell_get(np, cell_id);
    129	if (IS_ERR(cell))
    130		return PTR_ERR(cell);
    131
    132	buf = nvmem_cell_read(cell, &len);
    133	nvmem_cell_put(cell);
    134	if (IS_ERR(buf))
    135		return PTR_ERR(buf);
    136
    137	if (len > sizeof(u32)) {
    138		kfree(buf);
    139		return -EINVAL;
    140	}
    141
    142	memcpy(val, buf, len);
    143
    144	kfree(buf);
    145	return 0;
    146}
    147
    148static int sprd_thm_sensor_calibration(struct device_node *np,
    149				       struct sprd_thermal_data *thm,
    150				       struct sprd_thermal_sensor *sen)
    151{
    152	int ret;
    153	/*
    154	 * According to thermal datasheet, the default calibration offset is 64,
    155	 * and the default ratio is 1000.
    156	 */
    157	int dt_offset = 64, ratio = 1000;
    158
    159	ret = sprd_thm_cal_read(np, "sen_delta_cal", &dt_offset);
    160	if (ret)
    161		return ret;
    162
    163	ratio += thm->ratio_sign * thm->ratio_off;
    164
    165	/*
    166	 * According to the ideal slope K and ideal offset B, combined with
    167	 * calibration value of thermal from efuse, then calibrate the real
    168	 * slope k and offset b:
    169	 * k_cal = (k * ratio) / 1000.
    170	 * b_cal = b + (dt_offset - 64) * 500.
    171	 */
    172	sen->cal_slope = (thm->var_data->ideal_k * ratio) / 1000;
    173	sen->cal_offset = thm->var_data->ideal_b + (dt_offset - 128) * 250;
    174
    175	return 0;
    176}
    177
    178static int sprd_thm_rawdata_to_temp(struct sprd_thermal_sensor *sen,
    179				    u32 rawdata)
    180{
    181	clamp(rawdata, (u32)SPRD_THM_RAW_DATA_LOW, (u32)SPRD_THM_RAW_DATA_HIGH);
    182
    183	/*
    184	 * According to the thermal datasheet, the formula of converting
    185	 * adc value to the temperature value should be:
    186	 * T_final = k_cal * x - b_cal.
    187	 */
    188	return sen->cal_slope * rawdata - sen->cal_offset;
    189}
    190
    191static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen)
    192{
    193	u32 val;
    194
    195	clamp(temp, (int)SPRD_THM_TEMP_LOW, (int)SPRD_THM_TEMP_HIGH);
    196
    197	/*
    198	 * According to the thermal datasheet, the formula of converting
    199	 * adc value to the temperature value should be:
    200	 * T_final = k_cal * x - b_cal.
    201	 */
    202	val = (temp + sen->cal_offset) / sen->cal_slope;
    203
    204	return clamp(val, val, (u32)(SPRD_THM_RAW_DATA_HIGH - 1));
    205}
    206
    207static int sprd_thm_read_temp(void *devdata, int *temp)
    208{
    209	struct sprd_thermal_sensor *sen = devdata;
    210	u32 data;
    211
    212	data = readl(sen->data->base + SPRD_THM_TEMP(sen->id)) &
    213		SPRD_THM_RAW_READ_MSK;
    214
    215	*temp = sprd_thm_rawdata_to_temp(sen, data);
    216
    217	return 0;
    218}
    219
    220static const struct thermal_zone_of_device_ops sprd_thm_ops = {
    221	.get_temp = sprd_thm_read_temp,
    222};
    223
    224static int sprd_thm_poll_ready_status(struct sprd_thermal_data *thm)
    225{
    226	u32 val;
    227	int ret;
    228
    229	/*
    230	 * Wait for thermal ready status before configuring thermal parameters.
    231	 */
    232	ret = readl_poll_timeout(thm->base + SPRD_THM_CTL, val,
    233				 !(val & SPRD_THM_SET_RDY_ST),
    234				 SPRD_THM_RDYST_POLLING_TIME,
    235				 SPRD_THM_RDYST_TIMEOUT);
    236	if (ret)
    237		return ret;
    238
    239	sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_MON_EN,
    240			     SPRD_THM_MON_EN);
    241	sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SET_RDY,
    242			     SPRD_THM_SET_RDY);
    243	return 0;
    244}
    245
    246static int sprd_thm_wait_temp_ready(struct sprd_thermal_data *thm)
    247{
    248	u32 val;
    249
    250	/* Wait for first temperature data ready before reading temperature */
    251	return readl_poll_timeout(thm->base + SPRD_THM_INTERNAL_STS1, val,
    252				  !(val & SPRD_THM_TEMPER_RDY),
    253				  SPRD_THM_TEMP_READY_POLL_TIME,
    254				  SPRD_THM_TEMP_READY_TIMEOUT);
    255}
    256
    257static int sprd_thm_set_ready(struct sprd_thermal_data *thm)
    258{
    259	int ret;
    260
    261	ret = sprd_thm_poll_ready_status(thm);
    262	if (ret)
    263		return ret;
    264
    265	/*
    266	 * Clear interrupt status, enable thermal interrupt and enable thermal.
    267	 *
    268	 * The SPRD thermal controller integrates a hardware interrupt signal,
    269	 * which means if the temperature is overheat, it will generate an
    270	 * interrupt and notify the event to PMIC automatically to shutdown the
    271	 * system. So here we should enable the interrupt bits, though we have
    272	 * not registered an irq handler.
    273	 */
    274	writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR);
    275	sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN,
    276			     SPRD_THM_BIT_INT_EN, SPRD_THM_BIT_INT_EN);
    277	sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
    278			     SPRD_THM_EN, SPRD_THM_EN);
    279	return 0;
    280}
    281
    282static void sprd_thm_sensor_init(struct sprd_thermal_data *thm,
    283				 struct sprd_thermal_sensor *sen)
    284{
    285	u32 otp_rawdata, hot_rawdata;
    286
    287	otp_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_OTP_TEMP, sen);
    288	hot_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_HOT_TEMP, sen);
    289
    290	/* Enable the sensor' overheat temperature protection interrupt */
    291	sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN,
    292			     SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id),
    293			     SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id));
    294
    295	/* Set the sensor' overheat and hot threshold temperature */
    296	sprd_thm_update_bits(thm->base + SPRD_THM_THRES(sen->id),
    297			     SPRD_THM_THRES_MASK,
    298			     (otp_rawdata << SPRD_THM_OTP_TRIP_SHIFT) |
    299			     hot_rawdata);
    300
    301	/* Enable the corresponding sensor */
    302	sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SEN(sen->id),
    303			     SPRD_THM_SEN(sen->id));
    304}
    305
    306static void sprd_thm_para_config(struct sprd_thermal_data *thm)
    307{
    308	/* Set the period of two valid temperature detection action */
    309	sprd_thm_update_bits(thm->base + SPRD_THM_DET_PERIOD,
    310			     SPRD_THM_DET_PERIOD_MASK, SPRD_THM_DET_PERIOD);
    311
    312	/* Set the sensors' monitor mode */
    313	sprd_thm_update_bits(thm->base + SPRD_THM_MON_CTL,
    314			     SPRD_THM_MON_MODE_MASK, SPRD_THM_MON_MODE);
    315
    316	/* Set the sensors' monitor period */
    317	sprd_thm_update_bits(thm->base + SPRD_THM_MON_PERIOD,
    318			     SPRD_THM_MON_PERIOD_MASK, SPRD_THM_MON_PERIOD);
    319}
    320
    321static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on)
    322{
    323	struct thermal_zone_device *tzd = sen->tzd;
    324
    325	if (on)
    326		thermal_zone_device_enable(tzd);
    327	else
    328		thermal_zone_device_disable(tzd);
    329}
    330
    331static int sprd_thm_probe(struct platform_device *pdev)
    332{
    333	struct device_node *np = pdev->dev.of_node;
    334	struct device_node *sen_child;
    335	struct sprd_thermal_data *thm;
    336	struct sprd_thermal_sensor *sen;
    337	const struct sprd_thm_variant_data *pdata;
    338	int ret, i;
    339	u32 val;
    340
    341	pdata = of_device_get_match_data(&pdev->dev);
    342	if (!pdata) {
    343		dev_err(&pdev->dev, "No matching driver data found\n");
    344		return -EINVAL;
    345	}
    346
    347	thm = devm_kzalloc(&pdev->dev, sizeof(*thm), GFP_KERNEL);
    348	if (!thm)
    349		return -ENOMEM;
    350
    351	thm->var_data = pdata;
    352	thm->base = devm_platform_ioremap_resource(pdev, 0);
    353	if (IS_ERR(thm->base))
    354		return PTR_ERR(thm->base);
    355
    356	thm->nr_sensors = of_get_child_count(np);
    357	if (thm->nr_sensors == 0 || thm->nr_sensors > SPRD_THM_MAX_SENSOR) {
    358		dev_err(&pdev->dev, "incorrect sensor count\n");
    359		return -EINVAL;
    360	}
    361
    362	thm->clk = devm_clk_get(&pdev->dev, "enable");
    363	if (IS_ERR(thm->clk)) {
    364		dev_err(&pdev->dev, "failed to get enable clock\n");
    365		return PTR_ERR(thm->clk);
    366	}
    367
    368	ret = clk_prepare_enable(thm->clk);
    369	if (ret)
    370		return ret;
    371
    372	sprd_thm_para_config(thm);
    373
    374	ret = sprd_thm_cal_read(np, "thm_sign_cal", &val);
    375	if (ret)
    376		goto disable_clk;
    377
    378	if (val > 0)
    379		thm->ratio_sign = -1;
    380	else
    381		thm->ratio_sign = 1;
    382
    383	ret = sprd_thm_cal_read(np, "thm_ratio_cal", &thm->ratio_off);
    384	if (ret)
    385		goto disable_clk;
    386
    387	for_each_child_of_node(np, sen_child) {
    388		sen = devm_kzalloc(&pdev->dev, sizeof(*sen), GFP_KERNEL);
    389		if (!sen) {
    390			ret = -ENOMEM;
    391			goto of_put;
    392		}
    393
    394		sen->data = thm;
    395		sen->dev = &pdev->dev;
    396
    397		ret = of_property_read_u32(sen_child, "reg", &sen->id);
    398		if (ret) {
    399			dev_err(&pdev->dev, "get sensor reg failed");
    400			goto of_put;
    401		}
    402
    403		ret = sprd_thm_sensor_calibration(sen_child, thm, sen);
    404		if (ret) {
    405			dev_err(&pdev->dev, "efuse cal analysis failed");
    406			goto of_put;
    407		}
    408
    409		sprd_thm_sensor_init(thm, sen);
    410
    411		sen->tzd = devm_thermal_zone_of_sensor_register(sen->dev,
    412								sen->id,
    413								sen,
    414								&sprd_thm_ops);
    415		if (IS_ERR(sen->tzd)) {
    416			dev_err(&pdev->dev, "register thermal zone failed %d\n",
    417				sen->id);
    418			ret = PTR_ERR(sen->tzd);
    419			goto of_put;
    420		}
    421
    422		thm->sensor[sen->id] = sen;
    423	}
    424	/* sen_child set to NULL at this point */
    425
    426	ret = sprd_thm_set_ready(thm);
    427	if (ret)
    428		goto of_put;
    429
    430	ret = sprd_thm_wait_temp_ready(thm);
    431	if (ret)
    432		goto of_put;
    433
    434	for (i = 0; i < thm->nr_sensors; i++)
    435		sprd_thm_toggle_sensor(thm->sensor[i], true);
    436
    437	platform_set_drvdata(pdev, thm);
    438	return 0;
    439
    440of_put:
    441	of_node_put(sen_child);
    442disable_clk:
    443	clk_disable_unprepare(thm->clk);
    444	return ret;
    445}
    446
    447#ifdef CONFIG_PM_SLEEP
    448static void sprd_thm_hw_suspend(struct sprd_thermal_data *thm)
    449{
    450	int i;
    451
    452	for (i = 0; i < thm->nr_sensors; i++) {
    453		sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
    454				     SPRD_THM_SEN(thm->sensor[i]->id), 0);
    455	}
    456
    457	sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
    458			     SPRD_THM_EN, 0x0);
    459}
    460
    461static int sprd_thm_suspend(struct device *dev)
    462{
    463	struct sprd_thermal_data *thm = dev_get_drvdata(dev);
    464	int i;
    465
    466	for (i = 0; i < thm->nr_sensors; i++)
    467		sprd_thm_toggle_sensor(thm->sensor[i], false);
    468
    469	sprd_thm_hw_suspend(thm);
    470	clk_disable_unprepare(thm->clk);
    471
    472	return 0;
    473}
    474
    475static int sprd_thm_hw_resume(struct sprd_thermal_data *thm)
    476{
    477	int ret, i;
    478
    479	for (i = 0; i < thm->nr_sensors; i++) {
    480		sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
    481				     SPRD_THM_SEN(thm->sensor[i]->id),
    482				     SPRD_THM_SEN(thm->sensor[i]->id));
    483	}
    484
    485	ret = sprd_thm_poll_ready_status(thm);
    486	if (ret)
    487		return ret;
    488
    489	writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR);
    490	sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
    491			     SPRD_THM_EN, SPRD_THM_EN);
    492	return sprd_thm_wait_temp_ready(thm);
    493}
    494
    495static int sprd_thm_resume(struct device *dev)
    496{
    497	struct sprd_thermal_data *thm = dev_get_drvdata(dev);
    498	int ret, i;
    499
    500	ret = clk_prepare_enable(thm->clk);
    501	if (ret)
    502		return ret;
    503
    504	ret = sprd_thm_hw_resume(thm);
    505	if (ret)
    506		goto disable_clk;
    507
    508	for (i = 0; i < thm->nr_sensors; i++)
    509		sprd_thm_toggle_sensor(thm->sensor[i], true);
    510
    511	return 0;
    512
    513disable_clk:
    514	clk_disable_unprepare(thm->clk);
    515	return ret;
    516}
    517#endif
    518
    519static int sprd_thm_remove(struct platform_device *pdev)
    520{
    521	struct sprd_thermal_data *thm = platform_get_drvdata(pdev);
    522	int i;
    523
    524	for (i = 0; i < thm->nr_sensors; i++) {
    525		sprd_thm_toggle_sensor(thm->sensor[i], false);
    526		devm_thermal_zone_of_sensor_unregister(&pdev->dev,
    527						       thm->sensor[i]->tzd);
    528	}
    529
    530	clk_disable_unprepare(thm->clk);
    531	return 0;
    532}
    533
    534static const struct of_device_id sprd_thermal_of_match[] = {
    535	{ .compatible = "sprd,ums512-thermal", .data = &ums512_data },
    536	{ },
    537};
    538MODULE_DEVICE_TABLE(of, sprd_thermal_of_match);
    539
    540static const struct dev_pm_ops sprd_thermal_pm_ops = {
    541	SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume)
    542};
    543
    544static struct platform_driver sprd_thermal_driver = {
    545	.probe = sprd_thm_probe,
    546	.remove = sprd_thm_remove,
    547	.driver = {
    548		.name = "sprd-thermal",
    549		.pm = &sprd_thermal_pm_ops,
    550		.of_match_table = sprd_thermal_of_match,
    551	},
    552};
    553
    554module_platform_driver(sprd_thermal_driver);
    555
    556MODULE_AUTHOR("Freeman Liu <freeman.liu@unisoc.com>");
    557MODULE_DESCRIPTION("Spreadtrum thermal driver");
    558MODULE_LICENSE("GPL v2");