thermal driver为zone device 添加sensor

来源:互联网 发布:sql查询成绩最高分 编辑:程序博客网 时间:2024/05/19 00:40
前面讲过在thermal_init->of_parse_thermal_zones的时候已经从dts中建好了zone device,并绑定了cool deviceint __init of_parse_thermal_zones(void){struct device_node *np, *child;struct __thermal_zone *tz;struct thermal_zone_device_ops *ops;//找到zone devicenp = of_find_node_by_name(NULL, "thermal-zones");if (!np) {pr_debug("unable to find thermal zones\n");return 0; /* Run successfully on systems without thermal DT */}for_each_available_child_of_node(np, child) {struct thermal_zone_device *zone;struct thermal_zone_params *tzp;int i, mask = 0;u32 prop;//从dts中parse值后赋值给tzptz = thermal_of_build_thermal_zone(child);if (IS_ERR(tz)) {pr_err("failed to build thermal zone %s: %ld\n",       child->name,       PTR_ERR(tz));continue;}ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);if (!ops)goto exit_free;tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);if (!tzp) {kfree(ops);goto exit_free;}/* No hwmon because there might be hwmon drivers registering */tzp->no_hwmon = true;if (!of_property_read_u32(child, "sustainable-power", &prop))tzp->sustainable_power = prop;for (i = 0; i < tz->ntrips; i++)mask |= 1 << i;/* these two are left for temperature drivers to use */tzp->slope = tz->slope;tzp->offset = tz->offset;//注册zone device 并绑定cool devicezone = thermal_zone_device_register(child->name, tz->ntrips,    mask, tz,    ops, tzp,    tz->passive_delay,    tz->polling_delay);if (IS_ERR(zone)) {pr_err("Failed to build %s zone %ld\n", child->name,       PTR_ERR(zone));kfree(tzp);kfree(ops);of_thermal_free_zone(tz);/* attempting to build remaining zones still */}}of_node_put(np);return 0;}但是需要注意的是,这里并没有为zone device 添加sensor,也就是说zone device不能得到目前的温度,因此thermal driver主要责任就是给zone device添加sensor。这里以下面的thermal 驱动为例static int hisi_thermal_probe(struct platform_device *pdev){struct hisi_thermal_data *data;struct resource *res;int i;int ret;//注册中断线程化ret = devm_request_threaded_irq(&pdev->dev, data->irq,hisi_thermal_alarm_irq,hisi_thermal_alarm_irq_thread,0, "hisi_thermal", data);if (ret < 0) {dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);return ret;}//调用hisi_thermal_register_sensor 为zone device添加sensor来获取温度for (i = 0; i < HISI_MAX_SENSORS; ++i) {ret = hisi_thermal_register_sensor(pdev, data,   &data->sensors[i], i);if (ret)dev_err(&pdev->dev,"failed to register thermal sensor: %d\n", ret);elsehisi_thermal_toggle_sensor(&data->sensors[i], true);}return 0;}继续看看hisi_thermal_register_sensorstatic int hisi_thermal_register_sensor(struct platform_device *pdev,struct hisi_thermal_data *data,struct hisi_thermal_sensor *sensor,int index){//调用devm_thermal_zone_of_sensor_register->thermal_zone_of_sensor_register 来为已经存在的zone device添加sensor,这里的hisi_of_thermal_ops 就是sensor 获取温度的opssensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,sensor->id, sensor, &hisi_of_thermal_ops);if (IS_ERR(sensor->tzd)) {ret = PTR_ERR(sensor->tzd);sensor->tzd = NULL;dev_err(&pdev->dev, "failed to register sensor id %d: %d\n",sensor->id, ret);return ret;}}struct thermal_zone_device *thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,const struct thermal_zone_of_device_ops *ops){struct device_node *np, *child, *sensor_np;struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);//找到zone device在dts中的nodenp = of_find_node_by_name(NULL, "thermal-zones");if (!np)return ERR_PTR(-ENODEV);if (!dev || !dev->of_node) {of_node_put(np);return ERR_PTR(-EINVAL);}sensor_np = of_node_get(dev->of_node);for_each_available_child_of_node(np, child) {struct of_phandle_args sensor_specs;int ret, id;/* For now, thermal framework supports only 1 sensor per zone */ret = of_parse_phandle_with_args(child, "thermal-sensors", "#thermal-sensor-cells", 0, &sensor_specs);if (ret)continue;//每个zone 只能有一个sensorif (sensor_specs.args_count >= 1) {id = sensor_specs.args[0];WARN(sensor_specs.args_count > 1,     "%s: too many cells in sensor specifier %d\n",     sensor_specs.np->name, sensor_specs.args_count);} else {id = 0;}//找到目前sensor对应的zone device。找到后通过thermal_zone_of_add_sensor 给zone 添加sensorif (sensor_specs.np == sensor_np && id == sensor_id) {tzd = thermal_zone_of_add_sensor(child, sensor_np, data, ops);if (!IS_ERR(tzd))tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);of_node_put(sensor_specs.np);of_node_put(child);goto exit;}of_node_put(sensor_specs.np);}}static struct thermal_zone_device *thermal_zone_of_add_sensor(struct device_node *zone,   struct device_node *sensor, void *data,   const struct thermal_zone_of_device_ops *ops){struct thermal_zone_device *tzd;struct __thermal_zone *tz;//这部是关键,根据name找到zone devicetzd = thermal_zone_get_zone_by_name(zone->name);if (IS_ERR(tzd))return ERR_PTR(-EPROBE_DEFER);tz = tzd->devdata;if (!ops)return ERR_PTR(-EINVAL);mutex_lock(&tzd->lock);tz->ops = ops;tz->sensor_data = data;//为zone device的赋值,后面就直接通过tzd->ops->get_temp 来获取温度tzd->ops->get_temp = of_thermal_get_temp;tzd->ops->get_trend = of_thermal_get_trend;}static int of_thermal_get_temp(struct thermal_zone_device *tz,       int *temp){struct __thermal_zone *data = tz->devdata;if (!data->ops->get_temp)return -EINVAL;//可见又是调用data->ops->get_temp,这里的data就是hisi_of_thermal_opsreturn data->ops->get_temp(data->sensor_data, temp);}static struct thermal_zone_of_device_ops hisi_of_thermal_ops = {.get_temp = hisi_thermal_get_temp,};hisi_thermal_get_temp->hisi_thermal_get_sensor_temp得到温度。查看hisi_thermal_get_sensor_temp的code会发现基本是在读取硬件寄存器

原创粉丝点击