diff --git a/drivers/thermal/airoha_thermal.c b/drivers/thermal/airoha_thermal.c
index b9fd6bf..77b3a1a 100644
--- a/drivers/thermal/airoha_thermal.c
+++ b/drivers/thermal/airoha_thermal.c
@@ -18,6 +18,12 @@
#define EN7581_DOUT_TADC 0x2f8
#define EN7581_DOUT_TADC_MASK GENMASK(15, 0)
+#define AN7583_MUX_SENSOR 0x2a0
+#define AN7583_LOAD_ADJ GENMASK(3, 2)
+#define AN7583_MUX_TADC 0x2e4
+#define AN7583_MUX_TADC_MASK GENMASK(3, 1)
+#define AN7583_DOUT_TADC 0x2f0
+
/* PTP_THERMAL regs */
#define EN7581_TEMPMONCTL0 0x800
#define EN7581_SENSE3_EN BIT(3)
@@ -181,6 +187,11 @@
#define EN7581_SCU_THERMAL_PROTECT_KEY 0x12
#define EN7581_SCU_THERMAL_MUX_DIODE1 0x7
+#define AN7583_SCU_THERMAL_PROTECT_KEY 0x80
+#define AN7583_NUM_SENSOR 3
+
+#define AIROHA_THERMAL_NO_MUX_SENSOR -1
+
/* Convert temp to raw value as read from ADC ((((temp / 100) - init) * slope) / 1000) + offset */
#define TEMP_TO_RAW(priv, temp) ((((((temp) / 100) - (priv)->init_temp) * \
(priv)->default_slope) / 1000) + \
@@ -193,42 +204,131 @@
#define AIROHA_MAX_SAMPLES 6
+/*
+ * AN7583 supports all these ADC mux but the original driver
+ * always checked temp with the AN7583_BGP_TEMP_SENSOR.
+ * Assume using the other sensor temperature is invalid and
+ * always read from AN7583_BGP_TEMP_SENSOR.
+ *
+ * On top of this it's defined that AN7583 supports 3
+ * sensor: AN7583_BGP_TEMP_SENSOR, AN7583_GBE_TEMP_SENSOR,
+ * AN7583_CPU_TEMP_SENSOR.
+ *
+ * Provide the ADC mux for reference.
+ */
+enum an7583_thermal_adc_mux {
+ AN7583_BGP_TEMP_SENSOR,
+ AN7583_PAD_AVS,
+ AN7583_CORE_POWER,
+ AN7583_AVSDAC_OUT,
+ AN7583_VCM,
+ AN7583_GBE_TEMP_SENSOR,
+ AN7583_CPU_TEMP_SENSOR,
+
+ AN7583_ADC_MUX_MAX,
+};
+
+enum an7583_thermal_diode_mux {
+ AN7583_D0_TADC,
+ AN7583_ZERO_TADC,
+ AN7583_D1_TADC,
+};
+
+enum airoha_thermal_chip_scu_field {
+ AIROHA_THERMAL_DOUT_TADC,
+ AIROHA_THERMAL_MUX_SENSOR,
+ AIROHA_THERMAL_MUX_TADC,
+
+ /* keep last */
+ AIROHA_THERMAL_FIELD_MAX,
+};
+
struct airoha_thermal_priv {
- void __iomem *base;
+ struct regmap *map;
struct regmap *chip_scu;
+ struct regmap_field *chip_scu_fields[AIROHA_THERMAL_FIELD_MAX];
struct resource scu_adc_res;
+ u32 pllrg_protect;
+ int current_adc;
+
struct thermal_zone_device *tz;
int init_temp;
int default_slope;
int default_offset;
};
+struct airoha_thermal_soc_data {
+ u32 pllrg_protect;
+
+ const struct thermal_zone_device_ops *thdev_ops;
+ int (*probe)(struct platform_device *pdev,
+ struct airoha_thermal_priv *priv);
+ int (*post_probe)(struct platform_device *pdev);
+};
+
+static const unsigned int an7583_thermal_coeff[AN7583_ADC_MUX_MAX] = {
+ [AN7583_BGP_TEMP_SENSOR] = 973,
+ [AN7583_GBE_TEMP_SENSOR] = 995,
+ [AN7583_CPU_TEMP_SENSOR] = 1035,
+};
+
+static const unsigned int an7583_thermal_slope[AN7583_ADC_MUX_MAX] = {
+ [AN7583_BGP_TEMP_SENSOR] = 7440,
+ [AN7583_GBE_TEMP_SENSOR] = 7620,
+ [AN7583_CPU_TEMP_SENSOR] = 8390,
+};
+
+static const unsigned int an7583_thermal_offset[AN7583_ADC_MUX_MAX] = {
+ [AN7583_BGP_TEMP_SENSOR] = 294,
+ [AN7583_GBE_TEMP_SENSOR] = 298,
+ [AN7583_CPU_TEMP_SENSOR] = 344,
+};
+
static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv)
{
u32 val;
- regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val);
- return FIELD_GET(EN7581_DOUT_TADC_MASK, val);
+ regmap_field_read(priv->chip_scu_fields[AIROHA_THERMAL_DOUT_TADC],
+ &val);
+ return val;
}
-static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv)
+static void airoha_set_thermal_mux(struct airoha_thermal_priv *priv,
+ int tdac_idx, int sensor_idx)
{
- u32 adc_mux, pllrg;
+ u32 pllrg;
/* Save PLLRG current value */
regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg);
- /* Give access to thermal regs */
- regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, EN7581_SCU_THERMAL_PROTECT_KEY);
- adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1);
- regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux);
+ /* Give access to Thermal regs */
+ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT,
+ priv->pllrg_protect);
+
+ /*
+ * Configure Thermal Sensor mux to sensor_idx.
+ * (if not supported, sensor_idx is AIROHA_THERMAL_NO_MUX_SENSOR)
+ */
+ if (sensor_idx != AIROHA_THERMAL_NO_MUX_SENSOR)
+ regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_SENSOR],
+ sensor_idx);
+
+ /* Configure Thermal ADC mux to tdac_idx */
+ if (priv->current_adc != tdac_idx) {
+ regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC],
+ tdac_idx);
+ priv->current_adc = tdac_idx;
+ }
/* Restore PLLRG value on exit */
regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg);
+
+ /* Sleep 10 ms for Thermal ADC to enable */
+ usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
}
-static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+static int en7581_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
{
struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
int min_value, max_value, avg_value, value;
@@ -253,7 +353,7 @@ static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
return 0;
}
-static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low,
+static int en7581_thermal_set_trips(struct thermal_zone_device *tz, int low,
int high)
{
struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
@@ -265,44 +365,44 @@ static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low,
RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK)));
/* We offset the high temp of 1°C to trigger correct event */
- writel(TEMP_TO_RAW(priv, high) >> 4,
- priv->base + EN7581_TEMPOFFSETH);
+ regmap_write(priv->map, EN7581_TEMPOFFSETH,
+ TEMP_TO_RAW(priv, high) >> 4);
enable_monitor = true;
}
if (low != -INT_MAX) {
/* Validate low and clamp it to a supported value */
- low = clamp_t(int, high, RAW_TO_TEMP(priv, 0),
+ low = clamp_t(int, low, RAW_TO_TEMP(priv, 0),
RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK)));
/* We offset the low temp of 1°C to trigger correct event */
- writel(TEMP_TO_RAW(priv, low) >> 4,
- priv->base + EN7581_TEMPOFFSETL);
+ regmap_write(priv->map, EN7581_TEMPOFFSETL,
+ TEMP_TO_RAW(priv, low) >> 4);
enable_monitor = true;
}
/* Enable sensor 0 monitor after trip are set */
if (enable_monitor)
- writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0);
+ regmap_write(priv->map, EN7581_TEMPMONCTL0, EN7581_SENSE0_EN);
return 0;
}
-static const struct thermal_zone_device_ops thdev_ops = {
- .get_temp = airoha_thermal_get_temp,
- .set_trips = airoha_thermal_set_trips,
+static const struct thermal_zone_device_ops en7581_thdev_ops = {
+ .get_temp = en7581_thermal_get_temp,
+ .set_trips = en7581_thermal_set_trips,
};
-static irqreturn_t airoha_thermal_irq(int irq, void *data)
+static irqreturn_t en7581_thermal_irq(int irq, void *data)
{
struct airoha_thermal_priv *priv = data;
enum thermal_notify_event event;
bool update = false;
- u32 status;
+ u32 status = 0;
- status = readl(priv->base + EN7581_TEMPMONINTSTS);
+ regmap_read(priv->map, EN7581_TEMPMONINTSTS, &status);
switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) {
case EN7581_HOFSINTSTS0:
event = THERMAL_TRIP_VIOLATED;
@@ -318,7 +418,7 @@ static irqreturn_t airoha_thermal_irq(int irq, void *data)
}
/* Reset Interrupt */
- writel(status, priv->base + EN7581_TEMPMONINTSTS);
+ regmap_write(priv->map, EN7581_TEMPMONINTSTS, status);
if (update)
thermal_zone_device_update(priv->tz, event);
@@ -326,21 +426,21 @@ static irqreturn_t airoha_thermal_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static void airoha_thermal_setup_adc_val(struct device *dev,
+static void en7581_thermal_setup_adc_val(struct device *dev,
struct airoha_thermal_priv *priv)
{
- u32 efuse_calib_info, cpu_sensor;
+ u32 efuse_calib_info = 0;
+ u32 cpu_sensor = 0;
- /* Setup thermal sensor to ADC mode and setup the mux to DIODE1 */
- airoha_init_thermal_ADC_mode(priv);
- /* sleep 10 ms for ADC to enable */
- usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
+ /* Setup Thermal Sensor to ADC mode and setup the mux to DIODE1 */
+ airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1,
+ AIROHA_THERMAL_NO_MUX_SENSOR);
- efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG);
+ regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info);
if (efuse_calib_info) {
priv->default_offset = FIELD_GET(EN7581_EFUSE_TEMP_OFFSET, efuse_calib_info);
/* Different slope are applied if the sensor is used for CPU or for package */
- cpu_sensor = readl(priv->base + EN7581_EFUSE_TEMP_CPU_SENSOR_REG);
+ regmap_read(priv->map, EN7581_EFUSE_TEMP_CPU_SENSOR_REG, &cpu_sensor);
if (cpu_sensor) {
priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT;
priv->init_temp = EN7581_INIT_TEMP_FTK_X10;
@@ -356,11 +456,11 @@ static void airoha_thermal_setup_adc_val(struct device *dev,
}
}
-static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv)
+static void en7581_thermal_setup_monitor(struct airoha_thermal_priv *priv)
{
/* Set measure mode */
- writel(FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4),
- priv->base + EN7581_TEMPMSRCTL0);
+ regmap_write(priv->map, EN7581_TEMPMSRCTL0,
+ FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4));
/*
* Configure ADC valid reading addr
@@ -375,15 +475,15 @@ static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv)
* We set valid instead of volt as we don't enable valid/volt
* split reading and AHB read valid addr in such case.