static int exynos_pm_notifier(struct notifier_block *notifier, unsigned long pm_event, void *v) { switch (pm_event) { case PM_SUSPEND_PREPARE: is_suspending = true; exynos_tmu_call_notifier(TMU_COLD); exynos_tmu_call_notifier(tmu_old_state); exynos_check_mif_noti_state(MEM_TH_TEMP2 - 1); exynos_gpu_call_notifier(GPU_COLD); break; case PM_POST_SUSPEND: is_suspending = false; break; } return NOTIFY_OK; }
static int exynos_pm_notifier(struct notifier_block *notifier, unsigned long pm_event, void *v) { switch (pm_event) { case PM_SUSPEND_PREPARE: exynos_tmu_call_notifier(1, old_hot); break; case PM_POST_SUSPEND: break; } return NOTIFY_OK; }
static int exynos_tmu_read(struct exynos_tmu_data *data) { u8 temp_code; int temp, i, max = INT_MIN, min = INT_MAX; int cold_event = 0; int hot_event = 0; enum tmu_noti_state_t cur_state; if (!th_zone || !th_zone->therm_dev) return -EPERM; mutex_lock(&data->lock); clk_enable(data->clk); for (i = 0; i < EXYNOS_TMU_COUNT; i++) { temp_code = readb(data->base[i] + EXYNOS_TMU_REG_CURRENT_TEMP); temp = code_to_temp(data, temp_code, i); if (temp < 0) continue; if (temp > max) max = temp; if (temp < min) min = temp; } clk_disable(data->clk); mutex_unlock(&data->lock); /* check current tmu state */ if (min <= COLD_TEMP && !old_cold) cold_event = 1; if (max >= HOT_CRITICAL_TEMP) cur_state = TMU_CRITICAL; else if (max > HOT_NORMAL_TEMP && max < HOT_CRITICAL_TEMP) cur_state = TMU_HOT; else if (max <= HOT_NORMAL_TEMP) cur_state = TMU_NORMAL; else cur_state = TMU_NORMAL; if (old_hot != cur_state) hot_event = cur_state; th_zone->therm_dev->last_temperature = max; exynos_tmu_call_notifier(cold_event, hot_event); return max; }
static int exynos_tmu_read(struct exynos_tmu_data *data) { u8 temp_code; int temp, i; int cold_event = old_cold; int hot_event = old_hot; int alltemp[EXYNOS_TMU_COUNT] = {0,}; if (!th_zone || !th_zone->therm_dev) return -EPERM; mutex_lock(&data->lock); clk_enable(data->clk); for (i = 0; i < EXYNOS_TMU_COUNT; i++) { temp_code = readb(data->base[i] + EXYNOS_TMU_REG_CURRENT_TEMP); temp = code_to_temp(data, temp_code); alltemp[i] = temp; } clk_disable(data->clk); mutex_unlock(&data->lock); if (temp <= THRESH_MEM_TEMP0) cold_event = TMU_COLD; else cold_event = TMU_NORMAL; if (old_hot != TMU_THR_LV3 && temp >= THRESH_MEM_TEMP2) hot_event = TMU_THR_LV3; else if (old_hot != TMU_THR_LV2 && (temp >= THRESH_MEM_TEMP1 && temp < THRESH_MEM_TEMP2)) hot_event = TMU_THR_LV2; else if (old_hot != TMU_THR_LV1 && (temp >= THRESH_MEM_TEMP0 && temp < THRESH_MEM_TEMP1)) hot_event = TMU_THR_LV1; sec_debug_aux_log(SEC_DEBUG_AUXLOG_THERMAL_CHANGE, "[TMU] %d", temp); //printk("[TMU] %s : Thermal Read %d C", __func__, temp); Found it! #ifdef CONFIG_EXYNOS4_EXPORT_TEMP tmu_curr_temperature = temp; #endif th_zone->therm_dev->last_temperature = temp; exynos_tmu_call_notifier(cold_event, hot_event); sec_debug_aux_log(SEC_DEBUG_AUXLOG_THERMAL_CHANGE, "[TMU] alltemp[0]: %d", alltemp[0]); return temp; }
static void exynos_check_tmu_noti_state(int min_temp, int max_temp) { enum tmu_noti_state_t cur_state; /* check current temperature state */ if (max_temp > HOT_CRITICAL_TEMP) cur_state = TMU_CRITICAL; else if (max_temp > HOT_NORMAL_TEMP && max_temp <= HOT_CRITICAL_TEMP) cur_state = TMU_HOT; else if (max_temp > COLD_TEMP && max_temp <= HOT_NORMAL_TEMP) cur_state = TMU_NORMAL; else cur_state = TMU_COLD; if (min_temp <= COLD_TEMP) cur_state = TMU_COLD; exynos_tmu_call_notifier(cur_state); }
static int __devinit exynos_tmu_probe(struct platform_device *pdev) { struct exynos_tmu_data *data; struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data; int ret, i; is_suspending = false; if (!pdata) pdata = exynos_get_driver_data(pdev); if (!pdata) { dev_err(&pdev->dev, "No platform init data supplied.\n"); return -ENODEV; } data = kzalloc(sizeof(struct exynos_tmu_data), GFP_KERNEL); if (!data) { dev_err(&pdev->dev, "Failed to allocate driver structure\n"); return -ENOMEM; } #ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ exynos_cpufreq_init_register_notifier(&exynos_cpufreq_nb); #endif INIT_WORK(&data->irq_work, exynos_tmu_work); for (i = 0; i < EXYNOS_TMU_COUNT; i++) { data->irq[i] = platform_get_irq(pdev, i); if (data->irq[i] < 0) { ret = data->irq[i]; dev_err(&pdev->dev, "Failed to get platform irq\n"); goto err_free; } data->mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); if (!data->mem[i]) { ret = -ENOENT; dev_err(&pdev->dev, "Failed to get platform resource\n"); goto err_free; } data->mem[i] = request_mem_region(data->mem[i]->start, resource_size(data->mem[i]), pdev->name); if (!data->mem[i]) { ret = -ENODEV; dev_err(&pdev->dev, "Failed to request memory region\n"); goto err_free; } data->base[i] = ioremap(data->mem[i]->start, resource_size(data->mem[i])); if (!data->base[i]) { ret = -ENODEV; dev_err(&pdev->dev, "Failed to ioremap memory\n"); goto err_mem_region; } ret = request_irq(data->irq[i], exynos_tmu_irq, IRQF_TRIGGER_RISING, "exynos-tmu", data); if (ret) { dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq[i]); goto err_io_remap; } } data->clk = clk_get(NULL, pdata->clk_name); if (IS_ERR(data->clk)) { ret = PTR_ERR(data->clk); dev_err(&pdev->dev, "Failed to get clock\n"); goto err_irq; } if (pdata->type == SOC_ARCH_EXYNOS5 || pdata->type == SOC_ARCH_EXYNOS4|| pdata->type == SOC_ARCH_EXYNOS3) data->soc = pdata->type; else { ret = -EINVAL; dev_err(&pdev->dev, "Platform not supported\n"); goto err_clk; } data->pdata = pdata; platform_set_drvdata(pdev, data); mutex_init(&data->lock); for (i = 0; i < EXYNOS_TMU_COUNT; i++) exynos_tmu_get_efuse(pdev, i); /*TMU initialization*/ for (i = 0; i < EXYNOS_TMU_COUNT; i++) { ret = exynos_tmu_initialize(pdev, i); if (ret) { dev_err(&pdev->dev, "Failed to initialize TMU[%d]\n", i); goto err_clk; } exynos_tmu_control(pdev, i, true); exynos_tmu_regdump(pdev, i); } /*Register the sensor with thermal management interface*/ (&exynos_sensor_conf)->private_data = data; exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en + pdata->trigger_level1_en + pdata->trigger_level2_en + pdata->trigger_level3_en; for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++) exynos_sensor_conf.trip_data.trip_val[i] = pdata->threshold + pdata->trigger_levels[i]; exynos_sensor_conf.cooling_data.freq_clip_count = pdata->freq_tab_count; for (i = 0; i < pdata->freq_tab_count; i++) { exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max = pdata->freq_tab[i].freq_clip_max; exynos_sensor_conf.cooling_data.freq_data[i].temp_level = pdata->freq_tab[i].temp_level; if (pdata->freq_tab[i].mask_val) exynos_sensor_conf.cooling_data.freq_data[i].mask_val = pdata->freq_tab[i].mask_val; else exynos_sensor_conf.cooling_data.freq_data[i].mask_val = cpu_all_mask; } for (i = 0; i <= THERMAL_TRIP_CRITICAL; i++) exynos_sensor_conf.cooling_data.size[i] = pdata->size[i]; #ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ exynos_sensor_conf.cooling_data_kfc.freq_clip_count = pdata->freq_tab_count; for (i = 0; i < pdata->freq_tab_count; i++) { exynos_sensor_conf.cooling_data_kfc.freq_data[i].freq_clip_max = pdata->freq_tab_kfc[i].freq_clip_max; exynos_sensor_conf.cooling_data_kfc.freq_data[i].temp_level = pdata->freq_tab_kfc[i].temp_level; if (pdata->freq_tab_kfc[i].mask_val) exynos_sensor_conf.cooling_data_kfc.freq_data[i].mask_val = pdata->freq_tab_kfc[i].mask_val; else exynos_sensor_conf.cooling_data_kfc.freq_data[i].mask_val = cpu_all_mask; } for (i = 0; i <= THERMAL_TRIP_CRITICAL; i++) exynos_sensor_conf.cooling_data_kfc.size[i] = pdata->size[i]; #endif register_pm_notifier(&exynos_pm_nb); exynos_tmu_pdev = pdev; #ifndef CONFIG_ARM_EXYNOS_MP_CPUFREQ ret = exynos_register_thermal(&exynos_sensor_conf); if (ret) { dev_err(&pdev->dev, "Failed to register thermal interface\n"); goto err_clk; } th_zone->exynos4_dev = pdev; ret = sysfs_create_group(&pdev->dev.kobj, &exynos_thermal_sensor_attr_group); if (ret) dev_err(&pdev->dev, "cannot create thermal sensor attributes\n"); #endif /* For low temperature compensation when boot time */ exynos_tmu_call_notifier(TMU_COLD); exynos_gpu_call_notifier(GPU_COLD); return 0; err_clk: platform_set_drvdata(pdev, NULL); clk_put(data->clk); err_irq: for (i = 0; i < EXYNOS_TMU_COUNT; i++) { if (data->irq[i]) free_irq(data->irq[i], data); } err_io_remap: for (i = 0; i < EXYNOS_TMU_COUNT; i++) { if (data->base[i]) iounmap(data->base[i]); } err_mem_region: for (i = 0; i < EXYNOS_TMU_COUNT; i++) { if (data->mem[i]) release_mem_region(data->mem[i]->start, resource_size(data->mem[i])); } err_free: kfree(data); #ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ exynos_cpufreq_init_unregister_notifier(&exynos_cpufreq_nb); #endif return ret; }
static int exynos_tmu_read(struct exynos_tmu_data *data) { u8 temp_code; int temp, i, max = INT_MIN, min = INT_MAX, gpu_temp = 0; #ifdef CONFIG_ARM_EXYNOS5410_BUS_DEVFREQ enum tmu_noti_state_t cur_state; #endif int alltemp[EXYNOS_TMU_COUNT] = {0,}; if (!th_zone || !th_zone->therm_dev) return -EPERM; mutex_lock(&data->lock); clk_enable(data->clk); for (i = 0; i < EXYNOS_TMU_COUNT; i++) { temp_code = readb(data->base[i] + EXYNOS_TMU_REG_CURRENT_TEMP); temp = code_to_temp(data, temp_code, i); if (temp < 0) temp = 0; alltemp[i] = temp; if (temp > max) max = temp; if (temp < min) min = temp; if (soc_is_exynos5420() && i == EXYNOS_GPU_NUMBER) gpu_temp = temp; } #ifdef CONFIG_SOC_EXYNOS5260 if (alltemp[EXYNOS_GPU0_NUMBER] > alltemp[EXYNOS_GPU1_NUMBER]) gpu_temp = alltemp[EXYNOS_GPU0_NUMBER]; else gpu_temp = alltemp[EXYNOS_GPU1_NUMBER]; #endif clk_disable(data->clk); mutex_unlock(&data->lock); #ifdef CONFIG_ARM_EXYNOS5410_BUS_DEVFREQ if (min <= COLD_TEMP) cur_state = TMU_COLD; if (max >= HOT_110) cur_state = TMU_110; else if (max > HOT_95 && max < HOT_110) cur_state = TMU_109; else if (max <= HOT_95) cur_state = TMU_95; if (cur_state >= HOT_95) pr_info("[TMU] POLLING: temp=%d, cpu=%d, int=%d, mif=%d, hot_event(for aref)=%d\n", max, g_cpufreq, g_intfreq, g_miffreq, cur_state); g_count++; /* to probe thermal run away caused by fimc-is */ if ((max >= 112 && tmu_old_state == TMU_110) && g_cam_err_count && g_intfreq == 800000) { cur_state = TMU_111; } exynos_tmu_call_notifier(cur_state); #endif if (soc_is_exynos5420()) { /* check temperature state */ exynos_check_tmu_noti_state(min, max); exynos_check_gpu_noti_state(gpu_temp); #ifdef CONFIG_ARM_EXYNOS5420_BUS_DEVFREQ if (!check_mif_probed()) goto out; #endif exynos_check_mif_noti_state(max); } if (soc_is_exynos5260()) { exynos_check_tmu_noti_state(min, max); exynos_check_gpu_noti_state(gpu_temp); exynos_check_mif_noti_state(max); } #ifdef CONFIG_ARM_EXYNOS5420_BUS_DEVFREQ out: #endif th_zone->therm_dev->last_temperature = max * MCELSIUS; DTM_DBG("[TMU] TMU0 = %d, TMU1 = %d, TMU2 = %d, TMU3 = %d, TMU4 = %d ------- CPU : %d , GPU : %d\n", alltemp[0], alltemp[1], alltemp[2], alltemp[3], alltemp[4], max, gpu_temp); return max; }
static int __devinit exynos_tmu_probe(struct platform_device *pdev) { struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data; int ret, i, count = 0; int trigger_level_en[TRIP_EN_COUNT]; if (!pdata) pdata = exynos_get_driver_data(pdev); if (!pdata) { dev_err(&pdev->dev, "No platform init data supplied.\n"); return -ENODEV; } tmudata = kzalloc(sizeof(struct exynos_tmu_data), GFP_KERNEL); if (!tmudata) { dev_err(&pdev->dev, "Failed to allocate driver structure\n"); return -ENOMEM; } INIT_WORK(&tmudata->irq_work, exynos_tmu_work); #ifndef CONFIG_ARM_TRUSTZONE /* ioremap for drex base address */ exynos4_base_drex0 = ioremap(EXYNOS4_PA_DMC0_4X12, SZ_64K); exynos4_base_drex1 = ioremap(EXYNOS4_PA_DMC1_4X12, SZ_64K); if(!exynos4_base_drex0 || !exynos4_base_drex1) { ret = -ENOMEM; goto err_drex_ioremap; } #endif for (i = 0; i < EXYNOS_TMU_COUNT; i++) { tmudata->irq[i] = platform_get_irq(pdev, i); if (tmudata->irq[i] < 0) { ret = tmudata->irq[i]; dev_err(&pdev->dev, "Failed to get platform irq\n"); goto err_get_resource; } tmudata->mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); if (!tmudata->mem[i]) { ret = -ENOENT; dev_err(&pdev->dev, "Failed to get platform resource\n"); goto err_get_resource; } tmudata->mem[i] = request_mem_region(tmudata->mem[i]->start, resource_size(tmudata->mem[i]), pdev->name); if (!tmudata->mem[i]) { ret = -ENODEV; dev_err(&pdev->dev, "Failed to request memory region\n"); goto err_mem_region; } tmudata->base[i] = ioremap(tmudata->mem[i]->start, resource_size(tmudata->mem[i])); if (!tmudata->base[i]) { ret = -ENODEV; dev_err(&pdev->dev, "Failed to ioremap memory\n"); goto err_io_remap; } ret = request_irq(tmudata->irq[i], exynos_tmu_irq, IRQF_TRIGGER_RISING, "exynos-tmu", tmudata); if (ret) { dev_err(&pdev->dev, "Failed to request irq: %d\n", tmudata->irq[i]); goto err_irq; } } tmudata->clk = clk_get(NULL, "tmu"); if (IS_ERR(tmudata->clk)) { ret = PTR_ERR(tmudata->clk); dev_err(&pdev->dev, "Failed to get clock\n"); goto err_clk; } if (pdata->type == SOC_ARCH_EXYNOS5 || pdata->type == SOC_ARCH_EXYNOS4) tmudata->soc = pdata->type; else { ret = -EINVAL; dev_err(&pdev->dev, "Platform not supported\n"); goto err_soc_type; } tmudata->pdata = pdata; platform_set_drvdata(pdev, tmudata); mutex_init(&tmudata->lock); for (i = 0; i < EXYNOS_TMU_COUNT; i++) { ret = exynos_tmu_initialize(pdev, i); if (ret) { dev_err(&pdev->dev, "Failed to initialize TMU[%d]\n", i); goto err_tmu; } exynos_tmu_control(pdev, i, true); } /*Register the sensor with thermal management interface*/ (&exynos_sensor_conf)->private_data = tmudata; exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en + pdata->trigger_level1_en + pdata->trigger_level2_en + pdata->trigger_level3_en; trigger_level_en[0] = pdata->trigger_level0_en; trigger_level_en[1] = pdata->trigger_level1_en; trigger_level_en[2] = pdata->trigger_level2_en; trigger_level_en[3] = pdata->trigger_level3_en; for (i = 0; i < TRIP_EN_COUNT; i++) { if (trigger_level_en[i]) { exynos_sensor_conf.trip_data.trip_val[count] = pdata->threshold + pdata->trigger_levels[i]; count++; } } exynos_sensor_conf.cooling_data.freq_clip_count = pdata->freq_tab_count; for (i = 0; i <= THERMAL_TRIP_CRITICAL; i++) exynos_sensor_conf.cooling_data.size[i] = pdata->size[i]; for (i = 0; i < pdata->freq_tab_count; i++) { exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max = pdata->freq_tab[i].freq_clip_max; exynos_sensor_conf.cooling_data.freq_data[i].temp_level = pdata->freq_tab[i].temp_level; exynos_sensor_conf.cooling_data.freq_data[i].mask_val = cpu_all_mask; } register_pm_notifier(&exynos_pm_nb); ret = exynos_register_thermal(&exynos_sensor_conf); if (ret) { dev_err(&pdev->dev, "Failed to register thermal interface\n"); goto err_register; } th_zone->exynos4_dev = pdev; /* For low temperature compensation when boot time */ exynos_tmu_call_notifier(1, 0); #ifdef CONFIG_EXYNOS4_EXPORT_TEMP tmu_curr_temperature = 35; // seems reasonable :-| #endif return 0; err_register: unregister_pm_notifier(&exynos_pm_nb); err_tmu: platform_set_drvdata(pdev, NULL); err_soc_type: clk_put(tmudata->clk); err_clk: for (i = 0; i < EXYNOS_TMU_COUNT; i++) { if (tmudata->irq[i]) free_irq(tmudata->irq[i], tmudata); } err_irq: for (i = 0; i < EXYNOS_TMU_COUNT; i++) { if (tmudata->base[i]) iounmap(tmudata->base[i]); } err_io_remap: for (i = 0; i < EXYNOS_TMU_COUNT; i++) { if (tmudata->mem[i]) release_mem_region(tmudata->mem[i]->start, resource_size(tmudata->mem[i])); } err_mem_region: err_get_resource: #ifndef CONFIG_ARM_TRUSTZONE iounmap(exynos4_base_drex0); iounmap(exynos4_base_drex1); err_drex_ioremap: kfree(tmudata); #endif return ret; }