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;
}