diff --git a/drivers/thermal/samsung/exynos_acpm_tmu.c b/drivers/thermal/samsung/exynos_acpm_tmu.c index 045021f94959..7d0d163ff11b 100644 --- a/drivers/thermal/samsung/exynos_acpm_tmu.c +++ b/drivers/thermal/samsung/exynos_acpm_tmu.c @@ -16,13 +16,13 @@ #include #include #include +#include #include "exynos_acpm_tmu.h" static unsigned int acpm_tmu_ch_num, acpm_tmu_size; static bool acpm_tmu_test_mode; static bool acpm_tmu_log; -static bool acpm_tmu_ipc_blocked; bool exynos_acpm_tmu_is_test_mode(void) { @@ -34,11 +34,6 @@ void exynos_acpm_tmu_set_test_mode(bool mode) acpm_tmu_test_mode = mode; } -void exynos_acpm_tmu_set_ipc_blocked(bool mode) -{ - acpm_tmu_ipc_blocked = mode; -} - void exynos_acpm_tmu_log(bool mode) { acpm_tmu_log = mode; @@ -66,9 +61,6 @@ static void exynos_acpm_tmu_ipc_send_data(union tmu_ipc_message *message) int ret; unsigned long long before, after, latency; - if (acpm_tmu_ipc_blocked) - return; - config.cmd = message->data; config.response = true; @@ -105,6 +97,49 @@ int exynos_acpm_tmu_set_init(struct acpm_tmu_cap *cap) return 0; } +/* + * TMU_IPC_READ_TEMP + * + * - tz: thermal zone index registered in device tree + */ +int exynos_acpm_tmu_set_read_temp(int tz, int *temp, int *stat) +{ + union tmu_ipc_message message; + + if (acpm_tmu_test_mode) + return -1; + + memset(&message, 0, sizeof(message)); + + message.req.type = TMU_IPC_READ_TEMP; + message.req.tzid = tz; + + exynos_acpm_tmu_ipc_send_data(&message); + if (acpm_tmu_log) { + int i; + u8 *temp = &message.resp.rsvd0; + pr_info_ratelimited("[acpm_tmu] tz %d temp 0:%d 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d\n", + tz, + message.resp.rsvd0, + message.resp.rsvd1, + message.resp.rsvd2, + message.resp.rsvd3, + message.resp.rsvd4, + message.resp.rsvd5, + message.resp.rsvd6); + for (i = 0; i < 7; i++) { + char name[40]; + + scnprintf(name, sizeof(name), "TMU%d_%d", tz, i); + trace_clock_set_rate(name, temp[i], raw_smp_processor_id()); + } + } + *temp = message.resp.temp; + *stat = message.resp.stat; + + return 0; +} + /* * TMU_IPC_AP_SUSPEND */ @@ -288,6 +323,24 @@ void exynos_acpm_tmu_tz_control(int tz, bool enable) } } +void exynos_acpm_tmu_clear_tz_irq(int tz) +{ + union tmu_ipc_message message; + + memset(&message, 0, sizeof(message)); + message.req.type = TMU_IPC_IRQ_CLEAR; + message.req.tzid = tz; + + exynos_acpm_tmu_ipc_send_data(&message); + if (acpm_tmu_log) { + pr_info_ratelimited("[acpm_tmu] data 0:0x%08x 1:0x%08x 2:0x%08x 3:0x%08x\n", + message.data[0], + message.data[1], + message.data[2], + message.data[3]); + } +} + void exynos_acpm_tmu_set_emul_temp(int tz, unsigned char temp) { union tmu_ipc_message message; diff --git a/drivers/thermal/samsung/exynos_acpm_tmu.h b/drivers/thermal/samsung/exynos_acpm_tmu.h index cbf468f9698c..246e2a54195e 100644 --- a/drivers/thermal/samsung/exynos_acpm_tmu.h +++ b/drivers/thermal/samsung/exynos_acpm_tmu.h @@ -111,19 +111,20 @@ struct acpm_tmu_cap { }; int exynos_acpm_tmu_set_init(struct acpm_tmu_cap *cap); +int exynos_acpm_tmu_set_read_temp(int tz, int *temp, int *stat); int exynos_acpm_tmu_set_suspend(int flag); int exynos_acpm_tmu_set_cp_call(void); int exynos_acpm_tmu_set_resume(void); int exynos_acpm_tmu_ipc_dump(int no, unsigned int dump[]); bool exynos_acpm_tmu_is_test_mode(void); void exynos_acpm_tmu_set_test_mode(bool mode); -void exynos_acpm_tmu_set_ipc_blocked(bool mode); void exynos_acpm_tmu_log(bool mode); void exynos_acpm_tmu_set_threshold(int tz, unsigned char temp[]); void exynos_acpm_tmu_set_hysteresis(int tz, unsigned char hyst[]); void exynos_acpm_tmu_set_interrupt_enable(int tz, unsigned char inten); void exynos_acpm_tmu_tz_control(int tz, bool enable); +void exynos_acpm_tmu_clear_tz_irq(int tz); void exynos_acpm_tmu_set_emul_temp(int tz, unsigned char temp); int exynos_acpm_tmu_init(void); diff --git a/drivers/thermal/samsung/gs101_tmu.h b/drivers/thermal/samsung/gs101_tmu.h index a3f88534b364..ffbf4724d4ed 100644 --- a/drivers/thermal/samsung/gs101_tmu.h +++ b/drivers/thermal/samsung/gs101_tmu.h @@ -132,89 +132,4 @@ struct throttling_stats { ktime_t *hardlimit_time_in_state; }; -#define TMU_TRIMINFO_CONFIG_REG 0 -#define TMU_TRIMINFO_CONFIG_CALIB_SEL_MASK 1 - -#define TMU_TRIMINFO0 0x0010 -#define TMU_TRIMINFO_REG(i) (TMU_TRIMINFO0 + 0x4 * (i)) -#define TMU_TRIMINFO_85_SHIFT 9 -#define TMU_TRIMINFO_25_85_MASK 0x1ff - -#define TMU_CURRENT_TEMP_P1_P0 0x0084 -#define TMU_CURRENT_TEMP_REG(i) (TMU_CURRENT_TEMP_P1_P0 + 0x4 * ((i) / 2)) -#define TMU_CURRENT_TEMP_SHIFT(i) (((i) % 2) * 16) -#define TMU_CURRENT_TEMP_MASK 0x1ff - -#define TMU_INTPEND_P0 0x00F8 -#define TMU_INTPEND_REG(i) (TMU_INTPEND_P0 + 0x50 * (i)) - -#define TMU_1P_TRIM_TEMP_25 25 -#define TMU_2P_TRIM_TEMP_85 85 - -#define TMU_UNKNOWN_TEMP 0 -#define TMU_MAX_TEMP 125 -#define TMU_MIN_TEMP 10 -#define TMU_SENSOR_PROBE_NUM 16 - -enum tmu_zone_t { - TMU_TOP = 0, - TMU_SUB = 1, - TMU_END = 2, -}; - -enum tmu_sensor_t { - TMU_P0_SENSOR = 0, - TMU_P1_SENSOR = 1, - TMU_P2_SENSOR = 2, - TMU_P3_SENSOR = 3, - TMU_P4_SENSOR = 4, - TMU_P5_SENSOR = 5, - TMU_P6_SENSOR = 6, - TMU_P7_SENSOR = 7, - TMU_P8_SENSOR = 8, - TMU_P9_SENSOR = 9, - TMU_P10_SENSOR = 10, - TMU_P11_SENSOR = 11, - TMU_P12_SENSOR = 12, - TMU_P13_SENSOR = 13, - TMU_P14_SENSOR = 14, - TMU_P15_SENSOR = 15, -}; - -#define TMU_P0_SENSOR_MASK (1 << TMU_P0_SENSOR) -#define TMU_P1_SENSOR_MASK (1 << TMU_P1_SENSOR) -#define TMU_P2_SENSOR_MASK (1 << TMU_P2_SENSOR) -#define TMU_P3_SENSOR_MASK (1 << TMU_P3_SENSOR) -#define TMU_P4_SENSOR_MASK (1 << TMU_P4_SENSOR) -#define TMU_P5_SENSOR_MASK (1 << TMU_P5_SENSOR) -#define TMU_P6_SENSOR_MASK (1 << TMU_P6_SENSOR) -#define TMU_P7_SENSOR_MASK (1 << TMU_P7_SENSOR) -#define TMU_P8_SENSOR_MASK (1 << TMU_P8_SENSOR) -#define TMU_P9_SENSOR_MASK (1 << TMU_P9_SENSOR) -#define TMU_P10_SENSOR_MASK (1 << TMU_P10_SENSOR) -#define TMU_P11_SENSOR_MASK (1 << TMU_P11_SENSOR) -#define TMU_P12_SENSOR_MASK (1 << TMU_P12_SENSOR) -#define TMU_P13_SENSOR_MASK (1 << TMU_P13_SENSOR) -#define TMU_P14_SENSOR_MASK (1 << TMU_P14_SENSOR) -#define TMU_P15_SENSOR_MASK (1 << TMU_P15_SENSOR) - -struct sensor_data { - enum tmu_sensor_t probe_id; - u16 trim_info_25; - u16 trim_info_85; -}; - -enum trim_type_t { - ONE_POINT_TRIMMING = 0, - TWO_POINT_TRIMMING = 1, -}; - -struct thermal_zone_data { - enum tmu_zone_t tmu_zone_id; - enum trim_type_t trim_type; - u16 sensors_mask; - struct sensor_data sensors[TMU_SENSOR_PROBE_NUM]; - u16 sensor_cnt; -}; - #endif /* _GS101_TMU_H */ diff --git a/drivers/thermal/samsung/gs101_tmu_v2.c b/drivers/thermal/samsung/gs101_tmu_v2.c index a504e5c448e7..501358f335d6 100644 --- a/drivers/thermal/samsung/gs101_tmu_v2.c +++ b/drivers/thermal/samsung/gs101_tmu_v2.c @@ -51,212 +51,6 @@ #define INVALID_TRIP -1 -enum tmu_grp_idx_t { - TZ_BIG = 0, - TZ_MID = 1, - TZ_LIT = 2, - TZ_GPU = 3, - TZ_ISP = 4, - TZ_TPU = 5, - TZ_END = 6, -}; - -#define TZ_BIG_SENSOR_MASK (TMU_P0_SENSOR_MASK | \ - TMU_P6_SENSOR_MASK | \ - TMU_P7_SENSOR_MASK | \ - TMU_P8_SENSOR_MASK | \ - TMU_P9_SENSOR_MASK) -#define TZ_MID_SENSOR_MASK (TMU_P4_SENSOR_MASK | \ - TMU_P5_SENSOR_MASK) -#define TZ_LIT_SENSOR_MASK (TMU_P1_SENSOR_MASK | \ - TMU_P2_SENSOR_MASK) -#define TZ_GPU_SENSOR_MASK (TMU_P1_SENSOR_MASK | \ - TMU_P2_SENSOR_MASK | \ - TMU_P3_SENSOR_MASK | \ - TMU_P4_SENSOR_MASK | \ - TMU_P5_SENSOR_MASK | \ - TMU_P6_SENSOR_MASK | \ - TMU_P7_SENSOR_MASK) -#define TZ_ISP_SENSOR_MASK (TMU_P14_SENSOR_MASK) -#define TZ_TPU_SENSOR_MASK (TMU_P8_SENSOR_MASK | \ - TMU_P9_SENSOR_MASK | \ - TMU_P10_SENSOR_MASK | \ - TMU_P11_SENSOR_MASK) - -static struct thermal_zone_data tz_config[] = { - [TZ_BIG] = { - .tmu_zone_id = TMU_TOP, - .sensors_mask = TZ_BIG_SENSOR_MASK, - }, - [TZ_MID] = { - .tmu_zone_id = TMU_TOP, - .sensors_mask = TZ_MID_SENSOR_MASK, - }, - [TZ_LIT] = { - .tmu_zone_id = TMU_TOP, - .sensors_mask = TZ_LIT_SENSOR_MASK, - }, - [TZ_GPU] = { - .tmu_zone_id = TMU_SUB, - .sensors_mask = TZ_GPU_SENSOR_MASK, - }, - [TZ_ISP] = { - .tmu_zone_id = TMU_SUB, - .sensors_mask = TZ_ISP_SENSOR_MASK, - }, - [TZ_TPU] = { - .tmu_zone_id = TMU_SUB, - .sensors_mask = TZ_TPU_SENSOR_MASK, - }, -}; - -static int gs101_tmu_tz_config_init(struct platform_device *pdev) -{ - struct gs101_tmu_data *pdata = platform_get_drvdata(pdev); - struct thermal_zone_data *tz_config_p; - enum trim_type_t tmu_trim_type[TMU_END]; - u16 cnt; - u32 val; - enum tmu_zone_t tmu_zone_id; - enum tmu_grp_idx_t tmu_grp_idx; - enum tmu_sensor_t probe_id; - - for (tmu_zone_id = 0; tmu_zone_id < TMU_END; tmu_zone_id++) { - val = readl(pdata->base + TMU_TRIMINFO_CONFIG_REG); - tmu_trim_type[tmu_zone_id] = (val & - TMU_TRIMINFO_CONFIG_CALIB_SEL_MASK); - } - - for (tmu_grp_idx = 0; tmu_grp_idx < TZ_END; tmu_grp_idx++) { - tz_config_p = &tz_config[tmu_grp_idx]; - if (tz_config_p->tmu_zone_id >= TMU_END) { - dev_err(&pdev->dev, - "Invalid tmu zone id %d for tz id %d\n", - tz_config_p->tmu_zone_id, tmu_grp_idx); - return -EINVAL; - break; - } - tz_config_p->trim_type = - tmu_trim_type[tz_config_p->tmu_zone_id]; - - cnt = 0; - for (probe_id = 0; probe_id < TMU_SENSOR_PROBE_NUM; probe_id++) { - if ((1 << probe_id) & tz_config_p->sensors_mask) { - tz_config_p->sensors[cnt].probe_id = probe_id; - val = readl(pdata->base + - TMU_TRIMINFO_REG(probe_id)); - tz_config_p->sensors[cnt].trim_info_25 = - (val & TMU_TRIMINFO_25_85_MASK); - tz_config_p->sensors[cnt].trim_info_85 = - ((val >> TMU_TRIMINFO_85_SHIFT) & - TMU_TRIMINFO_25_85_MASK); - cnt++; - } - } - tz_config_p->sensor_cnt = cnt; - } - - return 0; -} - -static int gs101_tmu_get_sensor_temp(struct gs101_tmu_data *pdata, - enum trim_type_t trim_type, - struct sensor_data *sensor_data_p, - int *temp) -{ - enum tmu_sensor_t probe_id = sensor_data_p->probe_id; - u32 temp_code; - - temp_code = readl(pdata->base + TMU_CURRENT_TEMP_REG(probe_id)); - temp_code = ((temp_code >> TMU_CURRENT_TEMP_SHIFT(probe_id)) & - TMU_CURRENT_TEMP_MASK); - - switch (trim_type) { - case ONE_POINT_TRIMMING: - *temp = (temp_code - sensor_data_p->trim_info_25) + - TMU_1P_TRIM_TEMP_25; - case TWO_POINT_TRIMMING: - *temp = (temp_code - sensor_data_p->trim_info_25) * - (TMU_2P_TRIM_TEMP_85 - TMU_1P_TRIM_TEMP_25) / - (sensor_data_p->trim_info_85 - - sensor_data_p->trim_info_25) + - TMU_1P_TRIM_TEMP_25; - } - - if (*temp > TMU_MAX_TEMP) { - *temp = TMU_MAX_TEMP; - } else if (*temp < TMU_MIN_TEMP) { - *temp = TMU_MIN_TEMP; - } - - return 0; -} - -static int gs101_tmu_get_tz_temp(struct gs101_tmu_data *pdata, int *temp) -{ - struct thermal_zone_data *tz_config_p = &tz_config[pdata->id]; - struct thermal_zone_device *tz = pdata->tzd; - int sensor_temp = TMU_UNKNOWN_TEMP; - int max_sensor_temp = TMU_UNKNOWN_TEMP; - u16 cnt; - char name[40]; - - for (cnt = 0; cnt < tz_config_p->sensor_cnt; cnt++) { - gs101_tmu_get_sensor_temp(pdata, - tz_config_p->trim_type, - &(tz_config_p->sensors[cnt]), - &sensor_temp); - - dev_dbg_ratelimited(&tz->device, "tz %d temp %d:%d", - pdata->id, cnt, sensor_temp); - scnprintf(name, sizeof(name), "TMU%d_%d", pdata->id, cnt); - trace_clock_set_rate(name, sensor_temp, raw_smp_processor_id()); - - if (sensor_temp > max_sensor_temp) - max_sensor_temp = sensor_temp; - } - - *temp = max_sensor_temp; - return 0; -} - -static int gs101_tmu_clear_tz_irq(struct gs101_tmu_data *pdata) -{ - struct thermal_zone_data *tz_config_p = &tz_config[pdata->id]; - u32 val; - u16 cnt; - enum tmu_sensor_t probe_id; - - mutex_lock(&pdata->lock); - for (cnt = 0; cnt < tz_config_p->sensor_cnt; cnt++) { - probe_id = tz_config_p->sensors[cnt].probe_id; - val = readl(pdata->base + TMU_INTPEND_REG(probe_id)); - exynos_acpm_tmu_set_ipc_blocked(true); - writel(val, pdata->base + TMU_INTPEND_REG(probe_id)); - exynos_acpm_tmu_set_ipc_blocked(false); - } - mutex_unlock(&pdata->lock); - - return 0; -} - -static bool has_tz_pending_irq(struct gs101_tmu_data *pdata) -{ - struct thermal_zone_data *tz_config_p = &tz_config[pdata->id]; - u32 val; - u16 cnt; - enum tmu_sensor_t probe_id; - - for (cnt = 0; cnt < tz_config_p->sensor_cnt; cnt++) { - probe_id = tz_config_p->sensors[cnt].probe_id; - val = readl(pdata->base + TMU_INTPEND_REG(probe_id)); - if (val) - return true; - } - - return false; -} - /** * mul_frac() - multiply two fixed-point numbers * @x: first multiplicand @@ -401,13 +195,6 @@ static int gs101_tmu_initialize(struct platform_device *pdev) hysteresis[i] = (unsigned char)(temp / MCELSIUS); } - - ret = gs101_tmu_tz_config_init(pdev); - if (ret) { - dev_err(&pdev->dev, "Failed to initialize tmu tz config\n"); - goto out; - } - exynos_acpm_tmu_set_threshold(data->id, threshold); exynos_acpm_tmu_set_hysteresis(data->id, hysteresis); exynos_acpm_tmu_set_interrupt_enable(data->id, inten); @@ -440,15 +227,16 @@ static int gs101_get_temp(void *p, int *temp) unsigned int mcinfo_temp = 0; unsigned int i; #endif - int tz_temp = 0; + int acpm_temp = 0, stat = 0; if (!data || !data->enabled) return -EINVAL; mutex_lock(&data->lock); - gs101_tmu_get_tz_temp(data, &tz_temp); - *temp = tz_temp * MCELSIUS; + exynos_acpm_tmu_set_read_temp(data->id, &acpm_temp, &stat); + + *temp = acpm_temp * MCELSIUS; if (data->limited_frequency) { if (!data->limited) { @@ -848,16 +636,28 @@ static void gs101_tmu_work(struct kthread_work *work) struct gs101_tmu_data *data = container_of(work, struct gs101_tmu_data, irq_work); struct thermal_zone_device *tz = data->tzd; + struct gs101_pi_param *params = data->pi_param; gs101_report_trigger(data); + mutex_lock(&data->lock); - gs101_tmu_clear_tz_irq(data); + exynos_acpm_tmu_clear_tz_irq(data->id); dev_dbg_ratelimited(&tz->device, "IRQ handled: tz:%s, temp:%d\n", tz->type, tz->temperature); - if (data->use_pi_thermal) + mutex_unlock(&data->lock); + + if (data->use_pi_thermal) { + if (params->switched_on) + /* + * handle hotplug and limited_threshold but do + * not trigger polling if it is already on + */ + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + else gs101_pi_thermal(data); + } enable_irq(data->irq); } @@ -867,13 +667,8 @@ static irqreturn_t gs101_tmu_irq(int irq, void *id) struct gs101_tmu_data *data = id; disable_irq_nosync(irq); - if (has_tz_pending_irq(data)) { - kthread_queue_work(&data->thermal_worker, &data->irq_work); - goto irq_handler_exit; - } - enable_irq(data->irq); + kthread_queue_work(&data->thermal_worker, &data->irq_work); -irq_handler_exit: return IRQ_HANDLED; } @@ -2669,12 +2464,18 @@ static int gs101_tmu_resume(struct device *dev) #if IS_ENABLED(CONFIG_EXYNOS_ACPM_THERMAL) struct gs101_tmu_data *data = platform_get_drvdata(pdev); struct cpumask mask; + int temp, stat; if (suspended_count == num_of_devices) exynos_acpm_tmu_set_resume(); gs101_tmu_control(pdev, true); + exynos_acpm_tmu_set_read_temp(data->id, &temp, &stat); + + pr_info("%s: thermal zone %d temp %d stat %d\n", + __func__, data->tzd->id, temp, stat); + enable_irq(data->irq); suspended_count--;