static int rockchip_thermal_remove(struct platform_device *pdev) { struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev); int i; for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++) { struct rockchip_thermal_sensor *sensor = &thermal->sensors[i]; rockchip_thermal_toggle_sensor(sensor, false); thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd); } thermal->chip->control(thermal->regs, false); clk_disable_unprepare(thermal->pclk); clk_disable_unprepare(thermal->clk); return 0; }
static int tmp102_remove(struct i2c_client *client) { struct tmp102 *tmp102 = i2c_get_clientdata(client); thermal_zone_of_sensor_unregister(tmp102->hwmon_dev, tmp102->tz); hwmon_device_unregister(tmp102->hwmon_dev); /* Stop monitoring if device was stopped originally */ if (tmp102->config_orig & TMP102_CONF_SD) { int config; config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); if (config >= 0) i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config | TMP102_CONF_SD); } return 0; }
static int hisi_thermal_remove(struct platform_device *pdev) { struct hisi_thermal_data *data = platform_get_drvdata(pdev); int i; for (i = 0; i < HISI_MAX_SENSORS; i++) { struct hisi_thermal_sensor *sensor = &data->sensors[i]; if (!sensor->tzd) continue; hisi_thermal_toggle_sensor(sensor, false); thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd); } hisi_thermal_disable_sensor(data); clk_disable_unprepare(data->clk); return 0; }
static int rockchip_thermal_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct rockchip_thermal_data *thermal; const struct of_device_id *match; struct resource *res; int irq; int i; int error; match = of_match_node(of_rockchip_thermal_match, np); if (!match) return -ENXIO; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "no irq resource?\n"); return -EINVAL; } thermal = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_thermal_data), GFP_KERNEL); if (!thermal) return -ENOMEM; thermal->pdev = pdev; thermal->chip = (const struct rockchip_tsadc_chip *)match->data; if (!thermal->chip) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); thermal->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(thermal->regs)) return PTR_ERR(thermal->regs); thermal->reset = devm_reset_control_get(&pdev->dev, "tsadc-apb"); if (IS_ERR(thermal->reset)) { error = PTR_ERR(thermal->reset); dev_err(&pdev->dev, "failed to get tsadc reset: %d\n", error); return error; } thermal->clk = devm_clk_get(&pdev->dev, "tsadc"); if (IS_ERR(thermal->clk)) { error = PTR_ERR(thermal->clk); dev_err(&pdev->dev, "failed to get tsadc clock: %d\n", error); return error; } thermal->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); if (IS_ERR(thermal->pclk)) { error = PTR_ERR(thermal->clk); dev_err(&pdev->dev, "failed to get apb_pclk clock: %d\n", error); return error; } error = clk_prepare_enable(thermal->clk); if (error) { dev_err(&pdev->dev, "failed to enable converter clock: %d\n", error); return error; } error = clk_prepare_enable(thermal->pclk); if (error) { dev_err(&pdev->dev, "failed to enable pclk: %d\n", error); goto err_disable_clk; } rockchip_thermal_reset_controller(thermal->reset); error = rockchip_configure_from_dt(&pdev->dev, np, thermal); if (error) { dev_err(&pdev->dev, "failed to parse device tree data: %d\n", error); goto err_disable_pclk; } thermal->chip->initialize(thermal->regs, thermal->tshut_polarity); error = rockchip_thermal_register_sensor(pdev, thermal, &thermal->sensors[0], SENSOR_CPU); if (error) { dev_err(&pdev->dev, "failed to register CPU thermal sensor: %d\n", error); goto err_disable_pclk; } error = rockchip_thermal_register_sensor(pdev, thermal, &thermal->sensors[1], SENSOR_GPU); if (error) { dev_err(&pdev->dev, "failed to register GPU thermal sensor: %d\n", error); goto err_unregister_cpu_sensor; } error = devm_request_threaded_irq(&pdev->dev, irq, NULL, &rockchip_thermal_alarm_irq_thread, IRQF_ONESHOT, "rockchip_thermal", thermal); if (error) { dev_err(&pdev->dev, "failed to request tsadc irq: %d\n", error); goto err_unregister_gpu_sensor; } thermal->chip->control(thermal->regs, true); for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++) rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); platform_set_drvdata(pdev, thermal); return 0; err_unregister_gpu_sensor: thermal_zone_of_sensor_unregister(&pdev->dev, thermal->sensors[1].tzd); err_unregister_cpu_sensor: thermal_zone_of_sensor_unregister(&pdev->dev, thermal->sensors[0].tzd); err_disable_pclk: clk_disable_unprepare(thermal->pclk); err_disable_clk: clk_disable_unprepare(thermal->clk); return error; }
static int bcm2835_thermal_probe(struct platform_device *pdev) { const struct of_device_id *match; struct thermal_zone_device *tz; struct bcm2835_thermal_data *data; struct resource *res; int err = 0; u32 val; unsigned long rate; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; match = of_match_device(bcm2835_thermal_of_match_table, &pdev->dev); if (!match) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->regs)) { err = PTR_ERR(data->regs); dev_err(&pdev->dev, "Could not get registers: %d\n", err); return err; } data->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(data->clk)) { err = PTR_ERR(data->clk); if (err != -EPROBE_DEFER) dev_err(&pdev->dev, "Could not get clk: %d\n", err); return err; } err = clk_prepare_enable(data->clk); if (err) return err; rate = clk_get_rate(data->clk); if ((rate < 1920000) || (rate > 5000000)) dev_warn(&pdev->dev, "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n", data->clk, data->clk); /* register of thermal sensor and get info from DT */ tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data, &bcm2835_thermal_ops); if (IS_ERR(tz)) { err = PTR_ERR(tz); dev_err(&pdev->dev, "Failed to register the thermal device: %d\n", err); goto err_clk; } /* * right now the FW does set up the HW-block, so we are not * touching the configuration registers. * But if the HW is not enabled, then set it up * using "sane" values used by the firmware right now. */ val = readl(data->regs + BCM2835_TS_TSENSCTL); if (!(val & BCM2835_TS_TSENSCTL_RSTB)) { int trip_temp, offset, slope; slope = thermal_zone_get_slope(tz); offset = thermal_zone_get_offset(tz); /* * For now we deal only with critical, otherwise * would need to iterate */ err = tz->ops->get_trip_temp(tz, 0, &trip_temp); if (err < 0) { dev_err(&pdev->dev, "Not able to read trip_temp: %d\n", err); goto err_tz; } /* set bandgap reference voltage and enable voltage regulator */ val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT << BCM2835_TS_TSENSCTL_CTRL_SHIFT) | BCM2835_TS_TSENSCTL_REGULEN; /* use the recommended reset duration */ val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT); /* trip_adc value from info */ val |= bcm2835_thermal_temp2adc(trip_temp, offset, slope) << BCM2835_TS_TSENSCTL_THOLD_SHIFT; /* write the value back to the register as 2 steps */ writel(val, data->regs + BCM2835_TS_TSENSCTL); val |= BCM2835_TS_TSENSCTL_RSTB; writel(val, data->regs + BCM2835_TS_TSENSCTL); } data->tz = tz; platform_set_drvdata(pdev, tz); bcm2835_thermal_debugfs(pdev); return 0; err_tz: thermal_zone_of_sensor_unregister(&pdev->dev, tz); err_clk: clk_disable_unprepare(data->clk); return err; }
static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res) { thermal_zone_of_sensor_unregister(dev, *(struct thermal_zone_device **)res); }