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