From be926ceeb4efc3bf44cb9b56f5c71aac9b1f8bbe Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Sun, 1 Jul 2018 00:10:50 +0200 Subject: [PATCH 01/34] thermal: i.MX: Allow thermal probe to fail gracefully in case of bad calibration. Without this fix, the thermal probe on i.MX6 might trigger a division by zero exception later in the probe if the calibration does fail. Note: This linux behavior (Division by zero in kernel) has been triggered on a Qemu i.MX6 emulation where parameters in nvmem were not set. With this fix the division by zero is not triggeed anymore as the thermal probe does fail early. Signed-off-by: Jean-Christophe Dubois Reviewed-by: Fabio Estevam Signed-off-by: Eduardo Valentin --- drivers/thermal/imx_thermal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 334d98be03b9..b1f82d64253e 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -604,7 +604,10 @@ static int imx_init_from_nvmem_cells(struct platform_device *pdev) ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val); if (ret) return ret; - imx_init_calib(pdev, val); + + ret = imx_init_calib(pdev, val); + if (ret) + return ret; ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val); if (ret) From 9bebf3485c6a365ef0b7e83443a707eda2abc78b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 2 May 2018 15:20:35 +0200 Subject: [PATCH 02/34] thermal: ti-soc-thermal: remove dead code Majority of this code (i.e. functions from ti-bandgap.c) has been introduced in May 2013 by commit eb982001dbd8 ("thermal: introduce TI SoC thermal driver"). Just remove it altogether (in case it is needed it can be easily resurrected from git repo). While at it fix incorrect "not used" comments. Tested-by: Keerthy Acked-by: Keerthy Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- .../thermal/ti-soc-thermal/dra752-bandgap.h | 68 ---- .../ti-soc-thermal/dra752-thermal-data.c | 65 --- .../ti-soc-thermal/omap3-thermal-data.c | 6 - .../ti-soc-thermal/omap4-thermal-data.c | 10 - .../thermal/ti-soc-thermal/omap4xxx-bandgap.h | 10 - .../ti-soc-thermal/omap5-thermal-data.c | 46 +-- .../thermal/ti-soc-thermal/omap5xxx-bandgap.h | 41 -- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 370 ------------------ drivers/thermal/ti-soc-thermal/ti-bandgap.h | 43 +- 9 files changed, 5 insertions(+), 654 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h index a31e4b5e82cd..9490cd63fa6a 100644 --- a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h @@ -54,56 +54,36 @@ #define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8 #define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154 #define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac -#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4 -#define DRA752_DTEMP_CORE_0_OFFSET 0x208 #define DRA752_DTEMP_CORE_1_OFFSET 0x20c #define DRA752_DTEMP_CORE_2_OFFSET 0x210 -#define DRA752_DTEMP_CORE_3_OFFSET 0x214 -#define DRA752_DTEMP_CORE_4_OFFSET 0x218 /* DRA752.iva register offsets */ #define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388 #define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398 #define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4 -#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4 -#define DRA752_DTEMP_IVA_0_OFFSET 0x3d0 #define DRA752_DTEMP_IVA_1_OFFSET 0x3d4 #define DRA752_DTEMP_IVA_2_OFFSET 0x3d8 -#define DRA752_DTEMP_IVA_3_OFFSET 0x3dc -#define DRA752_DTEMP_IVA_4_OFFSET 0x3e0 /* DRA752.mpu register offsets */ #define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4 #define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c #define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4 -#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc -#define DRA752_DTEMP_MPU_0_OFFSET 0x1e0 #define DRA752_DTEMP_MPU_1_OFFSET 0x1e4 #define DRA752_DTEMP_MPU_2_OFFSET 0x1e8 -#define DRA752_DTEMP_MPU_3_OFFSET 0x1ec -#define DRA752_DTEMP_MPU_4_OFFSET 0x1f0 /* DRA752.dspeve register offsets */ #define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384 #define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394 #define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0 -#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0 -#define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc #define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0 #define DRA752_DTEMP_DSPEVE_2_OFFSET 0x3c4 -#define DRA752_DTEMP_DSPEVE_3_OFFSET 0x3c8 -#define DRA752_DTEMP_DSPEVE_4_OFFSET 0x3cc /* DRA752.gpu register offsets */ #define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0 #define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150 #define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8 -#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0 -#define DRA752_DTEMP_GPU_0_OFFSET 0x1f4 #define DRA752_DTEMP_GPU_1_OFFSET 0x1f8 #define DRA752_DTEMP_GPU_2_OFFSET 0x1fc -#define DRA752_DTEMP_GPU_3_OFFSET 0x200 -#define DRA752_DTEMP_GPU_4_OFFSET 0x204 /** * Register bitfields for DRA752 @@ -114,7 +94,6 @@ */ /* DRA752.BANDGAP_STATUS_1 */ -#define DRA752_BANDGAP_STATUS_1_ALERT_MASK BIT(31) #define DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK BIT(5) #define DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK BIT(4) #define DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK BIT(3) @@ -125,10 +104,6 @@ /* DRA752.BANDGAP_CTRL_2 */ #define DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK BIT(22) #define DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK BIT(21) -#define DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK BIT(19) -#define DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK BIT(18) -#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK BIT(16) -#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK BIT(15) #define DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK BIT(3) #define DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK BIT(2) #define DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK BIT(1) @@ -141,17 +116,10 @@ #define DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK BIT(0) /* DRA752.BANDGAP_CTRL_1 */ -#define DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK (0x3 << 30) #define DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK (0x7 << 27) #define DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK BIT(23) #define DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK BIT(22) #define DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK BIT(21) -#define DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK BIT(20) -#define DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK BIT(19) -#define DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK BIT(18) -#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK BIT(17) -#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK BIT(16) -#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK BIT(15) #define DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK BIT(5) #define DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK BIT(4) #define DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK BIT(3) @@ -168,22 +136,6 @@ #define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16) #define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0) - -/* DRA752.BANDGAP_CUMUL_DTEMP_CORE */ -#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0) - -/* DRA752.BANDGAP_CUMUL_DTEMP_IVA */ -#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_MASK (0xffffffff << 0) - -/* DRA752.BANDGAP_CUMUL_DTEMP_MPU */ -#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_MASK (0xffffffff << 0) - -/* DRA752.BANDGAP_CUMUL_DTEMP_DSPEVE */ -#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_MASK (0xffffffff << 0) - -/* DRA752.BANDGAP_CUMUL_DTEMP_GPU */ -#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_MASK (0xffffffff << 0) - /** * Temperature limits and thresholds for DRA752 * @@ -202,10 +154,6 @@ /* bandgap clock limits */ #define DRA752_GPU_MAX_FREQ 1500000 #define DRA752_GPU_MIN_FREQ 1000000 -/* sensor limits */ -#define DRA752_GPU_MIN_TEMP -40000 -#define DRA752_GPU_MAX_TEMP 125000 -#define DRA752_GPU_HYST_VAL 5000 /* interrupts thresholds */ #define DRA752_GPU_T_HOT 800 #define DRA752_GPU_T_COLD 795 @@ -214,10 +162,6 @@ /* bandgap clock limits */ #define DRA752_MPU_MAX_FREQ 1500000 #define DRA752_MPU_MIN_FREQ 1000000 -/* sensor limits */ -#define DRA752_MPU_MIN_TEMP -40000 -#define DRA752_MPU_MAX_TEMP 125000 -#define DRA752_MPU_HYST_VAL 5000 /* interrupts thresholds */ #define DRA752_MPU_T_HOT 800 #define DRA752_MPU_T_COLD 795 @@ -226,10 +170,6 @@ /* bandgap clock limits */ #define DRA752_CORE_MAX_FREQ 1500000 #define DRA752_CORE_MIN_FREQ 1000000 -/* sensor limits */ -#define DRA752_CORE_MIN_TEMP -40000 -#define DRA752_CORE_MAX_TEMP 125000 -#define DRA752_CORE_HYST_VAL 5000 /* interrupts thresholds */ #define DRA752_CORE_T_HOT 800 #define DRA752_CORE_T_COLD 795 @@ -238,10 +178,6 @@ /* bandgap clock limits */ #define DRA752_DSPEVE_MAX_FREQ 1500000 #define DRA752_DSPEVE_MIN_FREQ 1000000 -/* sensor limits */ -#define DRA752_DSPEVE_MIN_TEMP -40000 -#define DRA752_DSPEVE_MAX_TEMP 125000 -#define DRA752_DSPEVE_HYST_VAL 5000 /* interrupts thresholds */ #define DRA752_DSPEVE_T_HOT 800 #define DRA752_DSPEVE_T_COLD 795 @@ -250,10 +186,6 @@ /* bandgap clock limits */ #define DRA752_IVA_MAX_FREQ 1500000 #define DRA752_IVA_MIN_FREQ 1000000 -/* sensor limits */ -#define DRA752_IVA_MIN_TEMP -40000 -#define DRA752_IVA_MAX_TEMP 125000 -#define DRA752_IVA_HYST_VAL 5000 /* interrupts thresholds */ #define DRA752_IVA_T_HOT 800 #define DRA752_IVA_T_COLD 795 diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c index 4167373327d9..33a3030aa3c0 100644 --- a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c @@ -41,24 +41,16 @@ dra752_core_temp_sensor_registers = { .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK, .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK, - .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK, .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK, - .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK, - .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK, .bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET, .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, - .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK, .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK, - .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET, - .ctrl_dtemp_0 = DRA752_DTEMP_CORE_0_OFFSET, .ctrl_dtemp_1 = DRA752_DTEMP_CORE_1_OFFSET, .ctrl_dtemp_2 = DRA752_DTEMP_CORE_2_OFFSET, - .ctrl_dtemp_3 = DRA752_DTEMP_CORE_3_OFFSET, - .ctrl_dtemp_4 = DRA752_DTEMP_CORE_4_OFFSET, .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET, }; @@ -74,24 +66,16 @@ dra752_iva_temp_sensor_registers = { .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET, .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK, .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK, - .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK, .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK, - .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK, - .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK, .bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET, .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, - .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK, .status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK, - .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET, - .ctrl_dtemp_0 = DRA752_DTEMP_IVA_0_OFFSET, .ctrl_dtemp_1 = DRA752_DTEMP_IVA_1_OFFSET, .ctrl_dtemp_2 = DRA752_DTEMP_IVA_2_OFFSET, - .ctrl_dtemp_3 = DRA752_DTEMP_IVA_3_OFFSET, - .ctrl_dtemp_4 = DRA752_DTEMP_IVA_4_OFFSET, .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET, }; @@ -107,24 +91,16 @@ dra752_mpu_temp_sensor_registers = { .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK, .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK, - .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK, .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK, - .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK, - .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK, .bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET, .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, - .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK, .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK, - .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET, - .ctrl_dtemp_0 = DRA752_DTEMP_MPU_0_OFFSET, .ctrl_dtemp_1 = DRA752_DTEMP_MPU_1_OFFSET, .ctrl_dtemp_2 = DRA752_DTEMP_MPU_2_OFFSET, - .ctrl_dtemp_3 = DRA752_DTEMP_MPU_3_OFFSET, - .ctrl_dtemp_4 = DRA752_DTEMP_MPU_4_OFFSET, .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET, }; @@ -140,24 +116,16 @@ dra752_dspeve_temp_sensor_registers = { .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET, .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK, .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK, - .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK, .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK, - .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK, - .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK, .bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET, .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, - .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK, .status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK, - .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET, - .ctrl_dtemp_0 = DRA752_DTEMP_DSPEVE_0_OFFSET, .ctrl_dtemp_1 = DRA752_DTEMP_DSPEVE_1_OFFSET, .ctrl_dtemp_2 = DRA752_DTEMP_DSPEVE_2_OFFSET, - .ctrl_dtemp_3 = DRA752_DTEMP_DSPEVE_3_OFFSET, - .ctrl_dtemp_4 = DRA752_DTEMP_DSPEVE_4_OFFSET, .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET, }; @@ -173,24 +141,16 @@ dra752_gpu_temp_sensor_registers = { .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK, .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK, - .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, .mask_counter_delay_mask = DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK, .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK, - .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK, - .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK, .bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET, .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, - .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK, .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK, - .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET, - .ctrl_dtemp_0 = DRA752_DTEMP_GPU_0_OFFSET, .ctrl_dtemp_1 = DRA752_DTEMP_GPU_1_OFFSET, .ctrl_dtemp_2 = DRA752_DTEMP_GPU_2_OFFSET, - .ctrl_dtemp_3 = DRA752_DTEMP_GPU_3_OFFSET, - .ctrl_dtemp_4 = DRA752_DTEMP_GPU_4_OFFSET, .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET, }; @@ -200,11 +160,6 @@ static struct temp_sensor_data dra752_mpu_temp_sensor_data = { .t_cold = DRA752_MPU_T_COLD, .min_freq = DRA752_MPU_MIN_FREQ, .max_freq = DRA752_MPU_MAX_FREQ, - .max_temp = DRA752_MPU_MAX_TEMP, - .min_temp = DRA752_MPU_MIN_TEMP, - .hyst_val = DRA752_MPU_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* Thresholds and limits for DRA752 GPU temperature sensor */ @@ -213,11 +168,6 @@ static struct temp_sensor_data dra752_gpu_temp_sensor_data = { .t_cold = DRA752_GPU_T_COLD, .min_freq = DRA752_GPU_MIN_FREQ, .max_freq = DRA752_GPU_MAX_FREQ, - .max_temp = DRA752_GPU_MAX_TEMP, - .min_temp = DRA752_GPU_MIN_TEMP, - .hyst_val = DRA752_GPU_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* Thresholds and limits for DRA752 CORE temperature sensor */ @@ -226,11 +176,6 @@ static struct temp_sensor_data dra752_core_temp_sensor_data = { .t_cold = DRA752_CORE_T_COLD, .min_freq = DRA752_CORE_MIN_FREQ, .max_freq = DRA752_CORE_MAX_FREQ, - .max_temp = DRA752_CORE_MAX_TEMP, - .min_temp = DRA752_CORE_MIN_TEMP, - .hyst_val = DRA752_CORE_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* Thresholds and limits for DRA752 DSPEVE temperature sensor */ @@ -239,11 +184,6 @@ static struct temp_sensor_data dra752_dspeve_temp_sensor_data = { .t_cold = DRA752_DSPEVE_T_COLD, .min_freq = DRA752_DSPEVE_MIN_FREQ, .max_freq = DRA752_DSPEVE_MAX_FREQ, - .max_temp = DRA752_DSPEVE_MAX_TEMP, - .min_temp = DRA752_DSPEVE_MIN_TEMP, - .hyst_val = DRA752_DSPEVE_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* Thresholds and limits for DRA752 IVA temperature sensor */ @@ -252,11 +192,6 @@ static struct temp_sensor_data dra752_iva_temp_sensor_data = { .t_cold = DRA752_IVA_T_COLD, .min_freq = DRA752_IVA_MIN_FREQ, .max_freq = DRA752_IVA_MAX_FREQ, - .max_temp = DRA752_IVA_MAX_TEMP, - .min_temp = DRA752_IVA_MIN_TEMP, - .hyst_val = DRA752_IVA_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* diff --git a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c index c6d217913dd1..f5366807daf0 100644 --- a/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap3-thermal-data.c @@ -48,9 +48,6 @@ omap34xx_mpu_temp_sensor_registers = { static struct temp_sensor_data omap34xx_mpu_temp_sensor_data = { .min_freq = 32768, .max_freq = 32768, - .max_temp = 125000, - .min_temp = -40000, - .hyst_val = 5000, }; /* @@ -119,9 +116,6 @@ omap36xx_mpu_temp_sensor_registers = { static struct temp_sensor_data omap36xx_mpu_temp_sensor_data = { .min_freq = 32768, .max_freq = 32768, - .max_temp = 125000, - .min_temp = -40000, - .hyst_val = 5000, }; /* diff --git a/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c index fd1113360603..c12211eaaac4 100644 --- a/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c @@ -42,9 +42,6 @@ omap4430_mpu_temp_sensor_registers = { static struct temp_sensor_data omap4430_mpu_temp_sensor_data = { .min_freq = OMAP4430_MIN_FREQ, .max_freq = OMAP4430_MAX_FREQ, - .max_temp = OMAP4430_MAX_TEMP, - .min_temp = OMAP4430_MIN_TEMP, - .hyst_val = OMAP4430_HYST_VAL, }; /* @@ -121,8 +118,6 @@ omap4460_mpu_temp_sensor_registers = { .tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK, .bgap_status = OMAP4460_BGAP_STATUS_OFFSET, - .status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK, - .status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK, .status_hot_mask = OMAP4460_HOT_FLAG_MASK, .status_cold_mask = OMAP4460_COLD_FLAG_MASK, @@ -137,11 +132,6 @@ static struct temp_sensor_data omap4460_mpu_temp_sensor_data = { .t_cold = OMAP4460_T_COLD, .min_freq = OMAP4460_MIN_FREQ, .max_freq = OMAP4460_MAX_FREQ, - .max_temp = OMAP4460_MAX_TEMP, - .min_temp = OMAP4460_MIN_TEMP, - .hyst_val = OMAP4460_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* diff --git a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h index 6f2de3a3356d..b87c8659ec60 100644 --- a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h @@ -73,10 +73,6 @@ /* bandgap clock limits (no control on 4430) */ #define OMAP4430_MAX_FREQ 32768 #define OMAP4430_MIN_FREQ 32768 -/* sensor limits */ -#define OMAP4430_MIN_TEMP -40000 -#define OMAP4430_MAX_TEMP 125000 -#define OMAP4430_HYST_VAL 5000 /** * *** OMAP4460 *** Applicable for OMAP4470 @@ -143,8 +139,6 @@ #define OMAP4460_TSHUT_COLD_MASK (0x3ff << 0) /* OMAP4460.BANDGAP_STATUS bits */ -#define OMAP4460_CLEAN_STOP_MASK BIT(3) -#define OMAP4460_BGAP_ALERT_MASK BIT(2) #define OMAP4460_HOT_FLAG_MASK BIT(1) #define OMAP4460_COLD_FLAG_MASK BIT(0) @@ -162,10 +156,6 @@ /* bandgap clock limits */ #define OMAP4460_MAX_FREQ 1500000 #define OMAP4460_MIN_FREQ 1000000 -/* sensor limits */ -#define OMAP4460_MIN_TEMP -40000 -#define OMAP4460_MAX_TEMP 123000 -#define OMAP4460_HYST_VAL 5000 /* interrupts thresholds */ #define OMAP4460_TSHUT_HOT 900 /* 122 deg C */ #define OMAP4460_TSHUT_COLD 895 /* 100 deg C */ diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c index 6ac037098b52..8191bae834de 100644 --- a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c @@ -38,12 +38,8 @@ omap5430_mpu_temp_sensor_registers = { .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET, .mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK, .mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK, - .mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK, .mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK, .mask_freeze_mask = OMAP5430_MASK_FREEZE_MPU_MASK, - .mask_clear_mask = OMAP5430_MASK_CLEAR_MPU_MASK, - .mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_MPU_MASK, - .bgap_counter = OMAP5430_BGAP_CTRL_OFFSET, .counter_mask = OMAP5430_COUNTER_MASK, @@ -57,17 +53,11 @@ omap5430_mpu_temp_sensor_registers = { .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK, .bgap_status = OMAP5430_BGAP_STATUS_OFFSET, - .status_clean_stop_mask = 0x0, - .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK, .status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK, .status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK, - .bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_MPU_OFFSET, - .ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_MPU_0_OFFSET, .ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_MPU_1_OFFSET, .ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_MPU_2_OFFSET, - .ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_MPU_3_OFFSET, - .ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_MPU_4_OFFSET, .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU, }; @@ -84,11 +74,8 @@ omap5430_gpu_temp_sensor_registers = { .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET, .mask_hot_mask = OMAP5430_MASK_HOT_GPU_MASK, .mask_cold_mask = OMAP5430_MASK_COLD_GPU_MASK, - .mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK, .mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK, .mask_freeze_mask = OMAP5430_MASK_FREEZE_GPU_MASK, - .mask_clear_mask = OMAP5430_MASK_CLEAR_GPU_MASK, - .mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_GPU_MASK, .bgap_counter = OMAP5430_BGAP_CTRL_OFFSET, .counter_mask = OMAP5430_COUNTER_MASK, @@ -102,17 +89,11 @@ omap5430_gpu_temp_sensor_registers = { .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK, .bgap_status = OMAP5430_BGAP_STATUS_OFFSET, - .status_clean_stop_mask = 0x0, - .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK, .status_hot_mask = OMAP5430_HOT_GPU_FLAG_MASK, .status_cold_mask = OMAP5430_COLD_GPU_FLAG_MASK, - .bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_GPU_OFFSET, - .ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_GPU_0_OFFSET, .ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_GPU_1_OFFSET, .ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_GPU_2_OFFSET, - .ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_GPU_3_OFFSET, - .ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_GPU_4_OFFSET, .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU, }; @@ -130,11 +111,8 @@ omap5430_core_temp_sensor_registers = { .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET, .mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK, .mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK, - .mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK, .mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK, .mask_freeze_mask = OMAP5430_MASK_FREEZE_CORE_MASK, - .mask_clear_mask = OMAP5430_MASK_CLEAR_CORE_MASK, - .mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_CORE_MASK, .bgap_counter = OMAP5430_BGAP_CTRL_OFFSET, .counter_mask = OMAP5430_COUNTER_MASK, @@ -148,17 +126,11 @@ omap5430_core_temp_sensor_registers = { .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK, .bgap_status = OMAP5430_BGAP_STATUS_OFFSET, - .status_clean_stop_mask = 0x0, - .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK, .status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK, .status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK, - .bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_CORE_OFFSET, - .ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_CORE_0_OFFSET, .ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_CORE_1_OFFSET, .ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_CORE_2_OFFSET, - .ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_CORE_3_OFFSET, - .ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_CORE_4_OFFSET, .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE, }; @@ -171,11 +143,6 @@ static struct temp_sensor_data omap5430_mpu_temp_sensor_data = { .t_cold = OMAP5430_MPU_T_COLD, .min_freq = OMAP5430_MPU_MIN_FREQ, .max_freq = OMAP5430_MPU_MAX_FREQ, - .max_temp = OMAP5430_MPU_MAX_TEMP, - .min_temp = OMAP5430_MPU_MIN_TEMP, - .hyst_val = OMAP5430_MPU_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* Thresholds and limits for OMAP5430 GPU temperature sensor */ @@ -186,11 +153,6 @@ static struct temp_sensor_data omap5430_gpu_temp_sensor_data = { .t_cold = OMAP5430_GPU_T_COLD, .min_freq = OMAP5430_GPU_MIN_FREQ, .max_freq = OMAP5430_GPU_MAX_FREQ, - .max_temp = OMAP5430_GPU_MAX_TEMP, - .min_temp = OMAP5430_GPU_MIN_TEMP, - .hyst_val = OMAP5430_GPU_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* Thresholds and limits for OMAP5430 CORE temperature sensor */ @@ -201,11 +163,6 @@ static struct temp_sensor_data omap5430_core_temp_sensor_data = { .t_cold = OMAP5430_CORE_T_COLD, .min_freq = OMAP5430_CORE_MIN_FREQ, .max_freq = OMAP5430_CORE_MAX_FREQ, - .max_temp = OMAP5430_CORE_MAX_TEMP, - .min_temp = OMAP5430_CORE_MIN_TEMP, - .hyst_val = OMAP5430_CORE_HYST_VAL, - .update_int1 = 1000, - .update_int2 = 2000, }; /* @@ -319,8 +276,7 @@ const struct ti_bandgap_data omap5430_data = { TI_BANDGAP_FEATURE_FREEZE_BIT | TI_BANDGAP_FEATURE_TALERT | TI_BANDGAP_FEATURE_COUNTER_DELAY | - TI_BANDGAP_FEATURE_HISTORY_BUFFER | - TI_BANDGAP_FEATURE_ERRATA_813, + TI_BANDGAP_FEATURE_HISTORY_BUFFER, .fclock_name = "l3instr_ts_gclk_div", .div_ck_name = "l3instr_ts_gclk_div", .conv_table = omap5430_adc_to_temp, diff --git a/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h index 400b55dffadd..9096403b74b0 100644 --- a/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h @@ -44,36 +44,24 @@ #define OMAP5430_TEMP_SENSOR_GPU_OFFSET 0x150 #define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET 0x1A8 #define OMAP5430_BGAP_TSHUT_GPU_OFFSET 0x1B4 -#define OMAP5430_BGAP_CUMUL_DTEMP_GPU_OFFSET 0x1C0 -#define OMAP5430_BGAP_DTEMP_GPU_0_OFFSET 0x1F4 #define OMAP5430_BGAP_DTEMP_GPU_1_OFFSET 0x1F8 #define OMAP5430_BGAP_DTEMP_GPU_2_OFFSET 0x1FC -#define OMAP5430_BGAP_DTEMP_GPU_3_OFFSET 0x200 -#define OMAP5430_BGAP_DTEMP_GPU_4_OFFSET 0x204 /* OMAP5430.MPU register offsets */ #define OMAP5430_FUSE_OPP_BGAP_MPU 0x4 #define OMAP5430_TEMP_SENSOR_MPU_OFFSET 0x14C #define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET 0x1A4 #define OMAP5430_BGAP_TSHUT_MPU_OFFSET 0x1B0 -#define OMAP5430_BGAP_CUMUL_DTEMP_MPU_OFFSET 0x1BC -#define OMAP5430_BGAP_DTEMP_MPU_0_OFFSET 0x1E0 #define OMAP5430_BGAP_DTEMP_MPU_1_OFFSET 0x1E4 #define OMAP5430_BGAP_DTEMP_MPU_2_OFFSET 0x1E8 -#define OMAP5430_BGAP_DTEMP_MPU_3_OFFSET 0x1EC -#define OMAP5430_BGAP_DTEMP_MPU_4_OFFSET 0x1F0 /* OMAP5430.MPU register offsets */ #define OMAP5430_FUSE_OPP_BGAP_CORE 0x8 #define OMAP5430_TEMP_SENSOR_CORE_OFFSET 0x154 #define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET 0x1AC #define OMAP5430_BGAP_TSHUT_CORE_OFFSET 0x1B8 -#define OMAP5430_BGAP_CUMUL_DTEMP_CORE_OFFSET 0x1C4 -#define OMAP5430_BGAP_DTEMP_CORE_0_OFFSET 0x208 #define OMAP5430_BGAP_DTEMP_CORE_1_OFFSET 0x20C #define OMAP5430_BGAP_DTEMP_CORE_2_OFFSET 0x210 -#define OMAP5430_BGAP_DTEMP_CORE_3_OFFSET 0x214 -#define OMAP5430_BGAP_DTEMP_CORE_4_OFFSET 0x218 /* OMAP5430.common register offsets */ #define OMAP5430_BGAP_CTRL_OFFSET 0x1A0 @@ -94,17 +82,10 @@ #define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0) /* OMAP5430.BANDGAP_CTRL */ -#define OMAP5430_MASK_SIDLEMODE_MASK (0x3 << 30) #define OMAP5430_MASK_COUNTER_DELAY_MASK (0x7 << 27) #define OMAP5430_MASK_FREEZE_CORE_MASK BIT(23) #define OMAP5430_MASK_FREEZE_GPU_MASK BIT(22) #define OMAP5430_MASK_FREEZE_MPU_MASK BIT(21) -#define OMAP5430_MASK_CLEAR_CORE_MASK BIT(20) -#define OMAP5430_MASK_CLEAR_GPU_MASK BIT(19) -#define OMAP5430_MASK_CLEAR_MPU_MASK BIT(18) -#define OMAP5430_MASK_CLEAR_ACCUM_CORE_MASK BIT(17) -#define OMAP5430_MASK_CLEAR_ACCUM_GPU_MASK BIT(16) -#define OMAP5430_MASK_CLEAR_ACCUM_MPU_MASK BIT(15) #define OMAP5430_MASK_HOT_CORE_MASK BIT(5) #define OMAP5430_MASK_COLD_CORE_MASK BIT(4) #define OMAP5430_MASK_HOT_GPU_MASK BIT(3) @@ -123,17 +104,7 @@ #define OMAP5430_TSHUT_HOT_MASK (0x3ff << 16) #define OMAP5430_TSHUT_COLD_MASK (0x3ff << 0) -/* OMAP5430.BANDGAP_CUMUL_DTEMP_MPU */ -#define OMAP5430_CUMUL_DTEMP_MPU_MASK (0xffffffff << 0) - -/* OMAP5430.BANDGAP_CUMUL_DTEMP_GPU */ -#define OMAP5430_CUMUL_DTEMP_GPU_MASK (0xffffffff << 0) - -/* OMAP5430.BANDGAP_CUMUL_DTEMP_CORE */ -#define OMAP5430_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0) - /* OMAP5430.BANDGAP_STATUS */ -#define OMAP5430_BGAP_ALERT_MASK BIT(31) #define OMAP5430_HOT_CORE_FLAG_MASK BIT(5) #define OMAP5430_COLD_CORE_FLAG_MASK BIT(4) #define OMAP5430_HOT_GPU_FLAG_MASK BIT(3) @@ -159,10 +130,6 @@ /* bandgap clock limits */ #define OMAP5430_GPU_MAX_FREQ 1500000 #define OMAP5430_GPU_MIN_FREQ 1000000 -/* sensor limits */ -#define OMAP5430_GPU_MIN_TEMP -40000 -#define OMAP5430_GPU_MAX_TEMP 125000 -#define OMAP5430_GPU_HYST_VAL 5000 /* interrupts thresholds */ #define OMAP5430_GPU_TSHUT_HOT 915 #define OMAP5430_GPU_TSHUT_COLD 900 @@ -173,10 +140,6 @@ /* bandgap clock limits */ #define OMAP5430_MPU_MAX_FREQ 1500000 #define OMAP5430_MPU_MIN_FREQ 1000000 -/* sensor limits */ -#define OMAP5430_MPU_MIN_TEMP -40000 -#define OMAP5430_MPU_MAX_TEMP 125000 -#define OMAP5430_MPU_HYST_VAL 5000 /* interrupts thresholds */ #define OMAP5430_MPU_TSHUT_HOT 915 #define OMAP5430_MPU_TSHUT_COLD 900 @@ -187,10 +150,6 @@ /* bandgap clock limits */ #define OMAP5430_CORE_MAX_FREQ 1500000 #define OMAP5430_CORE_MIN_FREQ 1000000 -/* sensor limits */ -#define OMAP5430_CORE_MIN_TEMP -40000 -#define OMAP5430_CORE_MAX_TEMP 125000 -#define OMAP5430_CORE_HYST_VAL 5000 /* interrupts thresholds */ #define OMAP5430_CORE_TSHUT_HOT 915 #define OMAP5430_CORE_TSHUT_COLD 900 diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 696ab3046b87..097328d8e943 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -305,217 +305,6 @@ int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t) return 0; } -/** - * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale - * @bgp: struct ti_bandgap pointer - * @temp: value in mCelsius - * @adc: address where to write the resulting temperature in ADC representation - * - * Simple conversion from mCelsius to ADC values. In case the temp value - * is out of the ADC conv table range, it returns -ERANGE, 0 on success. - * The conversion table is indexed by the ADC values. - * - * Return: 0 if conversion was successful, else -ERANGE in case the @temp - * argument is out of the ADC conv table range. - */ -static -int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc) -{ - const struct ti_bandgap_data *conf = bgp->conf; - const int *conv_table = bgp->conf->conv_table; - int high, low, mid; - - low = 0; - high = conf->adc_end_val - conf->adc_start_val; - mid = (high + low) / 2; - - if (temp < conv_table[low] || temp > conv_table[high]) - return -ERANGE; - - while (low < high) { - if (temp < conv_table[mid]) - high = mid - 1; - else - low = mid + 1; - mid = (low + high) / 2; - } - - *adc = conf->adc_start_val + low; - return 0; -} - -/** - * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value - * @bgp: struct ti_bandgap pointer - * @adc_val: temperature value in ADC representation - * @hyst_val: hysteresis value in mCelsius - * @sum: address where to write the resulting temperature (in ADC scale) - * - * Adds an hysteresis value (in mCelsius) to a ADC temperature value. - * - * Return: 0 on success, -ERANGE otherwise. - */ -static -int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val, - u32 *sum) -{ - int temp, ret; - - /* - * Need to add in the mcelsius domain, so we have a temperature - * the conv_table range - */ - ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp); - if (ret < 0) - return ret; - - temp += hyst_val; - - ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum); - return ret; -} - -/*** Helper functions handling device Alert/Shutdown signals ***/ - -/** - * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold - * @bgp: struct ti_bandgap pointer - * @id: bandgap sensor id - * @t_hot: hot temperature value to trigger alert signal - * @t_cold: cold temperature value to trigger alert signal - * - * Checks the requested t_hot and t_cold values and configures the IRQ event - * masks accordingly. Call this function only if bandgap features HAS(TALERT). - */ -static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id, - u32 t_hot, u32 t_cold) -{ - struct temp_sensor_registers *tsr; - u32 temp, reg_val; - - /* Read the current on die temperature */ - temp = ti_bandgap_read_temp(bgp, id); - - tsr = bgp->conf->sensors[id].registers; - reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); - - if (temp < t_hot) - reg_val |= tsr->mask_hot_mask; - else - reg_val &= ~tsr->mask_hot_mask; - - if (t_cold < temp) - reg_val |= tsr->mask_cold_mask; - else - reg_val &= ~tsr->mask_cold_mask; - ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl); -} - -/** - * ti_bandgap_update_alert_threshold() - sequence to update thresholds - * @bgp: struct ti_bandgap pointer - * @id: bandgap sensor id - * @val: value (ADC) of a new threshold - * @hot: desired threshold to be updated. true if threshold hot, false if - * threshold cold - * - * It will program the required thresholds (hot and cold) for TALERT signal. - * This function can be used to update t_hot or t_cold, depending on @hot value. - * It checks the resulting t_hot and t_cold values, based on the new passed @val - * and configures the thresholds so that t_hot is always greater than t_cold. - * Call this function only if bandgap features HAS(TALERT). - * - * Return: 0 if no error, else corresponding error - */ -static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id, - int val, bool hot) -{ - struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data; - struct temp_sensor_registers *tsr; - u32 thresh_val, reg_val, t_hot, t_cold, ctrl; - int err = 0; - - tsr = bgp->conf->sensors[id].registers; - - /* obtain the current value */ - thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold); - t_cold = (thresh_val & tsr->threshold_tcold_mask) >> - __ffs(tsr->threshold_tcold_mask); - t_hot = (thresh_val & tsr->threshold_thot_mask) >> - __ffs(tsr->threshold_thot_mask); - if (hot) - t_hot = val; - else - t_cold = val; - - if (t_cold > t_hot) { - if (hot) - err = ti_bandgap_add_hyst(bgp, t_hot, - -ts_data->hyst_val, - &t_cold); - else - err = ti_bandgap_add_hyst(bgp, t_cold, - ts_data->hyst_val, - &t_hot); - } - - /* write the new threshold values */ - reg_val = thresh_val & - ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask); - reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) | - (t_cold << __ffs(tsr->threshold_tcold_mask)); - - /** - * Errata i813: - * Spurious Thermal Alert: Talert can happen randomly while the device - * remains under the temperature limit defined for this event to trig. - * This spurious event is caused by a incorrect re-synchronization - * between clock domains. The comparison between configured threshold - * and current temperature value can happen while the value is - * transitioning (metastable), thus causing inappropriate event - * generation. No spurious event occurs as long as the threshold value - * stays unchanged. Spurious event can be generated while a thermal - * alert threshold is modified in - * CONTROL_BANDGAP_THRESHOLD_MPU/GPU/CORE/DSPEVE/IVA_n. - */ - - if (TI_BANDGAP_HAS(bgp, ERRATA_813)) { - /* Mask t_hot and t_cold events at the IP Level */ - ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); - - if (hot) - ctrl &= ~tsr->mask_hot_mask; - else - ctrl &= ~tsr->mask_cold_mask; - - ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl); - } - - /* Write the threshold value */ - ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold); - - if (TI_BANDGAP_HAS(bgp, ERRATA_813)) { - /* Unmask t_hot and t_cold events at the IP Level */ - ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); - if (hot) - ctrl |= tsr->mask_hot_mask; - else - ctrl |= tsr->mask_cold_mask; - - ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl); - } - - if (err) { - dev_err(bgp->dev, "failed to reprogram thot threshold\n"); - err = -EIO; - goto exit; - } - - ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold); -exit: - return err; -} - /** * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap * @bgp: struct ti_bandgap pointer @@ -543,165 +332,6 @@ static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) return 0; } -/** - * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot - * @bgp: struct ti_bandgap pointer - * @id: bandgap sensor id - * @val: value (mCelsius) of a new threshold - * @hot: desired threshold to be updated. true if threshold hot, false if - * threshold cold - * - * It will update the required thresholds (hot and cold) for TALERT signal. - * This function can be used to update t_hot or t_cold, depending on @hot value. - * Validates the mCelsius range and update the requested threshold. - * Call this function only if bandgap features HAS(TALERT). - * - * Return: 0 if no error, else corresponding error value. - */ -static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val, - bool hot) -{ - struct temp_sensor_data *ts_data; - struct temp_sensor_registers *tsr; - u32 adc_val; - int ret; - - ret = ti_bandgap_validate(bgp, id); - if (ret) - return ret; - - if (!TI_BANDGAP_HAS(bgp, TALERT)) - return -ENOTSUPP; - - ts_data = bgp->conf->sensors[id].ts_data; - tsr = bgp->conf->sensors[id].registers; - if (hot) { - if (val < ts_data->min_temp + ts_data->hyst_val) - ret = -EINVAL; - } else { - if (val > ts_data->max_temp + ts_data->hyst_val) - ret = -EINVAL; - } - - if (ret) - return ret; - - ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val); - if (ret < 0) - return ret; - - spin_lock(&bgp->lock); - ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot); - spin_unlock(&bgp->lock); - return ret; -} - -/** - * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot - * @bgp: struct ti_bandgap pointer - * @id: bandgap sensor id - * @val: value (mCelsius) of a threshold - * @hot: desired threshold to be read. true if threshold hot, false if - * threshold cold - * - * It will fetch the required thresholds (hot and cold) for TALERT signal. - * This function can be used to read t_hot or t_cold, depending on @hot value. - * Call this function only if bandgap features HAS(TALERT). - * - * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the - * corresponding error value if some operation fails. - */ -static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id, - int *val, bool hot) -{ - struct temp_sensor_registers *tsr; - u32 temp, mask; - int ret = 0; - - ret = ti_bandgap_validate(bgp, id); - if (ret) - goto exit; - - if (!TI_BANDGAP_HAS(bgp, TALERT)) { - ret = -ENOTSUPP; - goto exit; - } - - tsr = bgp->conf->sensors[id].registers; - if (hot) - mask = tsr->threshold_thot_mask; - else - mask = tsr->threshold_tcold_mask; - - temp = ti_bandgap_readl(bgp, tsr->bgap_threshold); - temp = (temp & mask) >> __ffs(mask); - ret = ti_bandgap_adc_to_mcelsius(bgp, temp, &temp); - if (ret) { - dev_err(bgp->dev, "failed to read thot\n"); - ret = -EIO; - goto exit; - } - - *val = temp; - -exit: - return ret; -} - -/*** Exposed APIs ***/ - -/** - * ti_bandgap_read_thot() - reads sensor current thot - * @bgp: pointer to bandgap instance - * @id: sensor id - * @thot: resulting current thot value - * - * Return: 0 on success or the proper error code - */ -int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot) -{ - return _ti_bandgap_read_threshold(bgp, id, thot, true); -} - -/** - * ti_bandgap_write_thot() - sets sensor current thot - * @bgp: pointer to bandgap instance - * @id: sensor id - * @val: desired thot value - * - * Return: 0 on success or the proper error code - */ -int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val) -{ - return _ti_bandgap_write_threshold(bgp, id, val, true); -} - -/** - * ti_bandgap_read_tcold() - reads sensor current tcold - * @bgp: pointer to bandgap instance - * @id: sensor id - * @tcold: resulting current tcold value - * - * Return: 0 on success or the proper error code - */ -int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold) -{ - return _ti_bandgap_read_threshold(bgp, id, tcold, false); -} - -/** - * ti_bandgap_write_tcold() - sets the sensor tcold - * @bgp: pointer to bandgap instance - * @id: sensor id - * @val: desired tcold value - * - * Return: 0 on success or the proper error code - */ -int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val) -{ - return _ti_bandgap_write_threshold(bgp, id, val, false); -} - /** * ti_bandgap_read_counter() - read the sensor counter * @bgp: pointer to bandgap instance diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index 209c664c2823..68d39ad43241 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h @@ -78,11 +78,8 @@ * @bgap_mask_ctrl: BANDGAP_MASK_CTRL register offset * @mask_hot_mask: mask to bandgap_mask_ctrl.mask_hot * @mask_cold_mask: mask to bandgap_mask_ctrl.mask_cold - * @mask_sidlemode_mask: mask to bandgap_mask_ctrl.mask_sidlemode * @mask_counter_delay_mask: mask to bandgap_mask_ctrl.mask_counter_delay * @mask_freeze_mask: mask to bandgap_mask_ctrl.mask_free - * @mask_clear_mask: mask to bandgap_mask_ctrl.mask_clear - * @mask_clear_accum_mask: mask to bandgap_mask_ctrl.mask_clear_accum * @bgap_mode_ctrl: BANDGAP_MODE_CTRL register offset * @mode_ctrl_mask: mask to bandgap_mode_ctrl.mode_ctrl * @bgap_counter: BANDGAP_COUNTER register offset @@ -91,21 +88,13 @@ * @threshold_thot_mask: mask to bandgap_threhold.thot * @threshold_tcold_mask: mask to bandgap_threhold.tcold * @tshut_threshold: TSHUT_THRESHOLD register offset (TSHUT thresholds) - * @tshut_efuse_mask: mask to tshut_threshold.tshut_efuse - * @tshut_efuse_shift: shift to tshut_threshold.tshut_efuse * @tshut_hot_mask: mask to tshut_threhold.thot * @tshut_cold_mask: mask to tshut_threhold.thot * @bgap_status: BANDGAP_STATUS register offset - * @status_clean_stop_mask: mask to bandgap_status.clean_stop - * @status_bgap_alert_mask: mask to bandgap_status.bandgap_alert * @status_hot_mask: mask to bandgap_status.hot * @status_cold_mask: mask to bandgap_status.cold - * @bgap_cumul_dtemp: BANDGAP_CUMUL_DTEMP register offset - * @ctrl_dtemp_0: CTRL_DTEMP0 register offset * @ctrl_dtemp_1: CTRL_DTEMP1 register offset * @ctrl_dtemp_2: CTRL_DTEMP2 register offset - * @ctrl_dtemp_3: CTRL_DTEMP3 register offset - * @ctrl_dtemp_4: CTRL_DTEMP4 register offset * @bgap_efuse: BANDGAP_EFUSE register offset * * The register offsets and bitfields might change across @@ -121,17 +110,14 @@ struct temp_sensor_registers { u32 temp_sensor_ctrl; u32 bgap_tempsoff_mask; u32 bgap_soc_mask; - u32 bgap_eocz_mask; /* not used: but needs revisit */ + u32 bgap_eocz_mask; u32 bgap_dtemp_mask; u32 bgap_mask_ctrl; u32 mask_hot_mask; u32 mask_cold_mask; - u32 mask_sidlemode_mask; /* not used: but may be needed for pm */ u32 mask_counter_delay_mask; u32 mask_freeze_mask; - u32 mask_clear_mask; /* not used: but needed for trending */ - u32 mask_clear_accum_mask; /* not used: but needed for trending */ u32 bgap_mode_ctrl; u32 mode_ctrl_mask; @@ -144,23 +130,15 @@ struct temp_sensor_registers { u32 threshold_tcold_mask; u32 tshut_threshold; - u32 tshut_efuse_mask; /* not used */ - u32 tshut_efuse_shift; /* not used */ u32 tshut_hot_mask; u32 tshut_cold_mask; u32 bgap_status; - u32 status_clean_stop_mask; /* not used: but needed for trending */ - u32 status_bgap_alert_mask; /* not used */ u32 status_hot_mask; u32 status_cold_mask; - u32 bgap_cumul_dtemp; /* not used: but needed for trending */ - u32 ctrl_dtemp_0; /* not used: but needed for trending */ - u32 ctrl_dtemp_1; /* not used: but needed for trending */ - u32 ctrl_dtemp_2; /* not used: but needed for trending */ - u32 ctrl_dtemp_3; /* not used: but needed for trending */ - u32 ctrl_dtemp_4; /* not used: but needed for trending */ + u32 ctrl_dtemp_1; + u32 ctrl_dtemp_2; u32 bgap_efuse; }; @@ -172,11 +150,6 @@ struct temp_sensor_registers { * @t_cold: temperature to trigger a thermal alert (low initial value) * @min_freq: sensor minimum clock rate * @max_freq: sensor maximum clock rate - * @max_temp: sensor maximum temperature - * @min_temp: sensor minimum temperature - * @hyst_val: temperature hysteresis considered while converting ADC values - * @update_int1: update interval - * @update_int2: update interval * * This data structure will hold the required thresholds and temperature limits * for a specific temperature sensor, like shutdown temperature, alert @@ -189,11 +162,6 @@ struct temp_sensor_data { u32 t_cold; u32 min_freq; u32 max_freq; - int max_temp; - int min_temp; - int hyst_val; - u32 update_int1; /* not used */ - u32 update_int2; /* not used */ }; struct ti_bandgap_data; @@ -316,8 +284,6 @@ struct ti_temp_sensor { * * TI_BANDGAP_FEATURE_ERRATA_814 - used to workaorund when the bandgap device * has Errata 814 - * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device - * has Errata 813 * TI_BANDGAP_FEATURE_UNRELIABLE - used when the sensor readings are too * inaccurate. * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a @@ -334,8 +300,7 @@ struct ti_temp_sensor { #define TI_BANDGAP_FEATURE_COUNTER_DELAY BIT(8) #define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9) #define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10) -#define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11) -#define TI_BANDGAP_FEATURE_UNRELIABLE BIT(12) +#define TI_BANDGAP_FEATURE_UNRELIABLE BIT(11) #define TI_BANDGAP_HAS(b, f) \ ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f) From 8d98761a6fc1eeee7232471c5285665fc7ecaa23 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:44 +0200 Subject: [PATCH 03/34] thermal: armada: add a function that sanitizes the thermal zone name Thermal zone names must follow certain rules imposed by the framework. They are limited in length and shall not have any hyphen '-'. This is done in a separate function for future use in another location. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 4c275ec10ac5..4c88d70f09e5 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -70,6 +70,7 @@ struct armada_thermal_priv { void __iomem *status; void __iomem *control0; void __iomem *control1; + char zone_name[THERMAL_NAME_LENGTH]; struct armada_thermal_data *data; }; @@ -353,6 +354,37 @@ static const struct of_device_id armada_thermal_id_table[] = { }; MODULE_DEVICE_TABLE(of, armada_thermal_id_table); +static void armada_set_sane_name(struct platform_device *pdev, + struct armada_thermal_priv *priv) +{ + const char *name = dev_name(&pdev->dev); + char *insane_char; + + if (strlen(name) > THERMAL_NAME_LENGTH) { + /* + * When inside a system controller, the device name has the + * form: f06f8000.system-controller:ap-thermal so stripping + * after the ':' should give us a shorter but meaningful name. + */ + name = strrchr(name, ':'); + if (!name) + name = "armada_thermal"; + else + name++; + } + + /* Save the name locally */ + strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1); + priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0'; + + /* Then check there are no '-' or hwmon core will complain */ + do { + insane_char = strpbrk(priv->zone_name, "-"); + if (insane_char) + *insane_char = '_'; + } while (insane_char); +} + static int armada_thermal_probe(struct platform_device *pdev) { void __iomem *control = NULL; @@ -381,6 +413,9 @@ static int armada_thermal_probe(struct platform_device *pdev) priv->data = (struct armada_thermal_data *)match->data; + /* Ensure device name is correct for the thermal core */ + armada_set_sane_name(pdev, priv); + /* * Legacy DT bindings only described "control1" register (also referred * as "control MSB" on old documentation). New bindings cover @@ -402,7 +437,7 @@ static int armada_thermal_probe(struct platform_device *pdev) priv->data->init_sensor(pdev, priv); - thermal = thermal_zone_device_register(dev_name(&pdev->dev), 0, 0, priv, + thermal = thermal_zone_device_register(priv->zone_name, 0, 0, priv, &ops, NULL, 0, 0); if (IS_ERR(thermal)) { dev_err(&pdev->dev, From 931d3c5db42c935c7fcf119e844176ca5dcae326 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:45 +0200 Subject: [PATCH 04/34] thermal: armada: remove useless register accesses Prepare the migration to use regmaps by first simplifying the initialization functions: avoid unnecessary write/read cycles on configuration registers. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 4c88d70f09e5..de1d1c6b1975 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -103,16 +103,13 @@ static void armadaxp_init_sensor(struct platform_device *pdev, reg = readl_relaxed(priv->control1); reg |= PMU_TDC0_OTF_CAL_MASK; - writel(reg, priv->control1); /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); - writel(reg, priv->control1); /* Reset the sensor */ - reg = readl_relaxed(priv->control1); - writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1); + reg |= PMU_TDC0_SW_RST_MASK; writel(reg, priv->control1); @@ -129,14 +126,13 @@ static void armada370_init_sensor(struct platform_device *pdev, reg = readl_relaxed(priv->control1); reg |= PMU_TDC0_OTF_CAL_MASK; - writel(reg, priv->control1); /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); - writel(reg, priv->control1); reg &= ~PMU_TDC0_START_CAL_MASK; + writel(reg, priv->control1); msleep(10); From c5d7d57e6892e1613157c89c22b13441f9d2ddf5 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:46 +0200 Subject: [PATCH 05/34] thermal: armada: remove misleading comments On older versions of this thermal IP, TSEN referred as the internal sensor in the thermal IP while EXT_TSEN referred as sensors outside of this IP, ie in the CPUs most of the time. The bit names in the specifications do not follow this rule anymore, so remove these comments that are misleading. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index de1d1c6b1975..6cc53eef651d 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -51,12 +51,10 @@ #define CONTROL0_TSEN_TC_TRIM_MASK 0x7 #define CONTROL0_TSEN_TC_TRIM_VAL 0x3 -/* TSEN refers to the temperature sensors within the AP */ #define CONTROL0_TSEN_START BIT(0) #define CONTROL0_TSEN_RESET BIT(1) #define CONTROL0_TSEN_ENABLE BIT(2) -/* EXT_TSEN refers to the external temperature sensors, out of the AP */ #define CONTROL1_EXT_TSEN_SW_RESET BIT(7) #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) From 8b4c2712cd7cbf9f83b8032550c7cbdfcdf970eb Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:47 +0200 Subject: [PATCH 06/34] thermal: armada: rename the initialization routine Calling a hook ->init_sensor() while what is initialized is the IP itself and not the sensors is misleading. Rename the hook ->init() to avoid any confusion in later work bringing multi-sensors support. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 6cc53eef651d..2f2150f9639f 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -73,9 +73,9 @@ struct armada_thermal_priv { }; struct armada_thermal_data { - /* Initialize the sensor */ - void (*init_sensor)(struct platform_device *pdev, - struct armada_thermal_priv *); + /* Initialize the thermal IC */ + void (*init)(struct platform_device *pdev, + struct armada_thermal_priv *priv); /* Test for a valid sensor value (optional) */ bool (*is_valid)(struct armada_thermal_priv *); @@ -94,8 +94,8 @@ struct armada_thermal_data { bool needs_control0; }; -static void armadaxp_init_sensor(struct platform_device *pdev, - struct armada_thermal_priv *priv) +static void armadaxp_init(struct platform_device *pdev, + struct armada_thermal_priv *priv) { u32 reg; @@ -117,8 +117,8 @@ static void armadaxp_init_sensor(struct platform_device *pdev, writel(reg, priv->status); } -static void armada370_init_sensor(struct platform_device *pdev, - struct armada_thermal_priv *priv) +static void armada370_init(struct platform_device *pdev, + struct armada_thermal_priv *priv) { u32 reg; @@ -136,8 +136,8 @@ static void armada370_init_sensor(struct platform_device *pdev, msleep(10); } -static void armada375_init_sensor(struct platform_device *pdev, - struct armada_thermal_priv *priv) +static void armada375_init(struct platform_device *pdev, + struct armada_thermal_priv *priv) { u32 reg; @@ -164,8 +164,8 @@ static void armada_wait_sensor_validity(struct armada_thermal_priv *priv) STATUS_POLL_TIMEOUT_US); } -static void armada380_init_sensor(struct platform_device *pdev, - struct armada_thermal_priv *priv) +static void armada380_init(struct platform_device *pdev, + struct armada_thermal_priv *priv) { u32 reg = readl_relaxed(priv->control1); @@ -186,8 +186,8 @@ static void armada380_init_sensor(struct platform_device *pdev, armada_wait_sensor_validity(priv); } -static void armada_ap806_init_sensor(struct platform_device *pdev, - struct armada_thermal_priv *priv) +static void armada_ap806_init(struct platform_device *pdev, + struct armada_thermal_priv *priv) { u32 reg; @@ -247,7 +247,7 @@ static struct thermal_zone_device_ops ops = { }; static const struct armada_thermal_data armadaxp_data = { - .init_sensor = armadaxp_init_sensor, + .init = armadaxp_init, .temp_shift = 10, .temp_mask = 0x1ff, .coef_b = 3153000000ULL, @@ -257,7 +257,7 @@ static const struct armada_thermal_data armadaxp_data = { static const struct armada_thermal_data armada370_data = { .is_valid = armada_is_valid, - .init_sensor = armada370_init_sensor, + .init = armada370_init, .is_valid_bit = BIT(9), .temp_shift = 10, .temp_mask = 0x1ff, @@ -268,7 +268,7 @@ static const struct armada_thermal_data armada370_data = { static const struct armada_thermal_data armada375_data = { .is_valid = armada_is_valid, - .init_sensor = armada375_init_sensor, + .init = armada375_init, .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x1ff, @@ -280,7 +280,7 @@ static const struct armada_thermal_data armada375_data = { static const struct armada_thermal_data armada380_data = { .is_valid = armada_is_valid, - .init_sensor = armada380_init_sensor, + .init = armada380_init, .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x3ff, @@ -292,7 +292,7 @@ static const struct armada_thermal_data armada380_data = { static const struct armada_thermal_data armada_ap806_data = { .is_valid = armada_is_valid, - .init_sensor = armada_ap806_init_sensor, + .init = armada_ap806_init, .is_valid_bit = BIT(16), .temp_shift = 0, .temp_mask = 0x3ff, @@ -306,7 +306,7 @@ static const struct armada_thermal_data armada_ap806_data = { static const struct armada_thermal_data armada_cp110_data = { .is_valid = armada_is_valid, - .init_sensor = armada380_init_sensor, + .init = armada380_init, .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x3ff, @@ -429,7 +429,7 @@ static int armada_thermal_probe(struct platform_device *pdev) priv->control1 = control + CONTROL1_OFFSET; } - priv->data->init_sensor(pdev, priv); + priv->data->init(pdev, priv); thermal = thermal_zone_device_register(priv->zone_name, 0, 0, priv, &ops, NULL, 0, 0); From 5b5e17a182e14316ab4369fd9e8173207cf42130 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:48 +0200 Subject: [PATCH 07/34] thermal: armada: dissociate a380 and cp110 ->init() hooks Until now, Armada 380 and CP110 could share the same ->init() function because their use was identical. Prepare the support of multi-sensors support and overheat interrupt feature by separating the initialization paths before they actually diverge. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 2f2150f9639f..31ff57a654ba 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -200,6 +200,12 @@ static void armada_ap806_init(struct platform_device *pdev, armada_wait_sensor_validity(priv); } +static void armada_cp110_init(struct platform_device *pdev, + struct armada_thermal_priv *priv) +{ + armada380_init(pdev, priv); +} + static bool armada_is_valid(struct armada_thermal_priv *priv) { u32 reg = readl_relaxed(priv->status); @@ -306,7 +312,7 @@ static const struct armada_thermal_data armada_ap806_data = { static const struct armada_thermal_data armada_cp110_data = { .is_valid = armada_is_valid, - .init = armada380_init, + .init = armada_cp110_init, .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x3ff, From a9fae794e4c581bbe460106609ce88dec8b00973 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:49 +0200 Subject: [PATCH 08/34] thermal: armada: average over samples to avoid glitches Configure the sample frequency and number of averaged samples. This is needed for two reasons: 1/ To be bootloader independent. 2/ To prepare the introduction of multi-sensors support by preventing inconsistencies when reading temperatures that could be a mean of samples took from different sensors. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 31ff57a654ba..05214ebf1093 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -54,7 +54,12 @@ #define CONTROL0_TSEN_START BIT(0) #define CONTROL0_TSEN_RESET BIT(1) #define CONTROL0_TSEN_ENABLE BIT(2) +#define CONTROL0_TSEN_AVG_BYPASS BIT(6) +#define CONTROL0_TSEN_OSR_SHIFT 24 +#define CONTROL0_TSEN_OSR_MAX 0x3 +#define CONTROL1_TSEN_AVG_SHIFT 0 +#define CONTROL1_TSEN_AVG_MASK 0x7 #define CONTROL1_EXT_TSEN_SW_RESET BIT(7) #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) @@ -194,6 +199,13 @@ static void armada_ap806_init(struct platform_device *pdev, reg = readl_relaxed(priv->control0); reg &= ~CONTROL0_TSEN_RESET; reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE; + + /* Sample every ~2ms */ + reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT; + + /* Enable average (2 samples by default) */ + reg &= ~CONTROL0_TSEN_AVG_BYPASS; + writel(reg, priv->control0); /* Wait the sensors to be valid or the core will warn the user */ @@ -203,7 +215,20 @@ static void armada_ap806_init(struct platform_device *pdev, static void armada_cp110_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { + u32 reg; + armada380_init(pdev, priv); + + /* Sample every ~2ms */ + reg = readl_relaxed(priv->control0); + reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT; + writel(reg, priv->control0); + + /* Average the output value over 2^1 = 2 samples */ + reg = readl_relaxed(priv->control1); + reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT; + reg |= 1 << CONTROL1_TSEN_AVG_SHIFT; + writel(reg, priv->control1); } static bool armada_is_valid(struct armada_thermal_priv *priv) From 3d4e51844a4eb3c86e568bdcc9408602b46dc638 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:50 +0200 Subject: [PATCH 09/34] thermal: armada: convert driver to syscon register accesses Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area. This approach is not scalable so instead of adding consinuously memory areas in the DT (and change the DT bindings, while keeping backward compatibility), move the thermal node into a wider syscon from which it will be possible to also configure the thermal interrupt. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 197 ++++++++++++++++++++----------- 1 file changed, 128 insertions(+), 69 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 05214ebf1093..4d1ede40654f 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include /* Thermal Manager Control and Status Register */ #define PMU_TDC0_SW_RST_MASK (0x1 << 1) @@ -39,14 +41,6 @@ #define A375_READOUT_INVERT BIT(15) #define A375_HW_RESETn BIT(8) -/* Legacy bindings */ -#define LEGACY_CONTROL_MEM_LEN 0x4 - -/* Current bindings with the 2 control registers under the same memory area */ -#define LEGACY_CONTROL1_OFFSET 0x0 -#define CONTROL0_OFFSET 0x0 -#define CONTROL1_OFFSET 0x4 - /* Errata fields */ #define CONTROL0_TSEN_TC_TRIM_MASK 0x7 #define CONTROL0_TSEN_TC_TRIM_VAL 0x3 @@ -70,9 +64,7 @@ struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ struct armada_thermal_priv { - void __iomem *status; - void __iomem *control0; - void __iomem *control1; + struct regmap *syscon; char zone_name[THERMAL_NAME_LENGTH]; struct armada_thermal_data *data; }; @@ -96,15 +88,20 @@ struct armada_thermal_data { unsigned int temp_shift; unsigned int temp_mask; u32 is_valid_bit; - bool needs_control0; + + /* Syscon access */ + unsigned int syscon_control0_off; + unsigned int syscon_control1_off; + unsigned int syscon_status_off; }; static void armadaxp_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { + struct armada_thermal_data *data = priv->data; u32 reg; - reg = readl_relaxed(priv->control1); + regmap_read(priv->syscon, data->syscon_control1_off, ®); reg |= PMU_TDC0_OTF_CAL_MASK; /* Reference calibration value */ @@ -114,29 +111,31 @@ static void armadaxp_init(struct platform_device *pdev, /* Reset the sensor */ reg |= PMU_TDC0_SW_RST_MASK; - writel(reg, priv->control1); + regmap_write(priv->syscon, data->syscon_control1_off, reg); /* Enable the sensor */ - reg = readl_relaxed(priv->status); + regmap_read(priv->syscon, data->syscon_status_off, ®); reg &= ~PMU_TM_DISABLE_MASK; - writel(reg, priv->status); + regmap_write(priv->syscon, data->syscon_status_off, reg); } static void armada370_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { + struct armada_thermal_data *data = priv->data; u32 reg; - reg = readl_relaxed(priv->control1); + regmap_read(priv->syscon, data->syscon_control1_off, ®); reg |= PMU_TDC0_OTF_CAL_MASK; /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); + /* Reset the sensor */ reg &= ~PMU_TDC0_START_CAL_MASK; - writel(reg, priv->control1); + regmap_write(priv->syscon, data->syscon_control1_off, reg); msleep(10); } @@ -144,18 +143,20 @@ static void armada370_init(struct platform_device *pdev, static void armada375_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { + struct armada_thermal_data *data = priv->data; u32 reg; - reg = readl(priv->control1); + regmap_read(priv->syscon, data->syscon_control1_off, ®); reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT); reg &= ~A375_READOUT_INVERT; reg &= ~A375_HW_RESETn; + regmap_write(priv->syscon, data->syscon_control1_off, reg); - writel(reg, priv->control1); msleep(20); reg |= A375_HW_RESETn; - writel(reg, priv->control1); + regmap_write(priv->syscon, data->syscon_control1_off, reg); + msleep(50); } @@ -163,29 +164,29 @@ static void armada_wait_sensor_validity(struct armada_thermal_priv *priv) { u32 reg; - readl_relaxed_poll_timeout(priv->status, reg, - reg & priv->data->is_valid_bit, - STATUS_POLL_PERIOD_US, - STATUS_POLL_TIMEOUT_US); + regmap_read_poll_timeout(priv->syscon, priv->data->syscon_status_off, + reg, reg & priv->data->is_valid_bit, + STATUS_POLL_PERIOD_US, + STATUS_POLL_TIMEOUT_US); } static void armada380_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { - u32 reg = readl_relaxed(priv->control1); + struct armada_thermal_data *data = priv->data; + u32 reg; /* Disable the HW/SW reset */ + regmap_read(priv->syscon, data->syscon_control1_off, ®); reg |= CONTROL1_EXT_TSEN_HW_RESETn; reg &= ~CONTROL1_EXT_TSEN_SW_RESET; - writel(reg, priv->control1); + regmap_write(priv->syscon, data->syscon_control1_off, reg); /* Set Tsen Tc Trim to correct default value (errata #132698) */ - if (priv->control0) { - reg = readl_relaxed(priv->control0); - reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; - reg |= CONTROL0_TSEN_TC_TRIM_VAL; - writel(reg, priv->control0); - } + regmap_read(priv->syscon, data->syscon_control0_off, ®); + reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; + reg |= CONTROL0_TSEN_TC_TRIM_VAL; + regmap_write(priv->syscon, data->syscon_control0_off, reg); /* Wait the sensors to be valid or the core will warn the user */ armada_wait_sensor_validity(priv); @@ -194,9 +195,10 @@ static void armada380_init(struct platform_device *pdev, static void armada_ap806_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { + struct armada_thermal_data *data = priv->data; u32 reg; - reg = readl_relaxed(priv->control0); + regmap_read(priv->syscon, data->syscon_control0_off, ®); reg &= ~CONTROL0_TSEN_RESET; reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE; @@ -206,7 +208,7 @@ static void armada_ap806_init(struct platform_device *pdev, /* Enable average (2 samples by default) */ reg &= ~CONTROL0_TSEN_AVG_BYPASS; - writel(reg, priv->control0); + regmap_write(priv->syscon, data->syscon_control0_off, reg); /* Wait the sensors to be valid or the core will warn the user */ armada_wait_sensor_validity(priv); @@ -215,25 +217,28 @@ static void armada_ap806_init(struct platform_device *pdev, static void armada_cp110_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { + struct armada_thermal_data *data = priv->data; u32 reg; armada380_init(pdev, priv); /* Sample every ~2ms */ - reg = readl_relaxed(priv->control0); + regmap_read(priv->syscon, data->syscon_control0_off, ®); reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT; - writel(reg, priv->control0); + regmap_write(priv->syscon, data->syscon_control0_off, reg); /* Average the output value over 2^1 = 2 samples */ - reg = readl_relaxed(priv->control1); + regmap_read(priv->syscon, data->syscon_control1_off, ®); reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT; reg |= 1 << CONTROL1_TSEN_AVG_SHIFT; - writel(reg, priv->control1); + regmap_write(priv->syscon, data->syscon_control1_off, reg); } static bool armada_is_valid(struct armada_thermal_priv *priv) { - u32 reg = readl_relaxed(priv->status); + u32 reg; + + regmap_read(priv->syscon, priv->data->syscon_status_off, ®); return reg & priv->data->is_valid_bit; } @@ -252,7 +257,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal, return -EIO; } - reg = readl_relaxed(priv->status); + regmap_read(priv->syscon, priv->data->syscon_status_off, ®); reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; if (priv->data->signed_sample) /* The most significant bit is the sign bit */ @@ -284,6 +289,8 @@ static const struct armada_thermal_data armadaxp_data = { .coef_b = 3153000000ULL, .coef_m = 10000000ULL, .coef_div = 13825, + .syscon_status_off = 0xb0, + .syscon_control1_off = 0xd0, }; static const struct armada_thermal_data armada370_data = { @@ -295,6 +302,8 @@ static const struct armada_thermal_data armada370_data = { .coef_b = 3153000000ULL, .coef_m = 10000000ULL, .coef_div = 13825, + .syscon_status_off = 0x0, + .syscon_control1_off = 0x4, }; static const struct armada_thermal_data armada375_data = { @@ -306,7 +315,9 @@ static const struct armada_thermal_data armada375_data = { .coef_b = 3171900000ULL, .coef_m = 10000000ULL, .coef_div = 13616, - .needs_control0 = true, + .syscon_status_off = 0x78, + .syscon_control0_off = 0x7c, + .syscon_control1_off = 0x80, }; static const struct armada_thermal_data armada380_data = { @@ -319,6 +330,9 @@ static const struct armada_thermal_data armada380_data = { .coef_m = 2000096ULL, .coef_div = 4201, .inverted = true, + .syscon_control0_off = 0x70, + .syscon_control1_off = 0x74, + .syscon_status_off = 0x78, }; static const struct armada_thermal_data armada_ap806_data = { @@ -332,7 +346,9 @@ static const struct armada_thermal_data armada_ap806_data = { .coef_div = 1, .inverted = true, .signed_sample = true, - .needs_control0 = true, + .syscon_control0_off = 0x84, + .syscon_control1_off = 0x88, + .syscon_status_off = 0x8C, }; static const struct armada_thermal_data armada_cp110_data = { @@ -345,7 +361,9 @@ static const struct armada_thermal_data armada_cp110_data = { .coef_m = 2000096ULL, .coef_div = 4201, .inverted = true, - .needs_control0 = true, + .syscon_control0_off = 0x70, + .syscon_control1_off = 0x74, + .syscon_status_off = 0x78, }; static const struct of_device_id armada_thermal_id_table[] = { @@ -379,6 +397,57 @@ static const struct of_device_id armada_thermal_id_table[] = { }; MODULE_DEVICE_TABLE(of, armada_thermal_id_table); +static const struct regmap_config armada_thermal_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int armada_thermal_probe_legacy(struct platform_device *pdev, + struct armada_thermal_priv *priv) +{ + struct armada_thermal_data *data = priv->data; + struct resource *res; + void __iomem *base; + + /* First memory region points towards the status register */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + + /* + * Edit the resource start address and length to map over all the + * registers, instead of pointing at them one by one. + */ + res->start -= data->syscon_status_off; + res->end = res->start + max(data->syscon_status_off, + max(data->syscon_control0_off, + data->syscon_control1_off)) + + sizeof(unsigned int) - 1; + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->syscon = devm_regmap_init_mmio(&pdev->dev, base, + &armada_thermal_regmap_config); + if (IS_ERR(priv->syscon)) + return PTR_ERR(priv->syscon); + + return 0; +} + +static int armada_thermal_probe_syscon(struct platform_device *pdev, + struct armada_thermal_priv *priv) +{ + priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(priv->syscon)) + return PTR_ERR(priv->syscon); + + return 0; +} + static void armada_set_sane_name(struct platform_device *pdev, struct armada_thermal_priv *priv) { @@ -412,11 +481,10 @@ static void armada_set_sane_name(struct platform_device *pdev, static int armada_thermal_probe(struct platform_device *pdev) { - void __iomem *control = NULL; struct thermal_zone_device *thermal; const struct of_device_id *match; struct armada_thermal_priv *priv; - struct resource *res; + int ret; match = of_match_device(armada_thermal_id_table, &pdev->dev); if (!match) @@ -426,16 +494,6 @@ static int armada_thermal_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->status = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->status)) - return PTR_ERR(priv->status); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - control = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(control)) - return PTR_ERR(control); - priv->data = (struct armada_thermal_data *)match->data; /* Ensure device name is correct for the thermal core */ @@ -443,22 +501,23 @@ static int armada_thermal_probe(struct platform_device *pdev) /* * Legacy DT bindings only described "control1" register (also referred - * as "control MSB" on old documentation). New bindings cover + * as "control MSB" on old documentation). Then, bindings moved to cover * "control0/control LSB" and "control1/control MSB" registers within - * the same resource, which is then of size 8 instead of 4. + * the same resource, which was then of size 8 instead of 4. + * + * The logic of defining sporadic registers is broken. For instance, it + * blocked the addition of the overheat interrupt feature that needed + * another resource somewhere else in the same memory area. One solution + * is to define an overall system controller and put the thermal node + * into it, which requires the use of regmaps across all the driver. */ - if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) { - /* ->control0 unavailable in this configuration */ - if (priv->data->needs_control0) { - dev_err(&pdev->dev, "No access to control0 register\n"); - return -EINVAL; - } + if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) + ret = armada_thermal_probe_legacy(pdev, priv); + else + ret = armada_thermal_probe_syscon(pdev, priv); - priv->control1 = control + LEGACY_CONTROL1_OFFSET; - } else { - priv->control0 = control + CONTROL0_OFFSET; - priv->control1 = control + CONTROL1_OFFSET; - } + if (ret) + return ret; priv->data->init(pdev, priv); From c9899c183921f919e10fe821be7de9fea876ba65 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:51 +0200 Subject: [PATCH 10/34] thermal: armada: use the resource managed registration helper alternative Current use of thermal_zone_device_register() triggers a warning at boot and should be replaced by devm_thermal_zone_of_sensor_register(). This allows better handling of multiple thermal zones for later multi-sensors support. Also change the driver data to embed a new structure to make the difference between legacy data (which needs to be cleaned) and syscon-related data. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 124 +++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 23 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 4d1ede40654f..414329e94f8c 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -64,6 +64,7 @@ struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ struct armada_thermal_priv { + struct device *dev; struct regmap *syscon; char zone_name[THERMAL_NAME_LENGTH]; struct armada_thermal_data *data; @@ -95,6 +96,26 @@ struct armada_thermal_data { unsigned int syscon_status_off; }; +struct armada_drvdata { + enum drvtype { + LEGACY, + SYSCON + } type; + union { + struct armada_thermal_priv *priv; + struct thermal_zone_device *tz; + } data; +}; + +/* + * struct armada_thermal_sensor - hold the information of one thermal sensor + * @thermal: pointer to the local private structure + * @tzd: pointer to the thermal zone device + */ +struct armada_thermal_sensor { + struct armada_thermal_priv *priv; +}; + static void armadaxp_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { @@ -243,16 +264,14 @@ static bool armada_is_valid(struct armada_thermal_priv *priv) return reg & priv->data->is_valid_bit; } -static int armada_get_temp(struct thermal_zone_device *thermal, - int *temp) +static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp) { - struct armada_thermal_priv *priv = thermal->devdata; u32 reg, div; s64 sample, b, m; /* Valid check */ if (priv->data->is_valid && !priv->data->is_valid(priv)) { - dev_err(&thermal->device, + dev_err(priv->dev, "Temperature sensor reading not valid\n"); return -EIO; } @@ -278,7 +297,32 @@ static int armada_get_temp(struct thermal_zone_device *thermal, return 0; } -static struct thermal_zone_device_ops ops = { +static int armada_get_temp_legacy(struct thermal_zone_device *thermal, + int *temp) +{ + struct armada_thermal_priv *priv = thermal->devdata; + int ret; + + /* Do the actual reading */ + ret = armada_read_sensor(priv, temp); + + return ret; +} + +static struct thermal_zone_device_ops legacy_ops = { + .get_temp = armada_get_temp_legacy, +}; + +static int armada_get_temp(void *_sensor, int *temp) +{ + struct armada_thermal_sensor *sensor = _sensor; + struct armada_thermal_priv *priv = sensor->priv; + + /* Do the actual reading */ + return armada_read_sensor(priv, temp); +} + +static struct thermal_zone_of_device_ops of_ops = { .get_temp = armada_get_temp, }; @@ -481,7 +525,9 @@ static void armada_set_sane_name(struct platform_device *pdev, static int armada_thermal_probe(struct platform_device *pdev) { - struct thermal_zone_device *thermal; + struct thermal_zone_device *tz; + struct armada_thermal_sensor *sensors; + struct armada_drvdata *drvdata; const struct of_device_id *match; struct armada_thermal_priv *priv; int ret; @@ -494,10 +540,12 @@ static int armada_thermal_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->data = (struct armada_thermal_data *)match->data; + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* Ensure device name is correct for the thermal core */ - armada_set_sane_name(pdev, priv); + priv->dev = &pdev->dev; + priv->data = (struct armada_thermal_data *)match->data; /* * Legacy DT bindings only described "control1" register (also referred @@ -511,35 +559,65 @@ static int armada_thermal_probe(struct platform_device *pdev) * is to define an overall system controller and put the thermal node * into it, which requires the use of regmaps across all the driver. */ - if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) - ret = armada_thermal_probe_legacy(pdev, priv); - else - ret = armada_thermal_probe_syscon(pdev, priv); + if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) { + /* Ensure device name is correct for the thermal core */ + armada_set_sane_name(pdev, priv); + ret = armada_thermal_probe_legacy(pdev, priv); + if (ret) + return ret; + + priv->data->init(pdev, priv); + + tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv, + &legacy_ops, NULL, 0, 0); + if (IS_ERR(tz)) { + dev_err(&pdev->dev, + "Failed to register thermal zone device\n"); + return PTR_ERR(tz); + } + + drvdata->type = LEGACY; + drvdata->data.tz = tz; + platform_set_drvdata(pdev, drvdata); + + return 0; + } + + ret = armada_thermal_probe_syscon(pdev, priv); if (ret) return ret; priv->data->init(pdev, priv); + drvdata->type = SYSCON; + drvdata->data.priv = priv; + platform_set_drvdata(pdev, drvdata); - thermal = thermal_zone_device_register(priv->zone_name, 0, 0, priv, - &ops, NULL, 0, 0); - if (IS_ERR(thermal)) { + sensors = devm_kzalloc(&pdev->dev, sizeof(struct armada_thermal_sensor), + GFP_KERNEL); + if (!sensors) + return -ENOMEM; + + sensors->priv = priv; + + tz = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, sensors, + &of_ops); + if (IS_ERR(tz)) { dev_err(&pdev->dev, - "Failed to register thermal zone device\n"); - return PTR_ERR(thermal); + "Failed to register thermal sensor (err: %ld)\n", + PTR_ERR(tz)); + return PTR_ERR(tz); } - platform_set_drvdata(pdev, thermal); - return 0; } static int armada_thermal_exit(struct platform_device *pdev) { - struct thermal_zone_device *armada_thermal = - platform_get_drvdata(pdev); + struct armada_drvdata *drvdata = platform_get_drvdata(pdev); - thermal_zone_device_unregister(armada_thermal); + if (drvdata->type == LEGACY) + thermal_zone_device_unregister(drvdata->data.tz); return 0; } From f7c2068a1728c1b2aed9416b071a3e2f8f887786 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:52 +0200 Subject: [PATCH 11/34] thermal: armada: add multi-channel sensors support MVEBU thermal IP supports multiple channels. Each channel may have several sensors but for now each channel is wired to only one thermal sensor. The first channel always points to the so called internal sensor, within the thermal IP. There is usually one more channel (with one sensor each time) per CPU. The code has been written to support possible evolutions of the ap806 IP that would embed more CPUs and thus more channels to select. Each channel should be referenced in the device tree as an independent thermal zone. Add the possibility to read each of these sensors through sysfs by registering all the sensors (translated in "thermal_zone"). Also add a mutex on these accesses to avoid read conflicts (only one channel/sensor may be selected and read at a time). Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 133 ++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 414329e94f8c..e20d4f954f21 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -49,8 +49,13 @@ #define CONTROL0_TSEN_RESET BIT(1) #define CONTROL0_TSEN_ENABLE BIT(2) #define CONTROL0_TSEN_AVG_BYPASS BIT(6) +#define CONTROL0_TSEN_CHAN_SHIFT 13 +#define CONTROL0_TSEN_CHAN_MASK 0xF #define CONTROL0_TSEN_OSR_SHIFT 24 #define CONTROL0_TSEN_OSR_MAX 0x3 +#define CONTROL0_TSEN_MODE_SHIFT 30 +#define CONTROL0_TSEN_MODE_EXTERNAL 0x2 +#define CONTROL0_TSEN_MODE_MASK 0x3 #define CONTROL1_TSEN_AVG_SHIFT 0 #define CONTROL1_TSEN_AVG_MASK 0x7 @@ -67,7 +72,10 @@ struct armada_thermal_priv { struct device *dev; struct regmap *syscon; char zone_name[THERMAL_NAME_LENGTH]; + /* serialize temperature reads/updates */ + struct mutex update_lock; struct armada_thermal_data *data; + int current_channel; }; struct armada_thermal_data { @@ -94,6 +102,9 @@ struct armada_thermal_data { unsigned int syscon_control0_off; unsigned int syscon_control1_off; unsigned int syscon_status_off; + + /* One sensor is in the thermal IC, the others are in the CPUs if any */ + unsigned int cpu_nr; }; struct armada_drvdata { @@ -111,9 +122,11 @@ struct armada_drvdata { * struct armada_thermal_sensor - hold the information of one thermal sensor * @thermal: pointer to the local private structure * @tzd: pointer to the thermal zone device + * @id: identifier of the thermal sensor */ struct armada_thermal_sensor { struct armada_thermal_priv *priv; + int id; }; static void armadaxp_init(struct platform_device *pdev, @@ -181,14 +194,15 @@ static void armada375_init(struct platform_device *pdev, msleep(50); } -static void armada_wait_sensor_validity(struct armada_thermal_priv *priv) +static int armada_wait_sensor_validity(struct armada_thermal_priv *priv) { u32 reg; - regmap_read_poll_timeout(priv->syscon, priv->data->syscon_status_off, - reg, reg & priv->data->is_valid_bit, - STATUS_POLL_PERIOD_US, - STATUS_POLL_TIMEOUT_US); + return regmap_read_poll_timeout(priv->syscon, + priv->data->syscon_status_off, reg, + reg & priv->data->is_valid_bit, + STATUS_POLL_PERIOD_US, + STATUS_POLL_TIMEOUT_US); } static void armada380_init(struct platform_device *pdev, @@ -264,6 +278,58 @@ static bool armada_is_valid(struct armada_thermal_priv *priv) return reg & priv->data->is_valid_bit; } +/* There is currently no board with more than one sensor per channel */ +static int armada_select_channel(struct armada_thermal_priv *priv, int channel) +{ + struct armada_thermal_data *data = priv->data; + u32 ctrl0; + + if (channel < 0 || channel > priv->data->cpu_nr) + return -EINVAL; + + if (priv->current_channel == channel) + return 0; + + /* Stop the measurements */ + regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0); + ctrl0 &= ~CONTROL0_TSEN_START; + regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); + + /* Reset the mode, internal sensor will be automatically selected */ + ctrl0 &= ~(CONTROL0_TSEN_MODE_MASK << CONTROL0_TSEN_MODE_SHIFT); + + /* Other channels are external and should be selected accordingly */ + if (channel) { + /* Change the mode to external */ + ctrl0 |= CONTROL0_TSEN_MODE_EXTERNAL << + CONTROL0_TSEN_MODE_SHIFT; + /* Select the sensor */ + ctrl0 &= ~(CONTROL0_TSEN_CHAN_MASK << CONTROL0_TSEN_CHAN_SHIFT); + ctrl0 |= (channel - 1) << CONTROL0_TSEN_CHAN_SHIFT; + } + + /* Actually set the mode/channel */ + regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); + priv->current_channel = channel; + + /* Re-start the measurements */ + ctrl0 |= CONTROL0_TSEN_START; + regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); + + /* + * The IP has a latency of ~15ms, so after updating the selected source, + * we must absolutely wait for the sensor validity bit to ensure we read + * actual data. + */ + if (armada_wait_sensor_validity(priv)) { + dev_err(priv->dev, + "Temperature sensor reading not valid\n"); + return -EIO; + } + + return 0; +} + static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp) { u32 reg, div; @@ -317,9 +383,22 @@ static int armada_get_temp(void *_sensor, int *temp) { struct armada_thermal_sensor *sensor = _sensor; struct armada_thermal_priv *priv = sensor->priv; + int ret; + + mutex_lock(&priv->update_lock); + + /* Select the desired channel */ + ret = armada_select_channel(priv, sensor->id); + if (ret) + goto unlock_mutex; /* Do the actual reading */ - return armada_read_sensor(priv, temp); + ret = armada_read_sensor(priv, temp); + +unlock_mutex: + mutex_unlock(&priv->update_lock); + + return ret; } static struct thermal_zone_of_device_ops of_ops = { @@ -393,6 +472,7 @@ static const struct armada_thermal_data armada_ap806_data = { .syscon_control0_off = 0x84, .syscon_control1_off = 0x88, .syscon_status_off = 0x8C, + .cpu_nr = 4, }; static const struct armada_thermal_data armada_cp110_data = { @@ -526,10 +606,11 @@ static void armada_set_sane_name(struct platform_device *pdev, static int armada_thermal_probe(struct platform_device *pdev) { struct thermal_zone_device *tz; - struct armada_thermal_sensor *sensors; + struct armada_thermal_sensor *sensor; struct armada_drvdata *drvdata; const struct of_device_id *match; struct armada_thermal_priv *priv; + int sensor_id; int ret; match = of_match_device(armada_thermal_id_table, &pdev->dev); @@ -547,6 +628,8 @@ static int armada_thermal_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->data = (struct armada_thermal_data *)match->data; + mutex_init(&priv->update_lock); + /* * Legacy DT bindings only described "control1" register (also referred * as "control MSB" on old documentation). Then, bindings moved to cover @@ -588,25 +671,35 @@ static int armada_thermal_probe(struct platform_device *pdev) if (ret) return ret; + priv->current_channel = -1; priv->data->init(pdev, priv); drvdata->type = SYSCON; drvdata->data.priv = priv; platform_set_drvdata(pdev, drvdata); - sensors = devm_kzalloc(&pdev->dev, sizeof(struct armada_thermal_sensor), - GFP_KERNEL); - if (!sensors) - return -ENOMEM; + /* + * There is one channel for the IC and one per CPU (if any), each + * channel has one sensor. + */ + for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) { + sensor = devm_kzalloc(&pdev->dev, + sizeof(struct armada_thermal_sensor), + GFP_KERNEL); + if (!sensor) + return -ENOMEM; - sensors->priv = priv; - - tz = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, sensors, - &of_ops); - if (IS_ERR(tz)) { - dev_err(&pdev->dev, - "Failed to register thermal sensor (err: %ld)\n", - PTR_ERR(tz)); - return PTR_ERR(tz); + /* Register the sensor */ + sensor->priv = priv; + sensor->id = sensor_id; + tz = devm_thermal_zone_of_sensor_register(&pdev->dev, + sensor->id, sensor, + &of_ops); + if (IS_ERR(tz)) { + dev_info(&pdev->dev, "Thermal sensor %d unavailable\n", + sensor_id); + devm_kfree(&pdev->dev, sensor); + continue; + } } return 0; From 00707e4c9618949d492f685c324326f39f08ea9c Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:53 +0200 Subject: [PATCH 12/34] thermal: armada: remove sensors validity from the IP initialization When using new bindings with multiple sensors, sensor validity is checked twice because sensor selection also checks for the validity. Remove the redundant call from the IP initialization helper and move it to the legacy probe section where it is still needed. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index e20d4f954f21..1f6bc317748d 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -222,9 +222,6 @@ static void armada380_init(struct platform_device *pdev, reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; reg |= CONTROL0_TSEN_TC_TRIM_VAL; regmap_write(priv->syscon, data->syscon_control0_off, reg); - - /* Wait the sensors to be valid or the core will warn the user */ - armada_wait_sensor_validity(priv); } static void armada_ap806_init(struct platform_device *pdev, @@ -244,9 +241,6 @@ static void armada_ap806_init(struct platform_device *pdev, reg &= ~CONTROL0_TSEN_AVG_BYPASS; regmap_write(priv->syscon, data->syscon_control0_off, reg); - - /* Wait the sensors to be valid or the core will warn the user */ - armada_wait_sensor_validity(priv); } static void armada_cp110_init(struct platform_device *pdev, @@ -652,6 +646,9 @@ static int armada_thermal_probe(struct platform_device *pdev) priv->data->init(pdev, priv); + /* Wait the sensors to be valid */ + armada_wait_sensor_validity(priv); + tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv, &legacy_ops, NULL, 0, 0); if (IS_ERR(tz)) { From 68b14828ca102630e721d10b2e5dedc9c9b38095 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:54 +0200 Subject: [PATCH 13/34] thermal: armada: move validity check out of the read function Sensor selection when using multiple sensors already checks for the sensor validity. Move it to the legacy ->get_temp() hook, where it is still needed. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 1f6bc317748d..53e757a28506 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -329,13 +329,6 @@ static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp) u32 reg, div; s64 sample, b, m; - /* Valid check */ - if (priv->data->is_valid && !priv->data->is_valid(priv)) { - dev_err(priv->dev, - "Temperature sensor reading not valid\n"); - return -EIO; - } - regmap_read(priv->syscon, priv->data->syscon_status_off, ®); reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; if (priv->data->signed_sample) @@ -363,6 +356,13 @@ static int armada_get_temp_legacy(struct thermal_zone_device *thermal, struct armada_thermal_priv *priv = thermal->devdata; int ret; + /* Valid check */ + if (priv->data->is_valid && !priv->data->is_valid(priv)) { + dev_err(priv->dev, + "Temperature sensor reading not valid\n"); + return -EIO; + } + /* Do the actual reading */ ret = armada_read_sensor(priv, temp); From 8c0e64ac4075b7ca870098ed2ad6089868f5fa7b Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:55 +0200 Subject: [PATCH 14/34] thermal: armada: get rid of the ->is_valid() pointer The implementation of armada_is_valid() is very simple and is the same across all the versions of the IP since the ->is_valid_bit has been introduced. Simplify the structure by getting rid of the function pointer and calling directly the function. Signed-off-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 53e757a28506..4164a5a4e480 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -83,9 +83,6 @@ struct armada_thermal_data { void (*init)(struct platform_device *pdev, struct armada_thermal_priv *priv); - /* Test for a valid sensor value (optional) */ - bool (*is_valid)(struct armada_thermal_priv *); - /* Formula coeficients: temp = (b - m * reg) / div */ s64 coef_b; s64 coef_m; @@ -267,6 +264,9 @@ static bool armada_is_valid(struct armada_thermal_priv *priv) { u32 reg; + if (!priv->data->is_valid_bit) + return true; + regmap_read(priv->syscon, priv->data->syscon_status_off, ®); return reg & priv->data->is_valid_bit; @@ -357,7 +357,7 @@ static int armada_get_temp_legacy(struct thermal_zone_device *thermal, int ret; /* Valid check */ - if (priv->data->is_valid && !priv->data->is_valid(priv)) { + if (armada_is_valid(priv)) { dev_err(priv->dev, "Temperature sensor reading not valid\n"); return -EIO; @@ -411,7 +411,6 @@ static const struct armada_thermal_data armadaxp_data = { }; static const struct armada_thermal_data armada370_data = { - .is_valid = armada_is_valid, .init = armada370_init, .is_valid_bit = BIT(9), .temp_shift = 10, @@ -424,7 +423,6 @@ static const struct armada_thermal_data armada370_data = { }; static const struct armada_thermal_data armada375_data = { - .is_valid = armada_is_valid, .init = armada375_init, .is_valid_bit = BIT(10), .temp_shift = 0, @@ -438,7 +436,6 @@ static const struct armada_thermal_data armada375_data = { }; static const struct armada_thermal_data armada380_data = { - .is_valid = armada_is_valid, .init = armada380_init, .is_valid_bit = BIT(10), .temp_shift = 0, @@ -453,7 +450,6 @@ static const struct armada_thermal_data armada380_data = { }; static const struct armada_thermal_data armada_ap806_data = { - .is_valid = armada_is_valid, .init = armada_ap806_init, .is_valid_bit = BIT(16), .temp_shift = 0, @@ -470,7 +466,6 @@ static const struct armada_thermal_data armada_ap806_data = { }; static const struct armada_thermal_data armada_cp110_data = { - .is_valid = armada_is_valid, .init = armada_cp110_init, .is_valid_bit = BIT(10), .temp_shift = 0, From 4aa5496980e4c099ede8815d0672809efd8e226a Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:56 +0200 Subject: [PATCH 15/34] dt-bindings: cp110: rename cp110 syscon file There is no need to give numbers to system controllers inside the documentation as the syscons use the same compatibles. Furthermore, this approach does not scale very well and would force the creation of a new file each time a new syscon is added in the device tree. Signed-off-by: Miquel Raynal Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../{cp110-system-controller0.txt => cp110-system-controller.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/arm/marvell/{cp110-system-controller0.txt => cp110-system-controller.txt} (100%) diff --git a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt similarity index 100% rename from Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt rename to Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt From 2cefabe03f5ef6ff2c6c3faf949b05db63fda2a5 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:57 +0200 Subject: [PATCH 16/34] dt-bindings: ap806: prepare the syscon file to list other syscons nodes There are multiple system controllers in AP806. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic. Signed-off-by: Miquel Raynal Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../bindings/arm/marvell/ap806-system-controller.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt index 0b887440e08a..a856eb9a4e05 100644 --- a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt @@ -2,14 +2,14 @@ Marvell Armada AP806 System Controller ====================================== The AP806 is one of the two core HW blocks of the Marvell Armada 7K/8K -SoCs. It contains a system controller, which provides a number -registers giving access to numerous features: clocks, pin-muxing and -many other SoC configuration items. This DT binding allows to describe -this system controller. +SoCs. It contains system controllers, which provide several registers +giving access to numerous features: clocks, pin-muxing and many other +SoC configuration items. This DT binding allows to describe these +system controllers. For the top level node: - compatible: must be: "syscon", "simple-mfd"; - - reg: register area of the AP806 system controller + - reg: register area of the AP806 system controller Clocks: ------- From ab0156c50d7986aacbc9b8bd9abc59bb29869d81 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:58 +0200 Subject: [PATCH 17/34] dt-bindings: cp110: prepare the syscon file to list other syscons nodes There are multiple system controllers in CP110. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic, and align with AP806 file. Signed-off-by: Miquel Raynal Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../arm/marvell/cp110-system-controller.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt index 29cdbae6c5ac..56e7fb1153e7 100644 --- a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt @@ -1,15 +1,15 @@ -Marvell Armada CP110 System Controller 0 -======================================== +Marvell Armada CP110 System Controller +====================================== The CP110 is one of the two core HW blocks of the Marvell Armada 7K/8K -SoCs. It contains two sets of system control registers, System -Controller 0 and System Controller 1. This Device Tree binding allows -to describe the first system controller, which provides registers to -configure various aspects of the SoC. +SoCs. It contains system controllers, which provide several registers +giving access to numerous features: clocks, pin-muxing and many other +SoC configuration items. This DT binding allows to describe these +system controllers. For the top level node: - compatible: must be: "syscon", "simple-mfd"; - - reg: register area of the CP110 system controller 0 + - reg: register area of the CP110 system controller Clocks: ------- From afa544a2fb6827b5ea8547a69b28115439e14533 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:41:59 +0200 Subject: [PATCH 18/34] dt-bindings: ap806: add the thermal node in the syscon file Explain the thermal bindings now that the thermal IP is described being inside of a system controller. Add a reference to the thermal-zone node. Signed-off-by: Miquel Raynal Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../arm/marvell/ap806-system-controller.txt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt index a856eb9a4e05..3fd21bb7cb37 100644 --- a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt @@ -11,6 +11,9 @@ For the top level node: - compatible: must be: "syscon", "simple-mfd"; - reg: register area of the AP806 system controller +SYSTEM CONTROLLER 0 +=================== + Clocks: ------- @@ -98,3 +101,38 @@ ap_syscon: system-controller@6f4000 { gpio-ranges = <&ap_pinctrl 0 0 19>; }; }; + +SYSTEM CONTROLLER 1 +=================== + +Thermal: +-------- + +For common binding part and usage, refer to +Documentation/devicetree/bindings/thermal/thermal.txt + +The thermal IP can probe the temperature all around the processor. It +may feature several channels, each of them wired to one sensor. + +Required properties: +- compatible: must be one of: + * marvell,armada-ap806-thermal +- reg: register range associated with the thermal functions. + +Optional properties: +- #thermal-sensor-cells: shall be <1> when thermal-zones subnodes refer + to this IP and represents the channel ID. There is one sensor per + channel. O refers to the thermal IP internal channel, while positive + IDs refer to each CPU. + +Example: +ap_syscon1: system-controller@6f8000 { + compatible = "syscon", "simple-mfd"; + reg = <0x6f8000 0x1000>; + + ap_thermal: thermal-sensor@80 { + compatible = "marvell,armada-ap806-thermal"; + reg = <0x80 0x10>; + #thermal-sensor-cells = <1>; + }; +}; From e1ea68beaf539a1872debd749c62025cde0e2430 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:42:00 +0200 Subject: [PATCH 19/34] dt-bindings: cp110: update documentation since DT de-duplication CP110 master/slave DT files have been merged in a DT de-duplication work merged in v4.16. Update the syscon documentation accordingly to match the current state of the DT nodes. Signed-off-by: Miquel Raynal Acked-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../bindings/arm/marvell/cp110-system-controller.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt index 56e7fb1153e7..54b0d64ce819 100644 --- a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt @@ -163,26 +163,26 @@ Required properties: Example: -cpm_syscon0: system-controller@440000 { +CP110_LABEL(syscon0): system-controller@440000 { compatible = "syscon", "simple-mfd"; reg = <0x440000 0x1000>; - cpm_clk: clock { + CP110_LABEL(clk): clock { compatible = "marvell,cp110-clock"; #clock-cells = <2>; }; - cpm_pinctrl: pinctrl { + CP110_LABEL(pinctrl): pinctrl { compatible = "marvell,armada-8k-cpm-pinctrl"; }; - cpm_gpio1: gpio@100 { + CP110_LABEL(gpio1): gpio@100 { compatible = "marvell,armada-8k-gpio"; offset = <0x100>; ngpios = <32>; gpio-controller; #gpio-cells = <2>; - gpio-ranges = <&cpm_pinctrl 0 0 32>; + gpio-ranges = <&CP110_LABEL(pinctrl) 0 0 32>; }; }; From c3ab5dfff1e088e163aa2f866dd66e5a55af463f Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:42:01 +0200 Subject: [PATCH 20/34] dt-bindings: cp110: add the thermal node in the syscon file Explain the thermal bindings now that the thermal IP is described being inside of a system controller. Add a reference to the thermal-zone node. Signed-off-by: Miquel Raynal Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../arm/marvell/cp110-system-controller.txt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt index 54b0d64ce819..81ce742d2760 100644 --- a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt @@ -11,6 +11,9 @@ For the top level node: - compatible: must be: "syscon", "simple-mfd"; - reg: register area of the CP110 system controller +SYSTEM CONTROLLER 0 +=================== + Clocks: ------- @@ -186,3 +189,37 @@ CP110_LABEL(syscon0): system-controller@440000 { }; }; + +SYSTEM CONTROLLER 1 +=================== + +Thermal: +-------- + +The thermal IP can probe the temperature all around the processor. It +may feature several channels, each of them wired to one sensor. + +For common binding part and usage, refer to +Documentation/devicetree/bindings/thermal/thermal.txt + +Required properties: +- compatible: must be one of: + * marvell,armada-cp110-thermal +- reg: register range associated with the thermal functions. + +Optional properties: +- #thermal-sensor-cells: shall be <1> when thermal-zones subnodes refer + to this IP and represents the channel ID. There is one sensor per + channel. O refers to the thermal IP internal channel. + +Example: +CP110_LABEL(syscon1): system-controller@6f8000 { + compatible = "syscon", "simple-mfd"; + reg = <0x6f8000 0x1000>; + + CP110_LABEL(thermal): thermal-sensor@70 { + compatible = "marvell,armada-cp110-thermal"; + reg = <0x70 0x10>; + #thermal-sensor-cells = <1>; + }; +}; From 59d7f4a7fa9821a4ce0ea5870c367f9d8adb2619 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 16 Jul 2018 16:42:02 +0200 Subject: [PATCH 21/34] dt-bindings: thermal: armada: add reference to new bindings New bindings (using a syscon) are available for AP806 and CP110 compatibles. Add a reference to these files from the original documentation. Signed-off-by: Miquel Raynal Acked-by: Rob Herring Signed-off-by: Eduardo Valentin --- Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/armada-thermal.txt b/Documentation/devicetree/bindings/thermal/armada-thermal.txt index e0d013a2e66d..f3b441100890 100644 --- a/Documentation/devicetree/bindings/thermal/armada-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/armada-thermal.txt @@ -10,6 +10,11 @@ Required properties: * marvell,armada-ap806-thermal * marvell,armada-cp110-thermal +Note: these bindings are deprecated for AP806/CP110 and should instead +follow the rules described in: +Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt + - reg: Device's register space. Two entries are expected, see the examples below. The first one points to the status register (4B). The second one points to the control From 409ef0bacacf72c51cc876349ae3fdf7cf726d47 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 10 Jul 2018 16:40:34 +0100 Subject: [PATCH 22/34] thermal_hwmon: Sanitize attribute name passed to hwmon My Chromebook Plus (kevin) is spitting the following at boot time: (NULL device *): hwmon: 'sbs-9-000b' is not a valid name attribute, please fix Clearly, __hwmon_device_register is unhappy about the property name. Some investigation reveals that thermal_add_hwmon_sysfs doesn't sanitize the name of the attribute. In order to keep it quiet, let's replace '-' with '_' in hwmon->type This is consistent with what iio-hwmon does since b92fe9e3379c8. Signed-off-by: Marc Zyngier Tested-by: Enric Balletbo i Serra Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal_hwmon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index 11278836ed12..0bd47007c57f 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -142,6 +142,7 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) INIT_LIST_HEAD(&hwmon->tz_list); strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); + strreplace(hwmon->type, '-', '_'); hwmon->device = hwmon_device_register_with_info(NULL, hwmon->type, hwmon, NULL, NULL); if (IS_ERR(hwmon->device)) { From f6b6b52ef7a54160c0a4d2b56a58f84a2e5b33c5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 10 Jul 2018 16:40:35 +0100 Subject: [PATCH 23/34] thermal_hwmon: Pass the originating device down to hwmon_device_register_with_info When registering the hwmon device, we pass NULL as the device. While this doesn't result in any immediate breakage, it leaves the hwmon device at the root of the virtual devices, rather than attached to the thermal zone hierarchy. Instead, let's pass the actual device, which is part of the thermal_zone_device structure. This also avoids the rather unpleasant ""NULL device *" which can be generated by dev_{err,info} in the hwmon subsystem. Signed-off-by: Marc Zyngier Tested-by: Enric Balletbo i Serra Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal_hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index 0bd47007c57f..40c69a533b24 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -143,7 +143,7 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) INIT_LIST_HEAD(&hwmon->tz_list); strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); strreplace(hwmon->type, '-', '_'); - hwmon->device = hwmon_device_register_with_info(NULL, hwmon->type, + hwmon->device = hwmon_device_register_with_info(&tz->device, hwmon->type, hwmon, NULL, NULL); if (IS_ERR(hwmon->device)) { result = PTR_ERR(hwmon->device); From 5834edde914b042faedb9179386335927315767b Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 18 Jul 2018 12:13:07 +0530 Subject: [PATCH 24/34] thermal: tsens: Get rid of unused fields in structure status_field and trdy are unused in any of the tsens drivers. Remove them. Signed-off-by: Amit Kucheria Reviewed-by: Bjorn Andersson Acked-by: Rajendra Nayak Tested-by: Matthias Kaehlcke Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/tsens.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 911c1978892b..dc56e1e2a19e 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -77,9 +77,7 @@ struct tsens_device { struct device *dev; u32 num_sensors; struct regmap *map; - struct regmap_field *status_field; struct tsens_context ctx; - bool trdy; const struct tsens_ops *ops; struct tsens_sensor sensor[0]; }; From 4ce6dcfd0d38169d9067c768fcce8e0d49f60fac Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 18 Jul 2018 12:13:08 +0530 Subject: [PATCH 25/34] dt: thermal: tsens: Document the fallback DT property for v2 of TSENS IP We want to create common code for v2 of the TSENS IP block that is used in a large number of Qualcomm SoCs. "qcom,tsens-v2" should be able to handle most of the common functionality start with a common get_temp() function. It is also necessary to split out the memory regions for the TM and SROT register banks because their offsets are not constant across SoC families. Signed-off-by: Amit Kucheria Reviewed-by: Rob Herring Reviewed-by: Bjorn Andersson Tested-by: Matthias Kaehlcke Reviewed-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Eduardo Valentin --- .../bindings/thermal/qcom-tsens.txt | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt index 06195e8f35e2..1d9e8cf61018 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt @@ -1,18 +1,28 @@ * QCOM SoC Temperature Sensor (TSENS) Required properties: -- compatible : - - "qcom,msm8916-tsens" : For 8916 Family of SoCs - - "qcom,msm8974-tsens" : For 8974 Family of SoCs - - "qcom,msm8996-tsens" : For 8996 Family of SoCs +- compatible: + Must be one of the following: + - "qcom,msm8916-tsens" (MSM8916) + - "qcom,msm8974-tsens" (MSM8974) + - "qcom,msm8996-tsens" (MSM8996) + - "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998) + - "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845) + The generic "qcom,tsens-v2" property must be used as a fallback for any SoC + with version 2 of the TSENS IP. MSM8996 is the only exception because the + generic property did not exist when support was added. + +- reg: Address range of the thermal registers. + New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM + register spaces separately, with order being TM before SROT. + See Example 2, below. -- reg: Address range of the thermal registers - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. - #qcom,sensors: Number of sensors in tsens block - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify nvmem cells -Example: +Example 1 (legacy support before a fallback tsens-v2 property was introduced): tsens: thermal-sensor@900000 { compatible = "qcom,msm8916-tsens"; reg = <0x4a8000 0x2000>; @@ -20,3 +30,12 @@ tsens: thermal-sensor@900000 { nvmem-cell-names = "caldata", "calsel"; #thermal-sensor-cells = <1>; }; + +Example 2 (for any platform containing v2 of the TSENS IP): +tsens0: thermal-sensor@c263000 { + compatible = "qcom,sdm845-tsens", "qcom,tsens-v2"; + reg = <0xc263000 0x1ff>, /* TM */ + <0xc222000 0x1ff>; /* SROT */ + #qcom,sensors = <13>; + #thermal-sensor-cells = <1>; + }; From 5b1283984fa39933e094d237387ad8fd39527fc1 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 18 Jul 2018 12:13:09 +0530 Subject: [PATCH 26/34] thermal: tsens: Add support to split up register address space into two There are two banks of registers for v2 TSENS IPs: SROT and TM. On older SoCs these were contiguous, leading to DTs mapping them as one register address space of size 0x2000. In newer SoCs, these two banks are not contiguous anymore. Add logic to init_common() to differentiate between old and new DTs and adjust associated offsets for the TM register bank so that the old DTs will continue to function correctly. Signed-off-by: Amit Kucheria Reviewed-by: Bjorn Andersson Tested-by: Matthias Kaehlcke Reviewed-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/tsens-8996.c | 4 ++-- drivers/thermal/qcom/tsens-common.c | 12 ++++++++++++ drivers/thermal/qcom/tsens.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/qcom/tsens-8996.c b/drivers/thermal/qcom/tsens-8996.c index e1f77818d8fa..3e60cecd2c45 100644 --- a/drivers/thermal/qcom/tsens-8996.c +++ b/drivers/thermal/qcom/tsens-8996.c @@ -16,7 +16,7 @@ #include #include "tsens.h" -#define STATUS_OFFSET 0x10a0 +#define STATUS_OFFSET 0xa0 #define LAST_TEMP_MASK 0xfff #define STATUS_VALID_BIT BIT(21) #define CODE_SIGN_BIT BIT(11) @@ -28,7 +28,7 @@ static int get_temp_8996(struct tsens_device *tmdev, int id, int *temp) unsigned int sensor_addr; int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret; - sensor_addr = STATUS_OFFSET + s->hw_id * 4; + sensor_addr = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; ret = regmap_read(tmdev->map, sensor_addr, &code); if (ret) return ret; diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index b1449ad67fc0..c22dc18c7c65 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "tsens.h" @@ -126,11 +127,22 @@ static const struct regmap_config tsens_config = { int __init init_common(struct tsens_device *tmdev) { void __iomem *base; + struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node); + if (!op) + return -EINVAL; base = of_iomap(tmdev->dev->of_node, 0); if (!base) return -EINVAL; + /* The driver only uses the TM register address space for now */ + if (op->num_resources > 1) { + tmdev->tm_offset = 0; + } else { + /* old DTs where SROT and TM were in a contiguous 2K block */ + tmdev->tm_offset = 0x1000; + } + tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config); if (IS_ERR(tmdev->map)) { iounmap(base); diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index dc56e1e2a19e..d785b37b47d2 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -77,6 +77,7 @@ struct tsens_device { struct device *dev; u32 num_sensors; struct regmap *map; + u32 tm_offset; struct tsens_context ctx; const struct tsens_ops *ops; struct tsens_sensor sensor[0]; From 770324a4bf2ffbcab5692d473c3f3f0e36b5a289 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 18 Jul 2018 12:13:11 +0530 Subject: [PATCH 27/34] thermal: tsens: Rename tsens-8996 to tsens-v2 for reuse The TSENS block inside the 8996 is internally classified as version 2 of the IP. Several other SoC families use this block and can share this code. We rename get_temp() to reflect that it can be used across the v2 family. Signed-off-by: Amit Kucheria Reviewed-by: Bjorn Andersson Tested-by: Matthias Kaehlcke Reviewed-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/Makefile | 2 +- .../thermal/qcom/{tsens-8996.c => tsens-v2.c} | 25 ++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) rename drivers/thermal/qcom/{tsens-8996.c => tsens-v2.c} (66%) diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 2cc2193637e7..a821929ede0b 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o -qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o +qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o diff --git a/drivers/thermal/qcom/tsens-8996.c b/drivers/thermal/qcom/tsens-v2.c similarity index 66% rename from drivers/thermal/qcom/tsens-8996.c rename to drivers/thermal/qcom/tsens-v2.c index 3e60cecd2c45..44d3736109d6 100644 --- a/drivers/thermal/qcom/tsens-8996.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -1,27 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * Copyright (c) 2018, Linaro Limited */ -#include #include #include "tsens.h" -#define STATUS_OFFSET 0xa0 -#define LAST_TEMP_MASK 0xfff +#define STATUS_OFFSET 0xa0 +#define LAST_TEMP_MASK 0xfff #define STATUS_VALID_BIT BIT(21) #define CODE_SIGN_BIT BIT(11) -static int get_temp_8996(struct tsens_device *tmdev, int id, int *temp) +static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) { struct tsens_sensor *s = &tmdev->sensor[id]; u32 code; @@ -73,12 +64,12 @@ done: return 0; } -static const struct tsens_ops ops_8996 = { +static const struct tsens_ops ops_generic_v2 = { .init = init_common, - .get_temp = get_temp_8996, + .get_temp = get_temp_tsens_v2, }; const struct tsens_data data_8996 = { .num_sensors = 13, - .ops = &ops_8996, + .ops = &ops_generic_v2, }; From 191dc74bad60e1462094b2e25321479e7eb17cdc Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 18 Jul 2018 12:13:12 +0530 Subject: [PATCH 28/34] thermal: tsens: Add generic support for TSENS v2 IP SDM845 uses v2 of the TSENS IP block but the get_temp() function appears to be identical across v2.x.y in code seen so far. We use the generic get_temp() function defined as part of ops_generic_v2. Signed-off-by: Amit Kucheria Reviewed-by: Bjorn Andersson Tested-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/tsens-v2.c | 5 +++++ drivers/thermal/qcom/tsens.c | 3 +++ drivers/thermal/qcom/tsens.h | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 44d3736109d6..f40150fd7eae 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -69,6 +69,11 @@ static const struct tsens_ops ops_generic_v2 = { .get_temp = get_temp_tsens_v2, }; +const struct tsens_data data_tsens_v2 = { + .ops = &ops_generic_v2, +}; + +/* Kept around for backward compatibility with old msm8996.dtsi */ const struct tsens_data data_8996 = { .num_sensors = 13, .ops = &ops_generic_v2, diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 3440166c2ae9..a2c9bfae3d86 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -72,6 +72,9 @@ static const struct of_device_id tsens_table[] = { }, { .compatible = "qcom,msm8996-tsens", .data = &data_8996, + }, { + .compatible = "qcom,tsens-v2", + .data = &data_tsens_v2, }, {} }; diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index d785b37b47d2..14331eb45a86 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -88,6 +88,9 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32); int init_common(struct tsens_device *); int get_temp_common(struct tsens_device *, int, int *); -extern const struct tsens_data data_8916, data_8974, data_8960, data_8996; +/* TSENS v1 targets */ +extern const struct tsens_data data_8916, data_8974, data_8960; +/* TSENS v2 targets */ +extern const struct tsens_data data_8996, data_tsens_v2; #endif /* __QCOM_TSENS_H__ */ From e0fe01426c50f54d06b6ff69de2be536ec0a3256 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 26 Jul 2018 16:03:08 +0530 Subject: [PATCH 29/34] thermal: tsens: Rename variable We're actually reading the temperature from the status register. Fix the variable name to reflect that. Signed-off-by: Amit Kucheria Reviewed-by: Matthias Kaehlcke Reviewed-by: Bjorn Andersson Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/tsens-common.c | 6 +++--- drivers/thermal/qcom/tsens-v2.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index c22dc18c7c65..25e7f247b027 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -104,11 +104,11 @@ int get_temp_common(struct tsens_device *tmdev, int id, int *temp) { struct tsens_sensor *s = &tmdev->sensor[id]; u32 code; - unsigned int sensor_addr; + unsigned int status_reg; int last_temp = 0, ret; - sensor_addr = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET; - ret = regmap_read(tmdev->map, sensor_addr, &code); + status_reg = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET; + ret = regmap_read(tmdev->map, status_reg, &code); if (ret) return ret; last_temp = code & SN_ST_TEMP_MASK; diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index f40150fd7eae..908e3dcb2d5c 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -16,11 +16,11 @@ static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) { struct tsens_sensor *s = &tmdev->sensor[id]; u32 code; - unsigned int sensor_addr; + unsigned int status_reg; int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret; - sensor_addr = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; - ret = regmap_read(tmdev->map, sensor_addr, &code); + status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; + ret = regmap_read(tmdev->map, status_reg, &code); if (ret) return ret; last_temp = code & LAST_TEMP_MASK; @@ -28,7 +28,7 @@ static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) goto done; /* Try a second time */ - ret = regmap_read(tmdev->map, sensor_addr, &code); + ret = regmap_read(tmdev->map, status_reg, &code); if (ret) return ret; if (code & STATUS_VALID_BIT) { @@ -39,7 +39,7 @@ static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) } /* Try a third/last time */ - ret = regmap_read(tmdev->map, sensor_addr, &code); + ret = regmap_read(tmdev->map, status_reg, &code); if (ret) return ret; if (code & STATUS_VALID_BIT) { From faa590baf8dfe5ad877e062f18de4419e4d174f7 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 26 Jul 2018 16:03:09 +0530 Subject: [PATCH 30/34] thermal: tsens: switch from of_iomap() to devm_ioremap_resource() devm_ioremap_resources() automatically requests resources (so that the I/O region shows up in /proc/iomem) and devm_ wrappers do better error handling and unmapping of the I/O region when needed. Signed-off-by: Amit Kucheria Reviewed-by: Matthias Kaehlcke Reviewed-by: Bjorn Andersson Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/tsens-common.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index 25e7f247b027..6207d8d92351 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -127,13 +127,11 @@ static const struct regmap_config tsens_config = { int __init init_common(struct tsens_device *tmdev) { void __iomem *base; + struct resource *res; struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node); if (!op) return -EINVAL; - base = of_iomap(tmdev->dev->of_node, 0); - if (!base) - return -EINVAL; /* The driver only uses the TM register address space for now */ if (op->num_resources > 1) { @@ -143,11 +141,14 @@ int __init init_common(struct tsens_device *tmdev) tmdev->tm_offset = 0x1000; } + res = platform_get_resource(op, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&op->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config); - if (IS_ERR(tmdev->map)) { - iounmap(base); + if (IS_ERR(tmdev->map)) return PTR_ERR(tmdev->map); - } return 0; } From 432121adf5e880240237bd9b15ec0ab995d7ea1f Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 26 Jul 2018 16:03:10 +0530 Subject: [PATCH 31/34] thermal: tsens: Fix negative temperature reporting The current code will always return 0xffffffff in case of negative temperatures due to a bug in how the binary sign extension is being done. Use sign_extend32() instead. Signed-off-by: Amit Kucheria Reviewed-by: Matthias Kaehlcke Reviewed-by: Bjorn Andersson Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom/tsens-v2.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 908e3dcb2d5c..44da02f594ac 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -5,19 +5,20 @@ */ #include +#include #include "tsens.h" #define STATUS_OFFSET 0xa0 #define LAST_TEMP_MASK 0xfff #define STATUS_VALID_BIT BIT(21) -#define CODE_SIGN_BIT BIT(11) static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) { struct tsens_sensor *s = &tmdev->sensor[id]; u32 code; unsigned int status_reg; - int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret; + u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0; + int ret; status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; ret = regmap_read(tmdev->map, status_reg, &code); @@ -54,12 +55,8 @@ static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) else if (last_temp2 == last_temp3) last_temp = last_temp3; done: - /* Code sign bit is the sign extension for a negative value */ - if (last_temp & CODE_SIGN_BIT) - last_temp |= ~CODE_SIGN_BIT; - - /* Temperatures are in deciCelicius */ - *temp = last_temp * 100; + /* Convert temperature from deciCelsius to milliCelsius */ + *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100; return 0; } From c0c04707033c71d0490a412b0a941d87011949a3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 17 Jul 2018 17:46:17 +0200 Subject: [PATCH 32/34] thermal: samsung: Remove Exynos5440 clock handling left-overs Commit 8014220d48e7 ("thermal: samsung: Remove support for Exynos5440") removed the Exynos5440 specific part of code for accessing TMU interrupt registers but the surrounding clock handling was left. Clean it up. Signed-off-by: Krzysztof Kozlowski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index a992e51ef065..48eef552cba4 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -789,11 +789,6 @@ static void exynos_tmu_work(struct work_struct *work) struct exynos_tmu_data *data = container_of(work, struct exynos_tmu_data, irq_work); - if (!IS_ERR(data->clk_sec)) - clk_enable(data->clk_sec); - if (!IS_ERR(data->clk_sec)) - clk_disable(data->clk_sec); - thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED); mutex_lock(&data->lock); From 542cdf4068049458e1411b120bd5a4bbe3ddc49a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 24 Jul 2018 13:14:13 +0200 Subject: [PATCH 33/34] thermal: rcar_thermal: avoid NULL dereference in absence of IRQ resources Ensure that the base address used by a call to rcar_thermal_common_write() may be NULL if the SOC supports interrupts for use with the thermal device but none are defined in DT as is the case for R-Car H1 (r8a7779). Guard against this condition to prevent a NULL dereference when the device is probed. Tested on: * R-Mobile APE6 (r8a73a4) / APE6EVM * R-Car H1 (r8a7779) / Marzen * R-Car H2 (r8a7790) / Lager * R-Car M2-W (r8a7791) / Koelsch * R-Car M2-N (r8a7793) / Gose * R-Car D3 ES1.0 (r8a77995) / Draak Fixes: 1969d9dc2079 ("thermal: rcar_thermal: add r8a77995 support") Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 45fb284d4c11..e77e63070e99 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -598,7 +598,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) enr_bits |= 3 << (i * 8); } - if (enr_bits) + if (common->base && enr_bits) rcar_thermal_common_write(common, ENR, enr_bits); dev_info(dev, "%d sensor probed\n", i); From 84b64de597bcc26549a7cbfe2fa8022bbc142daa Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 30 Jul 2018 07:07:03 +0000 Subject: [PATCH 34/34] thermal: armada: fix copy-paste error in armada_thermal_probe() The return value from devm_kzalloc() is not checked correctly. The test is done against a wrong variable. Fix it. Fixes: e72f03ef2543 ("thermal: armada: use the resource managed registration helper alternative") Signed-off-by: Wei Yongjun Reviewed-by: Daniel Lezcano Reviewed-by: Miquel Raynal Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 4164a5a4e480..2c2f6d93034e 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -611,7 +611,7 @@ static int armada_thermal_probe(struct platform_device *pdev) return -ENOMEM; drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); - if (!priv) + if (!drvdata) return -ENOMEM; priv->dev = &pdev->dev;