Commit 45d7b386 authored by Finley Xiao's avatar Finley Xiao Committed by Daniel Lezcano
Browse files

thermal/drivers/rockchip: Support RK3588 SoC in the thermal driver



The RK3588 SoC has seven temperature sensor ADC channels:

- Chip Center
- CPU Cluster 1 (Dual A76 "Big" Cores)
- CPU Cluster 2 (Dual A76 "Big" Cores)
- CPU Cluster 0 (Quad A55 "Little" Cores)
- Power Domain Center
- Graphics Processing Unit
- Neural Processing Unit

Signed-off-by: default avatarFinley Xiao <finley.xiao@rock-chips.com>
[rebase, squash fixes]
Reviewed-by: default avatarHeiko Stuebner <heiko@sntech.de>
Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20230308112253.15659-7-sebastian.reichel@collabora.com
parent 267f5965
Loading
Loading
Loading
Loading
+177 −0
Original line number Diff line number Diff line
@@ -165,29 +165,49 @@ struct rockchip_thermal_data {
#define TSADCV2_AUTO_CON			0x04
#define TSADCV2_INT_EN				0x08
#define TSADCV2_INT_PD				0x0c
#define TSADCV3_AUTO_SRC_CON			0x0c
#define TSADCV3_HT_INT_EN			0x14
#define TSADCV3_HSHUT_GPIO_INT_EN		0x18
#define TSADCV3_HSHUT_CRU_INT_EN		0x1c
#define TSADCV3_INT_PD				0x24
#define TSADCV3_HSHUT_PD			0x28
#define TSADCV2_DATA(chn)			(0x20 + (chn) * 0x04)
#define TSADCV2_COMP_INT(chn)		        (0x30 + (chn) * 0x04)
#define TSADCV2_COMP_SHUT(chn)		        (0x40 + (chn) * 0x04)
#define TSADCV3_DATA(chn)			(0x2c + (chn) * 0x04)
#define TSADCV3_COMP_INT(chn)		        (0x6c + (chn) * 0x04)
#define TSADCV3_COMP_SHUT(chn)		        (0x10c + (chn) * 0x04)
#define TSADCV2_HIGHT_INT_DEBOUNCE		0x60
#define TSADCV2_HIGHT_TSHUT_DEBOUNCE		0x64
#define TSADCV3_HIGHT_INT_DEBOUNCE		0x14c
#define TSADCV3_HIGHT_TSHUT_DEBOUNCE		0x150
#define TSADCV2_AUTO_PERIOD			0x68
#define TSADCV2_AUTO_PERIOD_HT			0x6c
#define TSADCV3_AUTO_PERIOD			0x154
#define TSADCV3_AUTO_PERIOD_HT			0x158

#define TSADCV2_AUTO_EN				BIT(0)
#define TSADCV2_AUTO_EN_MASK			BIT(16)
#define TSADCV2_AUTO_SRC_EN(chn)		BIT(4 + (chn))
#define TSADCV3_AUTO_SRC_EN(chn)		BIT(chn)
#define TSADCV3_AUTO_SRC_EN_MASK(chn)		BIT(16 + chn)
#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH	BIT(8)
#define TSADCV2_AUTO_TSHUT_POLARITY_MASK	BIT(24)

#define TSADCV3_AUTO_Q_SEL_EN			BIT(1)

#define TSADCV2_INT_SRC_EN(chn)			BIT(chn)
#define TSADCV2_INT_SRC_EN_MASK(chn)		BIT(16 + (chn))
#define TSADCV2_SHUT_2GPIO_SRC_EN(chn)		BIT(4 + (chn))
#define TSADCV2_SHUT_2CRU_SRC_EN(chn)		BIT(8 + (chn))

#define TSADCV2_INT_PD_CLEAR_MASK		~BIT(8)
#define TSADCV3_INT_PD_CLEAR_MASK		~BIT(16)
#define TSADCV4_INT_PD_CLEAR_MASK		0xffffffff

#define TSADCV2_DATA_MASK			0xfff
#define TSADCV3_DATA_MASK			0x3ff
#define TSADCV4_DATA_MASK			0x1ff

#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT	4
#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT	4
@@ -198,6 +218,8 @@ struct rockchip_thermal_data {

#define TSADCV5_AUTO_PERIOD_TIME		1622 /* 2.5ms */
#define TSADCV5_AUTO_PERIOD_HT_TIME		1622 /* 2.5ms */
#define TSADCV6_AUTO_PERIOD_TIME		5000 /* 2.5ms */
#define TSADCV6_AUTO_PERIOD_HT_TIME		5000 /* 2.5ms */

#define TSADCV2_USER_INTER_PD_SOC		0x340 /* 13 clocks */
#define TSADCV5_USER_INTER_PD_SOC		0xfc0 /* 97us, at least 90us */
@@ -214,6 +236,12 @@ struct rockchip_thermal_data {
#define RK3568_GRF_TSADC_ANA_REG2		(0x10001 << 2)
#define RK3568_GRF_TSADC_TSEN			(0x10001 << 8)

#define RK3588_GRF0_TSADC_CON			0x0100

#define RK3588_GRF0_TSADC_TRM			(0xff0077 << 0)
#define RK3588_GRF0_TSADC_SHUT_2CRU		(0x30003 << 10)
#define RK3588_GRF0_TSADC_SHUT_2GPIO		(0x70007 << 12)

#define GRF_SARADC_TESTBIT_ON			(0x10001 << 2)
#define GRF_TSADC_TESTBIT_H_ON			(0x10001 << 2)
#define GRF_TSADC_VCM_EN_L			(0x10001 << 7)
@@ -508,6 +536,15 @@ static const struct tsadc_table rk3568_code_table[] = {
	{TSADCV2_DATA_MASK, 125000},
};

static const struct tsadc_table rk3588_code_table[] = {
	{0, -40000},
	{215, -40000},
	{285, 25000},
	{350, 85000},
	{395, 125000},
	{TSADCV4_DATA_MASK, 125000},
};

static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
				   int temp)
{
@@ -778,6 +815,25 @@ static void rk_tsadcv7_initialize(struct regmap *grf, void __iomem *regs,
	}
}

static void rk_tsadcv8_initialize(struct regmap *grf, void __iomem *regs,
				  enum tshut_polarity tshut_polarity)
{
	writel_relaxed(TSADCV6_AUTO_PERIOD_TIME, regs + TSADCV3_AUTO_PERIOD);
	writel_relaxed(TSADCV6_AUTO_PERIOD_HT_TIME,
		       regs + TSADCV3_AUTO_PERIOD_HT);
	writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
		       regs + TSADCV3_HIGHT_INT_DEBOUNCE);
	writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
		       regs + TSADCV3_HIGHT_TSHUT_DEBOUNCE);
	if (tshut_polarity == TSHUT_HIGH_ACTIVE)
		writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_HIGH |
			       TSADCV2_AUTO_TSHUT_POLARITY_MASK,
			       regs + TSADCV2_AUTO_CON);
	else
		writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_MASK,
			       regs + TSADCV2_AUTO_CON);
}

static void rk_tsadcv2_irq_ack(void __iomem *regs)
{
	u32 val;
@@ -794,6 +850,17 @@ static void rk_tsadcv3_irq_ack(void __iomem *regs)
	writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
}

static void rk_tsadcv4_irq_ack(void __iomem *regs)
{
	u32 val;

	val = readl_relaxed(regs + TSADCV3_INT_PD);
	writel_relaxed(val & TSADCV4_INT_PD_CLEAR_MASK, regs + TSADCV3_INT_PD);
	val = readl_relaxed(regs + TSADCV3_HSHUT_PD);
	writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK,
		       regs + TSADCV3_HSHUT_PD);
}

static void rk_tsadcv2_control(void __iomem *regs, bool enable)
{
	u32 val;
@@ -829,6 +896,18 @@ static void rk_tsadcv3_control(void __iomem *regs, bool enable)
	writel_relaxed(val, regs + TSADCV2_AUTO_CON);
}

static void rk_tsadcv4_control(void __iomem *regs, bool enable)
{
	u32 val;

	if (enable)
		val = TSADCV2_AUTO_EN | TSADCV2_AUTO_EN_MASK;
	else
		val = TSADCV2_AUTO_EN_MASK;

	writel_relaxed(val, regs + TSADCV2_AUTO_CON);
}

static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table,
			       int chn, void __iomem *regs, int *temp)
{
@@ -839,6 +918,16 @@ static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table,
	return rk_tsadcv2_code_to_temp(table, val, temp);
}

static int rk_tsadcv4_get_temp(const struct chip_tsadc_table *table,
			       int chn, void __iomem *regs, int *temp)
{
	u32 val;

	val = readl_relaxed(regs + TSADCV3_DATA(chn));

	return rk_tsadcv2_code_to_temp(table, val, temp);
}

static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
				 int chn, void __iomem *regs, int temp)
{
@@ -873,6 +962,33 @@ static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
	return 0;
}

static int rk_tsadcv3_alarm_temp(const struct chip_tsadc_table *table,
				 int chn, void __iomem *regs, int temp)
{
	u32 alarm_value;

	/*
	 * In some cases, some sensors didn't need the trip points, the
	 * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
	 * in the end, ignore this case and disable the high temperature
	 * interrupt.
	 */
	if (temp == INT_MAX) {
		writel_relaxed(TSADCV2_INT_SRC_EN_MASK(chn),
			       regs + TSADCV3_HT_INT_EN);
		return 0;
	}
	/* Make sure the value is valid */
	alarm_value = rk_tsadcv2_temp_to_code(table, temp);
	if (alarm_value == table->data_mask)
		return -ERANGE;
	writel_relaxed(alarm_value & table->data_mask,
		       regs + TSADCV3_COMP_INT(chn));
	writel_relaxed(TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn),
		       regs + TSADCV3_HT_INT_EN);
	return 0;
}

static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
				 int chn, void __iomem *regs, int temp)
{
@@ -892,6 +1008,25 @@ static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
	return 0;
}

static int rk_tsadcv3_tshut_temp(const struct chip_tsadc_table *table,
				 int chn, void __iomem *regs, int temp)
{
	u32 tshut_value;

	/* Make sure the value is valid */
	tshut_value = rk_tsadcv2_temp_to_code(table, temp);
	if (tshut_value == table->data_mask)
		return -ERANGE;

	writel_relaxed(tshut_value, regs + TSADCV3_COMP_SHUT(chn));

	/* TSHUT will be valid */
	writel_relaxed(TSADCV3_AUTO_SRC_EN(chn) | TSADCV3_AUTO_SRC_EN_MASK(chn),
		       regs + TSADCV3_AUTO_SRC_CON);

	return 0;
}

static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
				  enum tshut_mode mode)
{
@@ -909,6 +1044,22 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
	writel_relaxed(val, regs + TSADCV2_INT_EN);
}

static void rk_tsadcv3_tshut_mode(int chn, void __iomem *regs,
				  enum tshut_mode mode)
{
	u32 val_gpio, val_cru;

	if (mode == TSHUT_MODE_GPIO) {
		val_gpio = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn);
		val_cru = TSADCV2_INT_SRC_EN_MASK(chn);
	} else {
		val_cru = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn);
		val_gpio = TSADCV2_INT_SRC_EN_MASK(chn);
	}
	writel_relaxed(val_gpio, regs + TSADCV3_HSHUT_GPIO_INT_EN);
	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
}

static const struct rockchip_tsadc_chip px30_tsadc_data = {
	/* cpu, gpu */
	.chn_offset = 0,
@@ -1132,6 +1283,28 @@ static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
	},
};

static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
	/* top, big_core0, big_core1, little_core, center, gpu, npu */
	.chn_offset = 0,
	.chn_num = 7, /* seven channels for tsadc */
	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
	.tshut_temp = 95000,
	.initialize = rk_tsadcv8_initialize,
	.irq_ack = rk_tsadcv4_irq_ack,
	.control = rk_tsadcv4_control,
	.get_temp = rk_tsadcv4_get_temp,
	.set_alarm_temp = rk_tsadcv3_alarm_temp,
	.set_tshut_temp = rk_tsadcv3_tshut_temp,
	.set_tshut_mode = rk_tsadcv3_tshut_mode,
	.table = {
		.id = rk3588_code_table,
		.length = ARRAY_SIZE(rk3588_code_table),
		.data_mask = TSADCV4_DATA_MASK,
		.mode = ADC_INCREMENT,
	},
};

static const struct of_device_id of_rockchip_thermal_match[] = {
	{	.compatible = "rockchip,px30-tsadc",
		.data = (void *)&px30_tsadc_data,
@@ -1168,6 +1341,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
		.compatible = "rockchip,rk3568-tsadc",
		.data = (void *)&rk3568_tsadc_data,
	},
	{
		.compatible = "rockchip,rk3588-tsadc",
		.data = (void *)&rk3588_tsadc_data,
	},
	{ /* end */ },
};
MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);