コード例 #1
0
ファイル: omap-bandgap.c プロジェクト: AllenDou/linux
static
int __devinit omap_bandgap_probe(struct platform_device *pdev)
{
	struct omap_bandgap *bg_ptr;
	int clk_rate, ret = 0, i;

	bg_ptr = omap_bandgap_build(pdev);
	if (IS_ERR_OR_NULL(bg_ptr)) {
		dev_err(&pdev->dev, "failed to fetch platform data\n");
		return PTR_ERR(bg_ptr);
	}
	bg_ptr->dev = &pdev->dev;

	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
		if (ret) {
			dev_err(&pdev->dev,
				"failed to initialize system tshut IRQ\n");
			return ret;
		}
	}

	bg_ptr->fclock = clk_get(NULL, bg_ptr->conf->fclock_name);
	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
	if (ret) {
		dev_err(&pdev->dev, "failed to request fclock reference\n");
		goto free_irqs;
	}

	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->conf->div_ck_name);
	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
	if (ret) {
		dev_err(&pdev->dev,
			"failed to request div_ts_ck clock ref\n");
		goto free_irqs;
	}

	bg_ptr->conv_table = bg_ptr->conf->conv_table;
	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		struct temp_sensor_registers *tsr;
		u32 val;

		tsr = bg_ptr->conf->sensors[i].registers;
		/*
		 * check if the efuse has a non-zero value if not
		 * it is an untrimmed sample and the temperatures
		 * may not be accurate
		 */
		val = omap_bandgap_readl(bg_ptr, tsr->bgap_efuse);
		if (ret || !val)
			dev_info(&pdev->dev,
				 "Non-trimmed BGAP, Temp not accurate\n");
	}

	clk_rate = clk_round_rate(bg_ptr->div_clk,
				  bg_ptr->conf->sensors[0].ts_data->max_freq);
	if (clk_rate < bg_ptr->conf->sensors[0].ts_data->min_freq ||
	    clk_rate == 0xffffffff) {
		ret = -ENODEV;
		dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
		goto put_clks;
	}

	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
	if (ret)
		dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");

	bg_ptr->clk_rate = clk_rate;
	clk_enable(bg_ptr->fclock);

	mutex_init(&bg_ptr->bg_mutex);
	bg_ptr->dev = &pdev->dev;
	platform_set_drvdata(pdev, bg_ptr);

	omap_bandgap_power(bg_ptr, true);

	/* Set default counter to 1 for now */
	if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
		for (i = 0; i < bg_ptr->conf->sensor_count; i++)
			configure_temp_sensor_counter(bg_ptr, i, 1);

	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		struct temp_sensor_data *ts_data;

		ts_data = bg_ptr->conf->sensors[i].ts_data;

		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
			temp_sensor_init_talert_thresholds(bg_ptr, i,
							   ts_data->t_hot,
							   ts_data->t_cold);
		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) {
			temp_sensor_configure_tshut_hot(bg_ptr, i,
							ts_data->tshut_hot);
			temp_sensor_configure_tshut_cold(bg_ptr, i,
							 ts_data->tshut_cold);
		}
	}

	if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
		enable_continuous_mode(bg_ptr);

	/* Set .250 seconds time as default counter */
	if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
		for (i = 0; i < bg_ptr->conf->sensor_count; i++)
			configure_temp_sensor_counter(bg_ptr, i,
						      bg_ptr->clk_rate / 4);

	/* Every thing is good? Then expose the sensors */
	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		char *domain;

		if (bg_ptr->conf->sensors[i].register_cooling)
			bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i);

		domain = bg_ptr->conf->sensors[i].domain;
		if (bg_ptr->conf->expose_sensor)
			bg_ptr->conf->expose_sensor(bg_ptr, i, domain);
	}

	/*
	 * Enable the Interrupts once everything is set. Otherwise irq handler
	 * might be called as soon as it is enabled where as rest of framework
	 * is still getting initialised.
	 */
	if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
		ret = omap_bandgap_talert_init(bg_ptr, pdev);
		if (ret) {
			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
			i = bg_ptr->conf->sensor_count;
			goto disable_clk;
		}
	}

	return 0;

disable_clk:
	clk_disable(bg_ptr->fclock);
put_clks:
	clk_put(bg_ptr->fclock);
	clk_put(bg_ptr->div_clk);
free_irqs:
	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
		free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
		gpio_free(bg_ptr->tshut_gpio);
	}

	return ret;
}
コード例 #2
0
int omap4460plus_temp_sensor_init(struct scm *scm_ptr)
{
	struct omap_temp_sensor_registers *reg_ptr;
	struct omap4460plus_temp_sensor_data *ts_ptr;
	struct scm_regval *regval_ptr;
	int clk_rate, ret, i;

	scm_ptr->registers = kzalloc(sizeof(reg_ptr) *
				     scm_ptr->cnt, GFP_KERNEL);
	if (!scm_ptr->registers) {
		pr_err("Unable to allocate mem for scm registers\n");
		return -ENOMEM;
	}

	scm_ptr->ts_data = kzalloc(sizeof(ts_ptr) * scm_ptr->cnt, GFP_KERNEL);
	if (!scm_ptr->ts_data) {
		pr_err("Unable to allocate memory for ts data\n");
		ret = -ENOMEM;
		goto fail_alloc;
	}

	scm_ptr->regval = kzalloc(sizeof(regval_ptr) * scm_ptr->cnt,
						GFP_KERNEL);
	if (!scm_ptr->regval) {
		pr_err("Unable to allocate memory for regval\n");
		ret = -ENOMEM;
		goto fail_alloc;
	}

#ifdef CONFIG_THERMAL_FRAMEWORK
	scm_ptr->therm_fw = kzalloc(sizeof(struct thermal_dev *)
					* scm_ptr->cnt, GFP_KERNEL);
	if (!scm_ptr->therm_fw) {
		pr_err("Unable to allocate memory for ts data\n");
		return -ENOMEM;
	}
#elif defined(CONFIG_CPU_THERMAL)
	scm_ptr->cpu_therm = kzalloc(sizeof(struct thermal_sensor_conf)
		 * scm_ptr->cnt, GFP_KERNEL);
	if (!scm_ptr->cpu_therm) {
		pr_err("Unable to allocate memory for ts data\n");
		goto clk_err;
	}
#endif

	for (i = 0; i < scm_ptr->cnt; i++) {
#ifdef CONFIG_THERMAL_FRAMEWORK
		scm_ptr->therm_fw[i] =
				kzalloc(sizeof(struct thermal_dev), GFP_KERNEL);
#endif
		scm_ptr->regval[i] =
			kzalloc(sizeof(struct scm_regval), GFP_KERNEL);
	}

	if (scm_ptr->rev == 1) {
		scm_ptr->registers[0] = &omap4460_mpu_temp_sensor_registers;
		scm_ptr->ts_data[0] = &omap4460_mpu_temp_sensor_data;
		scm_ptr->conv_table = omap4460_adc_to_temp;
		/*
		 * check if the efuse has a non-zero value if not
		 * it is an untrimmed sample and the temperatures
		 * may not be accurate
		 */
		if (!omap4plus_scm_readl(scm_ptr,
					scm_ptr->registers[0]->bgap_efuse))
			pr_info("Non-trimmed BGAP, Temp not accurate\n");
#ifdef CONFIG_THERMAL_FRAMEWORK
		if (scm_ptr->therm_fw) {
			scm_ptr->therm_fw[0]->name = "omap_ondie_sensor";
			scm_ptr->therm_fw[0]->domain_name = "cpu";
			scm_ptr->therm_fw[0]->dev = scm_ptr->dev;
			scm_ptr->therm_fw[0]->dev_ops = &omap_sensor_ops;
			scm_ptr->therm_fw[0]->sen_id = 0;
			scm_ptr->therm_fw[0]->slope = 376;
			scm_ptr->therm_fw[0]->constant_offset =  -16000;
			thermal_sensor_dev_register(scm_ptr->therm_fw[0]);
		} else {
			pr_err("%s:Cannot alloc memory for thermal fw\n",
			       __func__);
			ret = -ENOMEM;
		}
#elif defined(CONFIG_CPU_THERMAL)
		strncpy(scm_ptr->cpu_therm[0].name, "omap_ondie_sensor",
			SENSOR_NAME_LEN);
		scm_ptr->cpu_therm[0].private_data = scm_ptr;
		scm_ptr->cpu_therm[0].read_temperature = omap_read_temp;
		if (omap4_has_mpu_1_5ghz())
			scm_ptr->cpu_therm[0].sensor_data =
				&omap4_1500mhz_bandgap_data;
		else
			scm_ptr->cpu_therm[0].sensor_data =
				&omap4_1200mhz_bandgap_data;
		omap_zones[0] = omap4_register_thermal(scm_ptr->cpu_therm);
#endif
	} else if (scm_ptr->rev == 2) {
		scm_ptr->registers[0] = &omap5430_mpu_temp_sensor_registers;
		scm_ptr->ts_data[0] = &omap5430_mpu_temp_sensor_data;
		scm_ptr->registers[1] = &omap5430_gpu_temp_sensor_registers;
		scm_ptr->ts_data[1] = &omap5430_gpu_temp_sensor_data;
		scm_ptr->registers[2] = &omap5430_core_temp_sensor_registers;
		scm_ptr->ts_data[2] = &omap5430_core_temp_sensor_data;
		scm_ptr->conv_table = omap5430_adc_to_temp;
#ifdef CONFIG_THERMAL_FRAMEWORK
		if (scm_ptr->therm_fw) {
			scm_ptr->therm_fw[0]->name = "omap_ondie_mpu_sensor";
			scm_ptr->therm_fw[0]->domain_name = "cpu";
			scm_ptr->therm_fw[0]->dev = scm_ptr->dev;
			scm_ptr->therm_fw[0]->dev_ops = &omap_sensor_ops;
			scm_ptr->therm_fw[0]->sen_id = 0;
			scm_ptr->therm_fw[0]->slope = 196;
			scm_ptr->therm_fw[0]->constant_offset =  -6822;
			thermal_sensor_dev_register(scm_ptr->therm_fw[0]);
			scm_ptr->therm_fw[1]->name = "omap_ondie_gpu_sensor";
			scm_ptr->therm_fw[1]->domain_name = "gpu";
			scm_ptr->therm_fw[1]->dev = scm_ptr->dev;
			scm_ptr->therm_fw[1]->dev_ops = &omap_sensor_ops;
			scm_ptr->therm_fw[1]->sen_id = 1;
			scm_ptr->therm_fw[1]->slope = 0;
			scm_ptr->therm_fw[1]->constant_offset =  7000;
			thermal_sensor_dev_register(scm_ptr->therm_fw[1]);
			scm_ptr->therm_fw[2]->name = "omap_ondie_core_sensor";
			scm_ptr->therm_fw[2]->domain_name = "core";
			scm_ptr->therm_fw[2]->dev = scm_ptr->dev;
			scm_ptr->therm_fw[2]->dev_ops = &omap_sensor_ops;
			scm_ptr->therm_fw[2]->sen_id = 2;
			scm_ptr->therm_fw[2]->slope = 0;
			scm_ptr->therm_fw[2]->constant_offset = 0;
			thermal_sensor_dev_register(scm_ptr->therm_fw[2]);
			/*TO DO:  Add for GPU and core */
		} else {
			pr_err("%s:Cannot alloc memory for thermal fw\n",
			       __func__);
			ret = -ENOMEM;
		}
#elif defined(CONFIG_CPU_THERMAL)
		strncpy(scm_ptr->cpu_therm[0].name, "omap_ondie_sensor",
			SENSOR_NAME_LEN);
		scm_ptr->cpu_therm[0].private_data = scm_ptr;
		scm_ptr->cpu_therm[0].read_temperature = omap_read_temp;
		scm_ptr->cpu_therm[0].sensor_data = &omap5_1500mhz_bandgap_data;
		omap_zones[0] = omap4_register_thermal(&scm_ptr->cpu_therm[0]);
		strncpy(scm_ptr->cpu_therm[1].name, "omap_ondie_gpu_sensor",
			SENSOR_NAME_LEN);
		scm_ptr->cpu_therm[1].private_data = scm_ptr;
		scm_ptr->cpu_therm[1].read_temperature = omap_read_temp;
		scm_ptr->cpu_therm[1].sensor_data = &omap5_1500mhz_bandgap_data;
		strncpy(scm_ptr->cpu_therm[2].name, "omap_ondie_core_sensor",
			SENSOR_NAME_LEN);
		scm_ptr->cpu_therm[2].private_data = scm_ptr;
		scm_ptr->cpu_therm[2].read_temperature = omap_read_temp;
		scm_ptr->cpu_therm[2].sensor_data = &omap5_1500mhz_bandgap_data;
#endif
	}

	if (scm_ptr->rev == 1) {

		clk_rate = clk_round_rate(scm_ptr->div_clk,
					  scm_ptr->ts_data[0]->max_freq);
		if (clk_rate < scm_ptr->ts_data[0]->min_freq ||
		    clk_rate == 0xffffffff) {
			ret = -ENODEV;
			goto clk_err;
		}

		ret = clk_set_rate(scm_ptr->div_clk, clk_rate);
		if (ret) {
			pr_err("Cannot set clock rate\n");
			goto clk_err;
		}

		scm_ptr->clk_rate = clk_rate;
	} else if (scm_ptr->rev == 2) {
			/* add clock rate code for omap5430 */
#ifdef CONFIG_MACH_OMAP_5430ZEBU
		scm_ptr->clk_rate = 1200;
#else

		clk_rate = clk_round_rate(scm_ptr->fclock,
				scm_ptr->ts_data[0]->max_freq);

		if (clk_rate < scm_ptr->ts_data[0]->min_freq ||
			clk_rate == 0xffffffff) {
			ret = -ENODEV;
			goto clk_err;
		}

		ret = clk_set_rate(scm_ptr->fclock, clk_rate);
		if (ret) {
			pr_err("Cannot set clock rate\n");
			goto clk_err;
		}
		scm_ptr->clk_rate = clk_rate;
#endif
	}

	clk_enable(scm_ptr->fclock);
	/* 1 clk cycle */
	for (i = 0; i < scm_ptr->cnt; i++)
		configure_temp_sensor_counter(scm_ptr, i, 1);
	for (i = 0; i < scm_ptr->cnt; i++) {
		temp_sensor_init_talert_thresholds(scm_ptr, i,
				scm_ptr->ts_data[i]->t_hot,
					scm_ptr->ts_data[i]->t_cold);
		temp_sensor_configure_tshut_hot(scm_ptr, i,
						scm_ptr->ts_data[i]->tshut_hot);
		temp_sensor_configure_tshut_cold(scm_ptr, i,
						 scm_ptr->ts_data[i]->
						 tshut_cold);
	}

	enable_continuous_mode(scm_ptr);

	/* Set .250 seconds time as default counter */
	for (i = 0; i < scm_ptr->cnt; i++) {
		configure_temp_sensor_counter(scm_ptr, i,
						scm_ptr->clk_rate / 4);
	}

	return 0;
clk_err:
	kfree(scm_ptr->ts_data);
fail_alloc:
	kfree(scm_ptr->registers);
	return ret;
}