static int amlogic_thermal_probe(struct platform_device *pdev) { int ret; struct amlogic_thermal_platform_data *pdata=NULL; //pdata = amlogic_get_driver_data(pdev); #ifdef CONFIG_AML_VIRTUAL_THERMAL ret=thermal_firmware_init(); if(ret<0){ printk("%s, this chip is not trimmed, use virtual thermal\n", __func__); trim_flag = 0; }else{ printk("%s, this chip is trimmed, use thermal\n", __func__); trim_flag = 1; } if(!trim_flag){ aml_virtaul_thermal_probe(pdev); INIT_DELAYED_WORK(&freq_collect_work, collect_freq_work); schedule_delayed_work(&freq_collect_work, msecs_to_jiffies(100)); atomic_set(&freq_update_flag, 0); } #else ret=thermal_firmware_init(); if(ret<0) return ret; #endif dev_info(&pdev->dev, "amlogic thermal probe start\n"); pdata = amlogic_thermal_initialize(pdev); if (!pdata) { dev_err(&pdev->dev, "Failed to initialize thermal\n"); goto err; } mutex_init(&pdata->lock); pdev->dev.platform_data=pdata; platform_set_drvdata(pdev, pdata); ret = amlogic_register_thermal(pdata); if (ret) { dev_err(&pdev->dev, "Failed to register thermal interface\n"); goto err; } dev_info(&pdev->dev, "amlogic thermal probe done\n"); return 0; err: platform_set_drvdata(pdev, NULL); return ret; }
static struct amlogic_thermal_platform_data * amlogic_thermal_init_from_dts(struct platform_device *pdev, int trim_flag) { int i = 0, ret = -1, val = 0, cells, descend, error = 0; struct property *prop; struct temp_level *tmp_level = NULL; struct amlogic_thermal_platform_data *pdata = NULL; if(!of_property_read_u32(pdev->dev.of_node, "trip_point", &val)){ //INIT FROM DTS pdata=kzalloc(sizeof(*pdata),GFP_KERNEL); if(!pdata){ goto err; } memset((void* )pdata,0,sizeof(*pdata)); ret=of_property_read_u32(pdev->dev.of_node, "#thermal-cells", &val); if(ret){ dev_err(&pdev->dev, "dt probe #thermal-cells failed: %d\n", ret); goto err; } cells=val; /* * process for KEEP_MODE and virtual thermal * Logic: If virtual thermal is enabled, then ignore keep_mode * */ pdata->trim_flag = trim_flag; if (!pdata->trim_flag) { // chip is not trimmed, use virtual thermal aml_virtaul_thermal_probe(pdev, pdata); } else if (of_property_read_bool(pdev->dev.of_node, "keep_mode")) { if (of_property_read_u32(pdev->dev.of_node, "keep_mode_threshold", &pdata->keep_mode_threshold)) { error = 1; } if (of_property_read_u32_array(pdev->dev.of_node, "keep_mode_max_range", pdata->keep_mode_max_range, sizeof(pdata->keep_mode_max_range)/sizeof(u32))) { error = 1; } if (!error && pdata->trim_flag) { // keep mode should not used for virtual thermal right now THERMAL_INFO("keep_mode_max_range: [%7d, %3d, %d, %d]\n", pdata->keep_mode_max_range[0], pdata->keep_mode_max_range[1], pdata->keep_mode_max_range[2], pdata->keep_mode_max_range[3]); pdata->keep_mode = 1; pdata->freq_sample_period = 5; } if (!of_property_read_u32_array(pdev->dev.of_node, "keep_mode_min_range", pdata->keep_mode_min_range, sizeof(pdata->keep_mode_min_range)/sizeof(u32))) { pdata->keep_min_exist = 1; THERMAL_INFO("keep_mode_min_range: [%7d, %3d, %d, %d]\n", pdata->keep_mode_min_range[0], pdata->keep_mode_min_range[1], pdata->keep_mode_min_range[2], pdata->keep_mode_min_range[3]); } } else { THERMAL_INFO("keep_mode is disabled\n"); } if(pdata->keep_mode || !pdata->trim_flag){ INIT_DELAYED_WORK(&pdata->thermal_work, thermal_work); schedule_delayed_work(&pdata->thermal_work, msecs_to_jiffies(100)); atomic_set(&freq_update_flag, 0); } prop = of_find_property(pdev->dev.of_node, "trip_point", &val); if (!prop){ dev_err(&pdev->dev, "read %s length error\n","trip_point"); goto err; } if (pdata->keep_mode) { pdata->temp_trip_count = 2; } else { pdata->temp_trip_count=val/cells/sizeof(u32); } tmp_level=kzalloc(sizeof(*tmp_level)*pdata->temp_trip_count,GFP_KERNEL); pdata->tmp_trip=kzalloc(sizeof(struct temp_trip)*pdata->temp_trip_count,GFP_KERNEL); if(!tmp_level){ goto err; } if (pdata->keep_mode) { // keep mode only need one point keep_mode_temp_level_init(pdata, tmp_level); } else { ret=of_property_read_u32_array(pdev->dev.of_node,"trip_point",(u32 *)tmp_level,val/sizeof(u32)); if (ret){ dev_err(&pdev->dev, "read %s data error\n","trip_point"); goto err; } } descend=get_desend(); for (i = 0; i < pdata->temp_trip_count; i++) { pdata->tmp_trip[i].temperature=tmp_level[i].temperature; tmp_level[i].cpu_high_freq=fix_to_freq(tmp_level[i].cpu_high_freq,descend); pdata->tmp_trip[i].cpu_lower_level=cpufreq_cooling_get_level(0,tmp_level[i].cpu_high_freq); tmp_level[i].cpu_low_freq=fix_to_freq(tmp_level[i].cpu_low_freq,descend); pdata->tmp_trip[i].cpu_upper_level=cpufreq_cooling_get_level(0,tmp_level[i].cpu_low_freq); pdata->tmp_trip[i].gpu_lower_freq=tmp_level[i].gpu_low_freq; pdata->tmp_trip[i].gpu_upper_freq=tmp_level[i].gpu_high_freq; pdata->tmp_trip[i].cpu_core_num=tmp_level[i].cpu_core_num; pdata->tmp_trip[i].gpu_core_num=tmp_level[i].gpu_core_num; } ret= of_property_read_u32(pdev->dev.of_node, "idle_interval", &val); if (ret){ dev_err(&pdev->dev, "read %s error\n","idle_interval"); goto err; } pdata->idle_interval=val; ret=of_property_read_string(pdev->dev.of_node,"dev_name",&pdata->name); if (ret){ dev_err(&pdev->dev, "read %s error\n","dev_name"); goto err; } pdata->mode=THERMAL_DEVICE_ENABLED; if(tmp_level) kfree(tmp_level); return pdata; } err: if(tmp_level) kfree(tmp_level); if(pdata) kfree(pdata); pdata= NULL; return pdata; }