@@ -847,7 +847,8 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
{
- struct mtk_thermal *mt = thermal_zone_device_priv(tz);
+ struct mtk_thermal_bank *bank = thermal_zone_device_priv(tz);
+ struct mtk_thermal *mt = bank->mt;
int i;
int tempmax = INT_MIN;
@@ -866,10 +867,41 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
return 0;
}
+static int mtk_read_sensor_temp(struct thermal_zone_device *tz, int *temperature)
+{
+ struct mtk_thermal_bank *bank = thermal_zone_device_priv(tz);
+ struct mtk_thermal *mt = bank->mt;
+ const struct mtk_thermal_data *conf = mt->conf;
+ int id = bank->id - 1;
+ int temp = INT_MIN;
+ u32 raw;
+
+ raw = readl(mt->thermal_base + conf->msr[id]);
+
+ temp = mt->raw_to_mcelsius(mt, id, raw);
+
+ /*
+ * The first read of a sensor often contains very high bogus
+ * temperature value. Filter these out so that the system does
+ * not immediately shut down.
+ */
+
+ if (unlikely(!mtk_thermal_temp_is_valid(temp)))
+ return -EAGAIN;
+
+ *temperature = temp;
+
+ return 0;
+}
+
static const struct thermal_zone_device_ops mtk_thermal_ops = {
.get_temp = mtk_read_temp,
};
+static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
+ .get_temp = mtk_read_sensor_temp,
+};
+
static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
u32 apmixed_phys_base, u32 auxadc_phys_base,
int ctrl_id)
@@ -1199,6 +1231,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
u64 auxadc_phys_base, apmixed_phys_base;
struct thermal_zone_device *tzdev;
void __iomem *apmixed_base, *auxadc_base;
+ struct mtk_thermal_bank *tz;
mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
if (!mt)
@@ -1285,14 +1318,35 @@ static int mtk_thermal_probe(struct platform_device *pdev)
mtk_thermal_init_bank(mt, i, apmixed_phys_base,
auxadc_phys_base, ctrl_id);
- tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
- &mtk_thermal_ops);
- if (IS_ERR(tzdev))
- return PTR_ERR(tzdev);
+ for (i = 0; i <= mt->conf->num_sensors; i++) {
+ tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
+ if (!tz)
+ return -ENOMEM;
+
+ tz->mt = mt;
+ tz->id = i;
+
+ tzdev = devm_thermal_of_zone_register(&pdev->dev, i,
+ tz, (i == 0) ?
+ &mtk_thermal_ops
+ : &mtk_thermal_sensor_ops);
+
+ if (IS_ERR(tzdev)) {
+ ret = PTR_ERR(tzdev);
+ if (ret == -ENODEV) {
+ dev_warn(&pdev->dev, "Can't find thermal zone for sensor %d; sensor skipped.\n", i);
+ continue;
+ }
+ dev_err(&pdev->dev,
+ "Error: Failed to register thermal zone %d, ret = %d\n",
+ i, ret);
+ return dev_err_probe(&pdev->dev, ret, "Failed to register thermal zone %d.\n", i);
+ }
- ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev);
- if (ret)
- dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
+ ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev);
+ if (ret)
+ dev_warn(&pdev->dev, "Sensor %d: Error in thermal_add_hwmon_sysfs: %d\n", i, ret);
+ }
return 0;
}