diff options
Diffstat (limited to 'drivers/thermal/tegra/soctherm.c')
| -rw-r--r-- | drivers/thermal/tegra/soctherm.c | 163 |
1 files changed, 61 insertions, 102 deletions
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 66e0639da4bf..5d26b52beaba 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -31,6 +31,7 @@ #include <linux/reset.h> #include <linux/thermal.h> +#include <dt-bindings/thermal/tegra114-soctherm.h> #include <dt-bindings/thermal/tegra124-soctherm.h> #include "../thermal_core.h" @@ -357,6 +358,12 @@ struct soctherm_oc_irq_chip_data { static struct soctherm_oc_irq_chip_data soc_irq_cdata; +/* Ensure that TEGRA114_* and TEGRA124_* counterparts are equal */ +static_assert(TEGRA114_SOCTHERM_SENSOR_CPU == TEGRA124_SOCTHERM_SENSOR_CPU); +static_assert(TEGRA114_SOCTHERM_SENSOR_MEM == TEGRA124_SOCTHERM_SENSOR_MEM); +static_assert(TEGRA114_SOCTHERM_SENSOR_GPU == TEGRA124_SOCTHERM_SENSOR_GPU); +static_assert(TEGRA114_SOCTHERM_SENSOR_PLLX == TEGRA124_SOCTHERM_SENSOR_PLLX); + /** * ccroc_writel() - writes a value to a CCROC register * @ts: pointer to a struct tegra_soctherm @@ -421,9 +428,9 @@ static int translate_temp(u16 val) return t; } -static int tegra_thermctl_get_temp(void *data, int *out_temp) +static int tegra_thermctl_get_temp(struct thermal_zone_device *tz, int *out_temp) { - struct tegra_thermctl_zone *zone = data; + struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz); u32 val; val = readl(zone->reg); @@ -450,8 +457,8 @@ static int enforce_temp_range(struct device *dev, int trip_temp) temp = clamp_val(trip_temp, min_low_temp, max_high_temp); if (temp != trip_temp) - dev_info(dev, "soctherm: trip temperature %d forced to %d\n", - trip_temp, temp); + dev_dbg(dev, "soctherm: trip temperature %d forced to %d\n", + trip_temp, temp); return temp; } @@ -582,24 +589,18 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id) return temp; } -static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) +static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, + const struct thermal_trip *trip, int temp) { - struct tegra_thermctl_zone *zone = data; - struct thermal_zone_device *tz = zone->tz; + struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz); struct tegra_soctherm *ts = zone->ts; const struct tegra_tsensor_group *sg = zone->sg; struct device *dev = zone->dev; - enum thermal_trip_type type; - int ret; if (!tz) return -EINVAL; - ret = tz->ops->get_trip_type(tz, trip, &type); - if (ret) - return ret; - - if (type == THERMAL_TRIP_CRITICAL) { + if (trip->type == THERMAL_TRIP_CRITICAL) { /* * If thermtrips property is set in DT, * doesn't need to program critical type trip to HW, @@ -610,7 +611,7 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) else return 0; - } else if (type == THERMAL_TRIP_HOT) { + } else if (trip->type == THERMAL_TRIP_HOT) { int i; for (i = 0; i < THROTTLE_SIZE; i++) { @@ -621,7 +622,7 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) continue; cdev = ts->throt_cfgs[i].cdev; - if (get_thermal_instance(tz, cdev, trip)) + if (thermal_trip_is_bound_to_cdev(tz, trip, cdev)) stc = find_throttle_cfg_by_name(ts, cdev->type); else continue; @@ -633,37 +634,6 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) return 0; } -static int tegra_thermctl_get_trend(void *data, int trip, - enum thermal_trend *trend) -{ - struct tegra_thermctl_zone *zone = data; - struct thermal_zone_device *tz = zone->tz; - int trip_temp, temp, last_temp, ret; - - if (!tz) - return -EINVAL; - - ret = tz->ops->get_trip_temp(zone->tz, trip, &trip_temp); - if (ret) - return ret; - - temp = READ_ONCE(tz->temperature); - last_temp = READ_ONCE(tz->last_temperature); - - if (temp > trip_temp) { - if (temp >= last_temp) - *trend = THERMAL_TREND_RAISING; - else - *trend = THERMAL_TREND_STABLE; - } else if (temp < trip_temp) { - *trend = THERMAL_TREND_DROPPING; - } else { - *trend = THERMAL_TREND_STABLE; - } - - return 0; -} - static void thermal_irq_enable(struct tegra_thermctl_zone *zn) { u32 r; @@ -688,9 +658,9 @@ static void thermal_irq_disable(struct tegra_thermctl_zone *zn) mutex_unlock(&zn->ts->thermctl_lock); } -static int tegra_thermctl_set_trips(void *data, int lo, int hi) +static int tegra_thermctl_set_trips(struct thermal_zone_device *tz, int lo, int hi) { - struct tegra_thermctl_zone *zone = data; + struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz); u32 r; thermal_irq_disable(zone); @@ -713,36 +683,31 @@ static int tegra_thermctl_set_trips(void *data, int lo, int hi) return 0; } -static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { +static const struct thermal_zone_device_ops tegra_of_thermal_ops = { .get_temp = tegra_thermctl_get_temp, .set_trip_temp = tegra_thermctl_set_trip_temp, - .get_trend = tegra_thermctl_get_trend, .set_trips = tegra_thermctl_set_trips, }; -static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) +static int get_hot_trip_cb(struct thermal_trip *trip, void *arg) { - int ntrips, i, ret; - enum thermal_trip_type type; + const struct thermal_trip **trip_ret = arg; - ntrips = of_thermal_get_ntrips(tz); - if (ntrips <= 0) - return -EINVAL; + if (trip->type != THERMAL_TRIP_HOT) + return 0; - for (i = 0; i < ntrips; i++) { - ret = tz->ops->get_trip_type(tz, i, &type); - if (ret) - return -EINVAL; - if (type == THERMAL_TRIP_HOT) { - ret = tz->ops->get_trip_temp(tz, i, temp); - if (!ret) - *trip = i; + *trip_ret = trip; + /* Return nonzero to terminate the search. */ + return 1; +} - return ret; - } - } +static const struct thermal_trip *get_hot_trip(struct thermal_zone_device *tz) +{ + const struct thermal_trip *trip = NULL; - return -EINVAL; + thermal_zone_for_each_trip(tz, get_hot_trip_cb, &trip); + + return trip; } /** @@ -774,13 +739,14 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, struct thermal_zone_device *tz) { struct tegra_soctherm *ts = dev_get_drvdata(dev); + const struct thermal_trip *hot_trip; struct soctherm_throt_cfg *stc; - int i, trip, temperature, ret; + int i, temperature, ret; /* Get thermtrips. If missing, try to get critical trips. */ temperature = tsensor_group_thermtrip_get(ts, sg->id); if (min_low_temp == temperature) - if (tz->ops->get_crit_temp(tz, &temperature)) + if (thermal_zone_get_crit_temp(tz, &temperature)) temperature = max_high_temp; ret = thermtrip_program(dev, sg, temperature); @@ -792,8 +758,8 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n", sg->name, temperature); - ret = get_hot_temp(tz, &trip, &temperature); - if (ret) { + hot_trip = get_hot_trip(tz); + if (!hot_trip) { dev_info(dev, "throttrip: %s: missing hot temperature\n", sg->name); return 0; @@ -806,7 +772,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, continue; cdev = ts->throt_cfgs[i].cdev; - if (get_thermal_instance(tz, cdev, trip)) + if (thermal_trip_is_bound_to_cdev(tz, hot_trip, cdev)) stc = find_throttle_cfg_by_name(ts, cdev->type); else continue; @@ -1247,7 +1213,7 @@ static const struct irq_domain_ops soctherm_oc_domain_ops = { /** * soctherm_oc_int_init() - Initial enabling of the over * current interrupts - * @np: The devicetree node for soctherm + * @fwnode: The devicetree node for soctherm * @num_irqs: The number of new interrupt requests * * Sets the over current interrupt request chip data @@ -1256,7 +1222,7 @@ static const struct irq_domain_ops soctherm_oc_domain_ops = { * -ENOMEM (out of memory), or irq_base if the function failed to * allocate the irqs */ -static int soctherm_oc_int_init(struct device_node *np, int num_irqs) +static int soctherm_oc_int_init(struct fwnode_handle *fwnode, int num_irqs) { if (!num_irqs) { pr_info("%s(): OC interrupts are not enabled\n", __func__); @@ -1275,10 +1241,8 @@ static int soctherm_oc_int_init(struct device_node *np, int num_irqs) soc_irq_cdata.irq_chip.irq_set_type = soctherm_oc_irq_set_type; soc_irq_cdata.irq_chip.irq_set_wake = NULL; - soc_irq_cdata.domain = irq_domain_add_linear(np, num_irqs, - &soctherm_oc_domain_ops, - &soc_irq_cdata); - + soc_irq_cdata.domain = irq_domain_create_linear(fwnode, num_irqs, &soctherm_oc_domain_ops, + &soc_irq_cdata); if (!soc_irq_cdata.domain) { pr_err("%s: Failed to create IRQ domain\n", __func__); return -ENOMEM; @@ -1692,7 +1656,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct tegra_soctherm *ts = dev_get_drvdata(dev); - struct device_node *np_stc, *np_stcc; + struct device_node *np_stc; const char *name; int i; @@ -1709,7 +1673,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) return; } - for_each_child_of_node(np_stc, np_stcc) { + for_each_child_of_node_scoped(np_stc, np_stcc) { struct soctherm_throt_cfg *stc; struct thermal_cooling_device *tcd; int err; @@ -1724,7 +1688,6 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) if (stc->init) { dev_err(dev, "throttle-cfg: %s: redefined!\n", name); - of_node_put(np_stcc); break; } @@ -2010,10 +1973,9 @@ static void tegra_soctherm_throttle(struct device *dev) static int soctherm_interrupts_init(struct platform_device *pdev, struct tegra_soctherm *tegra) { - struct device_node *np = pdev->dev.of_node; int ret; - ret = soctherm_oc_int_init(np, TEGRA_SOC_OC_IRQ_MAX); + ret = soctherm_oc_int_init(dev_fwnode(&pdev->dev), TEGRA_SOC_OC_IRQ_MAX); if (ret < 0) { dev_err(&pdev->dev, "soctherm_oc_int_init failed\n"); return ret; @@ -2090,6 +2052,12 @@ static void soctherm_init(struct platform_device *pdev) } static const struct of_device_id tegra_soctherm_of_match[] = { +#ifdef CONFIG_ARCH_TEGRA_114_SOC + { + .compatible = "nvidia,tegra114-soctherm", + .data = &tegra114_soctherm, + }, +#endif #ifdef CONFIG_ARCH_TEGRA_124_SOC { .compatible = "nvidia,tegra124-soctherm", @@ -2118,7 +2086,6 @@ static int tegra_soctherm_probe(struct platform_device *pdev) struct tegra_soctherm *tegra; struct thermal_zone_device *z; struct tsensor_shared_calib shared_calib; - struct resource *res; struct tegra_soctherm_soc *soc; unsigned int i; int err; @@ -2140,26 +2107,20 @@ static int tegra_soctherm_probe(struct platform_device *pdev) tegra->soc = soc; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "soctherm-reg"); - tegra->regs = devm_ioremap_resource(&pdev->dev, res); + tegra->regs = devm_platform_ioremap_resource_byname(pdev, "soctherm-reg"); if (IS_ERR(tegra->regs)) { dev_err(&pdev->dev, "can't get soctherm registers"); return PTR_ERR(tegra->regs); } if (!tegra->soc->use_ccroc) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "car-reg"); - tegra->clk_regs = devm_ioremap_resource(&pdev->dev, res); + tegra->clk_regs = devm_platform_ioremap_resource_byname(pdev, "car-reg"); if (IS_ERR(tegra->clk_regs)) { dev_err(&pdev->dev, "can't get car clk registers"); return PTR_ERR(tegra->clk_regs); } } else { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "ccroc-reg"); - tegra->ccroc_regs = devm_ioremap_resource(&pdev->dev, res); + tegra->ccroc_regs = devm_platform_ioremap_resource_byname(pdev, "ccroc-reg"); if (IS_ERR(tegra->ccroc_regs)) { dev_err(&pdev->dev, "can't get ccroc registers"); return PTR_ERR(tegra->ccroc_regs); @@ -2195,7 +2156,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev) if (err) return err; - /* calculate tsensor calibaration data */ + /* calculate tsensor calibration data */ for (i = 0; i < soc->num_tsensors; ++i) { err = tegra_calc_tsensor_calib(&soc->tsensors[i], &shared_calib, @@ -2233,9 +2194,9 @@ static int tegra_soctherm_probe(struct platform_device *pdev) zone->sg = soc->ttgs[i]; zone->ts = tegra; - z = devm_thermal_zone_of_sensor_register(&pdev->dev, - soc->ttgs[i]->id, zone, - &tegra_of_thermal_ops); + z = devm_thermal_of_zone_register(&pdev->dev, + soc->ttgs[i]->id, zone, + &tegra_of_thermal_ops); if (IS_ERR(z)) { err = PTR_ERR(z); dev_err(&pdev->dev, "failed to register sensor: %d\n", @@ -2264,15 +2225,13 @@ disable_clocks: return err; } -static int tegra_soctherm_remove(struct platform_device *pdev) +static void tegra_soctherm_remove(struct platform_device *pdev) { struct tegra_soctherm *tegra = platform_get_drvdata(pdev); debugfs_remove_recursive(tegra->debugfs_dir); soctherm_clk_enable(pdev, false); - - return 0; } static int __maybe_unused soctherm_suspend(struct device *dev) |
