コード例 #1
0
ファイル: pcb_temp_sensor.c プロジェクト: richardxu/panda-a4
static int __devinit pcb_temp_sensor_probe(struct platform_device *pdev)
{
	struct pcb_temp_sensor_pdata *pdata = pdev->dev.platform_data;
	struct pcb_temp_sensor *temp_sensor;
	int ret = 0;

	if (!pdata) {
		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
		return -EINVAL;
	}

	temp_sensor = kzalloc(sizeof(struct pcb_temp_sensor), GFP_KERNEL);
	if (!temp_sensor)
		return -ENOMEM;

	spin_lock_init(&temp_sensor->lock);
	mutex_init(&temp_sensor->sensor_mutex);

	temp_sensor->pdev = pdev;
	temp_sensor->dev = &pdev->dev;

	kobject_uevent(&pdev->dev.kobj, KOBJ_ADD);
	platform_set_drvdata(pdev, temp_sensor);

	temp_sensor->therm_fw = kzalloc(sizeof(struct thermal_dev), GFP_KERNEL);
	if (temp_sensor->therm_fw) {
		temp_sensor->therm_fw->name = "pcb_sensor";
		temp_sensor->therm_fw->domain_name = "pcb";
		temp_sensor->therm_fw->dev = temp_sensor->dev;
		temp_sensor->therm_fw->dev_ops = &pcb_sensor_ops;
		thermal_sensor_dev_register(temp_sensor->therm_fw);
	} else {
		dev_err(&pdev->dev, "%s:Cannot alloc memory for thermal fw\n",
			__func__);
		ret = -ENOMEM;
		goto therm_fw_alloc_err;
	}

	ret = sysfs_create_group(&pdev->dev.kobj,
				 &pcb_temp_sensor_group);
	if (ret) {
		dev_err(&pdev->dev, "could not create sysfs files\n");
		goto sysfs_create_err;
	}

	dev_info(&pdev->dev, "%s : '%s'\n", temp_sensor->therm_fw->name,
			pdata->name);

	return 0;

sysfs_create_err:
	thermal_sensor_dev_unregister(temp_sensor->therm_fw);
	kfree(temp_sensor->therm_fw);
	platform_set_drvdata(pdev, NULL);
therm_fw_alloc_err:
	mutex_destroy(&temp_sensor->sensor_mutex);
	kfree(temp_sensor);
	return ret;
}
コード例 #2
0
static int __devinit thermistor_probe(struct platform_device *pdev)
{
	struct thermistor_pdata *pdata = pdev->dev.platform_data;
	struct thermistor *temp_sensor;
	int ret = 0;

	if (!pdata) {
		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
		return -EINVAL;
	}

	temp_sensor = devm_kzalloc(&pdev->dev,
				   sizeof(struct thermistor), GFP_KERNEL);
	if (!temp_sensor)
		return -ENOMEM;

	temp_sensor->pdev = pdev;
	temp_sensor->dev = &pdev->dev;

	kobject_uevent(&pdev->dev.kobj, KOBJ_ADD);
	platform_set_drvdata(pdev, temp_sensor);

	temp_sensor->therm_fw = devm_kzalloc(&pdev->dev,
					     sizeof(struct thermal_dev),
					     GFP_KERNEL);
	if (temp_sensor->therm_fw) {
		temp_sensor->therm_fw->name = "thermistor";
		temp_sensor->therm_fw->domain_name = pdata->domain;
		temp_sensor->therm_fw->slope = pdata->slope;
		temp_sensor->therm_fw->constant = pdata->offset;
		temp_sensor->therm_fw->dev = temp_sensor->dev;
		temp_sensor->therm_fw->dev_ops = &thermistor_ops;
		thermal_sensor_dev_register(temp_sensor->therm_fw);
	} else {
		dev_err(&pdev->dev, "%s:Cannot alloc memory for thermal fw\n",
			__func__);
		ret = -ENOMEM;
		goto therm_fw_alloc_err;
	}

	ret = sysfs_create_group(&pdev->dev.kobj, &thermistor_group);
	if (ret) {
		dev_err(&pdev->dev, "could not create sysfs files\n");
		goto sysfs_create_err;
	}

	dev_info(&pdev->dev, "%s : '%s'\n", temp_sensor->therm_fw->name,
		 pdata->name);
	dev_info(&pdev->dev, "slope - %d, offset - %d\n", pdata->slope,
		 pdata->offset);

	return 0;

sysfs_create_err:
	thermal_sensor_dev_unregister(temp_sensor->therm_fw);
	platform_set_drvdata(pdev, NULL);
therm_fw_alloc_err:
	return ret;
}
コード例 #3
0
static int __devinit pcb_temp_sensor_probe(struct platform_device *pdev)
{
	struct pcb_temp_sensor_pdata *pdata = pdev->dev.platform_data;
	struct pcb_temp_sensor *temp_sensor;
	int ret = 0;

	if (!pdata) {
		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
		return -EINVAL;
	}

	temp_sensor = kzalloc(sizeof(struct pcb_temp_sensor), GFP_KERNEL);
	if (!temp_sensor)
		return -ENOMEM;

	/* Init delayed work for PCB sensor temperature */
	INIT_DELAYED_WORK(&temp_sensor->pcb_sensor_work,
			  pcb_sensor_delayed_work_fn);

	spin_lock_init(&temp_sensor->lock);
	mutex_init(&temp_sensor->sensor_mutex);

	temp_sensor->pdev = pdev;
	temp_sensor->dev = &pdev->dev;

	kobject_uevent(&pdev->dev.kobj, KOBJ_ADD);
	platform_set_drvdata(pdev, temp_sensor);

	temp_sensor->therm_fw = kzalloc(sizeof(struct thermal_dev), GFP_KERNEL);
	if (temp_sensor->therm_fw) {
		temp_sensor->therm_fw->name = "pcb_sensor";
		temp_sensor->therm_fw->domain_name = "cpu";
		temp_sensor->therm_fw->dev = temp_sensor->dev;
		temp_sensor->therm_fw->dev_ops = &pcb_sensor_ops;
		thermal_sensor_dev_register(temp_sensor->therm_fw);
	} else {
		dev_err(&pdev->dev, "%s:Cannot alloc memory for thermal fw\n",
			__func__);
		ret = -ENOMEM;
		goto therm_fw_alloc_err;
	}

	ret = sysfs_create_group(&pdev->dev.kobj,
				 &pcb_temp_sensor_group);
	if (ret) {
		dev_err(&pdev->dev, "could not create sysfs files\n");
		goto sysfs_create_err;
	}

	temp_sensor->work_delay = PCB_REPORT_DELAY_MS;
	schedule_delayed_work(&temp_sensor->pcb_sensor_work,
			msecs_to_jiffies(0));

	dev_info(&pdev->dev, "%s : '%s'\n", temp_sensor->therm_fw->name,
			pdata->name);

	return 0;

sysfs_create_err:
	thermal_sensor_dev_unregister(temp_sensor->therm_fw);
	kfree(temp_sensor->therm_fw);
	platform_set_drvdata(pdev, NULL);
therm_fw_alloc_err:
	mutex_destroy(&temp_sensor->sensor_mutex);
	kfree(temp_sensor);
	return ret;
}
コード例 #4
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;
}
コード例 #5
0
static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct omap_temp_sensor_pdata *pdata = pdev->dev.platform_data;
	struct omap_temp_sensor *temp_sensor;
	struct resource *mem;
	int ret = 0, val;

	if (!pdata) {
		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
		return -EINVAL;
	}

	temp_sensor = kzalloc(sizeof(struct omap_temp_sensor), GFP_KERNEL);
	if (!temp_sensor)
		return -ENOMEM;

	spin_lock_init(&temp_sensor->lock);
	mutex_init(&temp_sensor->sensor_mutex);

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem) {
		dev_err(&pdev->dev, "%s:no mem resource\n", __func__);
		ret = -EINVAL;
		goto plat_res_err;
	}

	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
	if (temp_sensor->irq < 0) {
		dev_err(&pdev->dev, "%s:Cannot get thermal alert irq\n",
			__func__);
		ret = -EINVAL;
		goto get_irq_err;
	}

	ret = gpio_request_one(OMAP_TSHUT_GPIO, GPIOF_DIR_IN,
		"thermal_shutdown");
	if (ret) {
		dev_err(&pdev->dev, "%s: Could not get tshut_gpio\n",
			__func__);
		goto tshut_gpio_req_err;
	}

	temp_sensor->tshut_irq = gpio_to_irq(OMAP_TSHUT_GPIO);
	if (temp_sensor->tshut_irq < 0) {
		dev_err(&pdev->dev, "%s:Cannot get thermal shutdown irq\n",
			__func__);
		ret = -EINVAL;
		goto get_tshut_irq_err;
	}

	temp_sensor->phy_base = pdata->offset;
	temp_sensor->pdev = pdev;
	temp_sensor->dev = dev;

	pm_runtime_enable(dev);
	pm_runtime_irq_safe(dev);


	kobject_uevent(&pdev->dev.kobj, KOBJ_ADD);
	platform_set_drvdata(pdev, temp_sensor);


	/*
	 * check if the efuse has a non-zero value if not
	 * it is an untrimmed sample and the temperatures
	 * may not be accurate */
	if (omap_readl(OMAP4_CTRL_MODULE_CORE +
			OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP))
		temp_sensor->is_efuse_valid = 1;

	temp_sensor->clock = clk_get(&temp_sensor->pdev->dev, "fck");
	if (IS_ERR(temp_sensor->clock)) {
		ret = PTR_ERR(temp_sensor->clock);
		pr_err("%s:Unable to get fclk: %d\n", __func__, ret);
		ret = -EINVAL;
		goto clk_get_err;
	}

	ret = omap_temp_sensor_enable(temp_sensor);
	if (ret) {
		dev_err(&pdev->dev, "%s:Cannot enable temp sensor\n", __func__);
		goto sensor_enable_err;
	}

	temp_sensor->therm_fw = kzalloc(sizeof(struct thermal_dev), GFP_KERNEL);
	if (temp_sensor->therm_fw) {
		temp_sensor->therm_fw->name = "omap_ondie_sensor";
		temp_sensor->therm_fw->domain_name = "cpu";
		temp_sensor->therm_fw->dev = temp_sensor->dev;
		temp_sensor->therm_fw->dev_ops = &omap_sensor_ops;
		thermal_sensor_dev_register(temp_sensor->therm_fw);
	} else {
		dev_err(&pdev->dev, "%s:Cannot alloc memory for thermal fw\n",
			__func__);
		ret = -ENOMEM;
		goto therm_fw_alloc_err;
	}

	omap_enable_continuous_mode(temp_sensor, 1);
	omap_configure_temp_sensor_thresholds(temp_sensor);
	/* 1 ms */
	omap_configure_temp_sensor_counter(temp_sensor, 1);

	/* Wait till the first conversion is done wait for at least 1ms */
	mdelay(2);

	/* Read the temperature once due to hw issue*/
	omap_report_temp(temp_sensor->therm_fw);

	/* Set 250 milli-seconds time as default counter */
	omap_configure_temp_sensor_counter(temp_sensor,
					temp_sensor->clk_rate * 250 / 1000);
	ret = sysfs_create_group(&pdev->dev.kobj,
				 &omap_temp_sensor_group);
	if (ret) {
		dev_err(&pdev->dev, "could not create sysfs files\n");
		goto sysfs_create_err;
	}

	ret = request_threaded_irq(temp_sensor->irq, NULL,
			omap_talert_irq_handler,
			IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
			"temp_sensor", (void *)temp_sensor);
	if (ret) {
		dev_err(&pdev->dev, "Request threaded irq failed.\n");
		goto req_irq_err;
	}

	ret = request_threaded_irq(temp_sensor->tshut_irq, NULL,
			omap_tshut_irq_handler,
			IRQF_TRIGGER_RISING | IRQF_ONESHOT,
			"tshut", (void *)temp_sensor);
	if (ret) {
		dev_err(&pdev->dev, "Request threaded irq failed for TSHUT.\n");
		goto tshut_irq_req_err;
	}

	/* unmask the T_COLD and unmask T_HOT at init */
	val = omap_temp_sensor_readl(temp_sensor, BGAP_CTRL_OFFSET);
	val |= OMAP4_MASK_COLD_MASK;
	val |= OMAP4_MASK_HOT_MASK;
	omap_temp_sensor_writel(temp_sensor, val, BGAP_CTRL_OFFSET);

	dev_info(&pdev->dev, "%s : '%s'\n", temp_sensor->therm_fw->name,
			pdata->name);

	temp_sensor_pm = temp_sensor;
	return 0;

tshut_irq_req_err:
	free_irq(temp_sensor->irq, temp_sensor);
req_irq_err:
	kobject_uevent(&temp_sensor->dev->kobj, KOBJ_REMOVE);
	sysfs_remove_group(&temp_sensor->dev->kobj, &omap_temp_sensor_group);
sysfs_create_err:
	thermal_sensor_dev_unregister(temp_sensor->therm_fw);
	kfree(temp_sensor->therm_fw);
	if (temp_sensor->clock)
		clk_put(temp_sensor->clock);
	platform_set_drvdata(pdev, NULL);
therm_fw_alloc_err:
	omap_temp_sensor_disable(temp_sensor);
sensor_enable_err:
	clk_put(temp_sensor->clock);
clk_get_err:
	pm_runtime_disable(&pdev->dev);
get_tshut_irq_err:
	gpio_free(OMAP_TSHUT_GPIO);
tshut_gpio_req_err:
get_irq_err:
plat_res_err:
	mutex_destroy(&temp_sensor->sensor_mutex);
	kfree(temp_sensor);
	return ret;
}
コード例 #6
0
static int __devinit tmp102_temp_sensor_probe(
		struct i2c_client *client, const struct i2c_device_id *id)
{
	struct tmp102_temp_sensor *tmp102;
	int ret = 0;
#ifdef CONFIG_THERMAL_DEBUG
	printk(KERN_DEBUG "%s\n", __func__);
#endif
	if (!i2c_check_functionality(client->adapter,
				     I2C_FUNC_SMBUS_WORD_DATA)) {
		dev_err(&client->dev, "adapter doesn't support SMBus word "
			"transactions\n");

		return -ENODEV;
	}

	tmp102 = kzalloc(sizeof(struct tmp102_temp_sensor), GFP_KERNEL);
	if (!tmp102)
		return -ENOMEM;

	mutex_init(&tmp102->sensor_mutex);

	tmp102->iclient = client;
	tmp102->dev = &client->dev;

	kobject_uevent(&client->dev.kobj, KOBJ_ADD);
	i2c_set_clientdata(client, tmp102);

	ret = tmp102_read_reg(client, TMP102_CONF_REG);
	if (ret < 0) {
		dev_err(&client->dev, "error reading config register\n");
		goto free_err;
	}
	tmp102->config_orig = ret;
	ret = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
	if (ret < 0) {
		dev_err(&client->dev, "error writing config register\n");
		goto restore_config_err;
	}
	ret = tmp102_read_reg(client, TMP102_CONF_REG);
	if (ret < 0) {
		dev_err(&client->dev, "error reading config register\n");
		goto restore_config_err;
	}
	ret &= ~TMP102_CONFIG_RD_ONLY;
	if (ret != TMP102_CONFIG) {
		dev_err(&client->dev, "config settings did not stick\n");
		ret = -ENODEV;
		goto restore_config_err;
	}
	tmp102->last_update = jiffies - HZ;
	mutex_init(&tmp102->sensor_mutex);

	ret = sysfs_create_group(&client->dev.kobj,
		&tmp102_temp_sensor_attr_group);
	if (ret)
		goto sysfs_create_err;

	tmp102->therm_fw = kzalloc(sizeof(struct thermal_dev), GFP_KERNEL);
	if (tmp102->therm_fw) {
		tmp102->therm_fw->name = TMP102_SENSOR_NAME;
		tmp102->therm_fw->domain_name = "pcb";
		tmp102->therm_fw->dev = tmp102->dev;
		tmp102->therm_fw->dev_ops = &tmp102_temp_sensor_ops;
		thermal_sensor_dev_register(tmp102->therm_fw);
	} else {
		ret = -ENOMEM;
		goto therm_fw_alloc_err;
	}

	dev_info(&client->dev, "initialized\n");

	return 0;

sysfs_create_err:
	thermal_sensor_dev_unregister(tmp102->therm_fw);
	kfree(tmp102->therm_fw);
restore_config_err:
	tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
therm_fw_alloc_err:
free_err:
	mutex_destroy(&tmp102->sensor_mutex);
	kfree(tmp102);

	return ret;
}