Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1308135 > unrolled thread
| Started by | Wei Ni <wni@nvidia.com> |
|---|---|
| First post | 2016-01-13 09:00 +0100 |
| Last post | 2016-01-14 11:00 +0100 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH V1 03/10] thermal: tegra: split tegra_soctherm driver Wei Ni <wni@nvidia.com> - 2016-01-13 09:00 +0100
Re: [PATCH V1 03/10] thermal: tegra: split tegra_soctherm driver Thierry Reding <thierry.reding@gmail.com> - 2016-01-13 16:10 +0100
Re: [PATCH V1 03/10] thermal: tegra: split tegra_soctherm driver Wei Ni <wni@nvidia.com> - 2016-01-14 11:00 +0100
| From | Wei Ni <wni@nvidia.com> |
|---|---|
| Date | 2016-01-13 09:00 +0100 |
| Subject | [PATCH V1 03/10] thermal: tegra: split tegra_soctherm driver |
| Message-ID | <qQovw-4Vo-9@gated-at.bofh.it> |
Split most of the T124 data and code into a T124-specific driver.
Split most of the fuse-related code into a fuse-related source file.
Now drivers/thermal/tegra_soctherm.c contains common SOC_THERM library
code. This is in preparation for adding a T210-specific driver in a
future patch.
Beyond the maintainability improvements, this is intended to separate
chip-specific ATE and characterization-related hacks into chip-specific
drivers, in the hopes that they won't pollute code for other chips.
Signed-off-by: Wei Ni <wni@nvidia.com>
---
drivers/thermal/tegra/Kconfig | 8 +-
drivers/thermal/tegra/Makefile | 3 +-
drivers/thermal/tegra/tegra124_soctherm.c | 201 +++++++++++++++++
drivers/thermal/tegra/tegra_soctherm.c | 333 ++--------------------------
drivers/thermal/tegra/tegra_soctherm.h | 106 +++++++++
drivers/thermal/tegra/tegra_soctherm_fuse.c | 143 ++++++++++++
6 files changed, 474 insertions(+), 320 deletions(-)
create mode 100644 drivers/thermal/tegra/tegra124_soctherm.c
create mode 100644 drivers/thermal/tegra/tegra_soctherm.h
create mode 100644 drivers/thermal/tegra/tegra_soctherm_fuse.c
diff --git a/drivers/thermal/tegra/Kconfig b/drivers/thermal/tegra/Kconfig
index a6e6cd4528dc..ae7e5e93dab9 100644
--- a/drivers/thermal/tegra/Kconfig
+++ b/drivers/thermal/tegra/Kconfig
@@ -1,6 +1,10 @@
config TEGRA_SOCTHERM
- tristate "Tegra SOCTHERM thermal management"
- depends on ARCH_TEGRA
+ bool
+
+config TEGRA124_SOCTHERM
+ bool "Tegra124 SOCTHERM thermal management"
+ depends on ARCH_TEGRA_124_SOC
+ select TEGRA_SOCTHERM
help
Enable this option for integrated thermal management support on NVIDIA
Tegra124 systems-on-chip. The driver supports four thermal zones
diff --git a/drivers/thermal/tegra/Makefile b/drivers/thermal/tegra/Makefile
index 8c51076e4b1e..7a864ec07a25 100644
--- a/drivers/thermal/tegra/Makefile
+++ b/drivers/thermal/tegra/Makefile
@@ -3,4 +3,5 @@
#
# Tegra soc thermal drivers
-obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
+obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o tegra_soctherm_fuse.o
+obj-$(CONFIG_TEGRA124_SOCTHERM) += tegra124_soctherm.o
diff --git a/drivers/thermal/tegra/tegra124_soctherm.c b/drivers/thermal/tegra/tegra124_soctherm.c
new file mode 100644
index 000000000000..56bf26d58a04
--- /dev/null
+++ b/drivers/thermal/tegra/tegra124_soctherm.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/thermal/tegra124-soctherm.h>
+
+#include "tegra_soctherm.h"
+
+static const struct tegra_tsensor_configuration t124_tsensor_config = {
+ .tall = 16300,
+ .tiddq_en = 1,
+ .ten_count = 1,
+ .tsample = 120,
+ .tsample_ate = 480,
+};
+
+static const struct tegra_tsensor_group tegra124_tsensor_group_cpu = {
+ .id = TEGRA124_SOCTHERM_SENSOR_CPU,
+ .name = "cpu",
+ .sensor_temp_offset = SENSOR_TEMP1,
+ .sensor_temp_mask = SENSOR_TEMP1_CPU_TEMP_MASK,
+ .pdiv = 8,
+ .pdiv_ate = 8,
+ .pdiv_mask = SENSOR_PDIV_CPU_MASK,
+ .pllx_hotspot_diff = 10,
+ .pllx_hotspot_mask = SENSOR_HOTSPOT_CPU_MASK,
+};
+
+static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
+ .id = TEGRA124_SOCTHERM_SENSOR_GPU,
+ .name = "gpu",
+ .sensor_temp_offset = SENSOR_TEMP1,
+ .sensor_temp_mask = SENSOR_TEMP1_GPU_TEMP_MASK,
+ .pdiv = 8,
+ .pdiv_ate = 8,
+ .pdiv_mask = SENSOR_PDIV_GPU_MASK,
+ .pllx_hotspot_diff = 5,
+ .pllx_hotspot_mask = SENSOR_HOTSPOT_GPU_MASK,
+};
+
+static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
+ .id = TEGRA124_SOCTHERM_SENSOR_PLLX,
+ .name = "pll",
+ .sensor_temp_offset = SENSOR_TEMP2,
+ .sensor_temp_mask = SENSOR_TEMP2_PLLX_TEMP_MASK,
+ .pdiv = 8,
+ .pdiv_ate = 8,
+ .pdiv_mask = SENSOR_PDIV_PLLX_MASK,
+};
+
+static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
+ .id = TEGRA124_SOCTHERM_SENSOR_MEM,
+ .name = "mem",
+ .sensor_temp_offset = SENSOR_TEMP2,
+ .sensor_temp_mask = SENSOR_TEMP2_MEM_TEMP_MASK,
+ .pdiv = 8,
+ .pdiv_ate = 8,
+ .pdiv_mask = SENSOR_PDIV_MEM_MASK,
+ .pllx_hotspot_diff = 0,
+ .pllx_hotspot_mask = SENSOR_HOTSPOT_MEM_MASK,
+};
+
+static const struct tegra_tsensor_group *
+tegra124_tsensor_groups[TEGRA124_SOCTHERM_SENSOR_NUM] = {
+ &tegra124_tsensor_group_cpu,
+ &tegra124_tsensor_group_gpu,
+ &tegra124_tsensor_group_pll,
+ &tegra124_tsensor_group_mem,
+};
+
+static struct tegra_tsensor tegra124_tsensors[] = {
+ {
+ .name = "cpu0",
+ .base = 0xc0,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x098,
+ .fuse_corr_alpha = 1135400,
+ .fuse_corr_beta = -6266900,
+ .group = &tegra124_tsensor_group_cpu,
+ },
+ {
+ .name = "cpu1",
+ .base = 0xe0,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x084,
+ .fuse_corr_alpha = 1122220,
+ .fuse_corr_beta = -5700700,
+ .group = &tegra124_tsensor_group_cpu,
+ },
+ {
+ .name = "cpu2",
+ .base = 0x100,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x088,
+ .fuse_corr_alpha = 1127000,
+ .fuse_corr_beta = -6768200,
+ .group = &tegra124_tsensor_group_cpu,
+ },
+ {
+ .name = "cpu3",
+ .base = 0x120,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x12c,
+ .fuse_corr_alpha = 1110900,
+ .fuse_corr_beta = -6232000,
+ .group = &tegra124_tsensor_group_cpu,
+ },
+ {
+ .name = "mem0",
+ .base = 0x140,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x158,
+ .fuse_corr_alpha = 1122300,
+ .fuse_corr_beta = -5936400,
+ .group = &tegra124_tsensor_group_mem,
+ },
+ {
+ .name = "mem1",
+ .base = 0x160,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x15c,
+ .fuse_corr_alpha = 1145700,
+ .fuse_corr_beta = -7124600,
+ .group = &tegra124_tsensor_group_mem,
+ },
+ {
+ .name = "gpu",
+ .base = 0x180,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x154,
+ .fuse_corr_alpha = 1120100,
+ .fuse_corr_beta = -6000500,
+ .group = &tegra124_tsensor_group_gpu,
+ },
+ {
+ .name = "pllx",
+ .base = 0x1a0,
+ .config = &t124_tsensor_config,
+ .calib_fuse_offset = 0x160,
+ .fuse_corr_alpha = 1106500,
+ .fuse_corr_beta = -6729300,
+ .group = &tegra124_tsensor_group_pll,
+ },
+ { .name = NULL },
+};
+
+/*
+ * Mask/shift bits in FUSE_TSENSOR_COMMON and
+ * FUSE_TSENSOR_COMMON, which are described in
+ * tegra_soctherm_fuse.c
+ */
+static const struct tegra_soctherm_fuse tegra124_soctherm_fuse = {
+ .fuse_base_cp_mask = 0x3ff,
+ .fuse_base_cp_shift = 0,
+ .fuse_base_ft_mask = 0x7ff << 10,
+ .fuse_base_ft_shift = 10,
+ .fuse_shift_ft_mask = 0x1f << 21,
+ .fuse_shift_ft_shift = 21,
+ .fuse_spare_realignment = 0x1fc,
+};
+
+static const struct of_device_id tegra124_soctherm_of_match[] = {
+ { .compatible = "nvidia,tegra124-soctherm" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
+
+static int tegra124_soctherm_probe(struct platform_device *pdev)
+{
+ return tegra_soctherm_probe(pdev,
+ tegra124_tsensors,
+ tegra124_tsensor_groups,
+ &tegra124_soctherm_fuse);
+}
+
+static struct platform_driver tegra124_soctherm_driver = {
+ .probe = tegra124_soctherm_probe,
+ .remove = tegra_soctherm_remove,
+ .driver = {
+ .name = "tegra124_soctherm",
+ .of_match_table = tegra124_soctherm_of_match,
+ },
+};
+module_platform_driver(tegra124_soctherm_driver);
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("Tegra124 SOCTHERM thermal management driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/tegra/tegra_soctherm.c b/drivers/thermal/tegra/tegra_soctherm.c
index 80d97151739e..cc5a3e14948f 100644
--- a/drivers/thermal/tegra/tegra_soctherm.c
+++ b/drivers/thermal/tegra/tegra_soctherm.c
@@ -27,9 +27,10 @@
#include <linux/reset.h>
#include <linux/thermal.h>
-#include <soc/tegra/fuse.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
+#include "tegra_soctherm.h"
+
#define SENSOR_CONFIG0 0
#define SENSOR_CONFIG0_STOP BIT(0)
#define SENSOR_CONFIG0_TALL_SHIFT 8
@@ -43,225 +44,27 @@
#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
#define SENSOR_CONFIG1_TEMP_ENABLE BIT(31)
-#define SENSOR_CONFIG2 8
-#define SENSOR_CONFIG2_THERMA_SHIFT 16
-#define SENSOR_CONFIG2_THERMB_SHIFT 0
-
-#define SENSOR_PDIV 0x1c0
-#define SENSOR_PDIV_CPU_MASK (0xf << 12)
-#define SENSOR_PDIV_GPU_MASK (0xf << 8)
-#define SENSOR_PDIV_MEM_MASK (0xf << 4)
-#define SENSOR_PDIV_PLLX_MASK (0xf << 0)
-
-#define SENSOR_HOTSPOT_OFF 0x1c4
-#define SENSOR_HOTSPOT_CPU_MASK (0xff << 16)
-#define SENSOR_HOTSPOT_GPU_MASK (0xff << 8)
-#define SENSOR_HOTSPOT_MEM_MASK (0xff << 0)
-
-#define SENSOR_TEMP1 0x1c8
-#define SENSOR_TEMP1_CPU_TEMP_MASK (0xffff << 16)
-#define SENSOR_TEMP1_GPU_TEMP_MASK 0xffff
-#define SENSOR_TEMP2 0x1cc
-#define SENSOR_TEMP2_MEM_TEMP_MASK (0xffff << 16)
-#define SENSOR_TEMP2_PLLX_TEMP_MASK 0xffff
+/*
+ * SENSOR_CONFIG2 is defined in tegra_soctherm.h
+ * because, it will be used by tegra_soctherm_fuse.c
+ */
#define READBACK_VALUE_MASK 0xff00
#define READBACK_VALUE_SHIFT 8
#define READBACK_ADD_HALF BIT(7)
#define READBACK_NEGATE BIT(1)
-#define FUSE_TSENSOR8_CALIB 0x180
-#define FUSE_SPARE_REALIGNMENT_REG_0 0x1fc
-
-#define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff
-#define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13)
-#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
-
-#define FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK 0x3ff
-#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK (0x7ff << 10)
-#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT 10
-
-#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_MASK 0x3f
-#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK (0x1f << 21)
-#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT 21
-
-#define NOMINAL_CALIB_FT_T124 105
-#define NOMINAL_CALIB_CP_T124 25
-
/* get val from register(r) mask bits(m) */
#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
/* set val(v) to mask bits(m) of register(r) */
#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
(((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
-/**
- * struct tegra_tsensor_group - SOC_THERM sensor group data
- * @name: short name of the temperature sensor group
- * @id: numeric ID of the temperature sensor group
- * @sensor_temp_offset: offset of the SENSOR_TEMP* register
- * @sensor_temp_mask: bit mask for this sensor group in SENSOR_TEMP* register
- * @pdiv: the sensor count post-divider to use during runtime
- * @pdiv_ate: the sensor count post-divider used during automated test
- * @pdiv_mask: register bitfield mask for the PDIV field for this sensor
- * @pllx_hotspot_diff: hotspot offset from the PLLX sensor, must be 0 for
- PLLX sensor group
- * @pllx_hotspot_mask: register bitfield mask for the HOTSPOT field
- */
-struct tegra_tsensor_group {
- const char *name;
- u8 id;
- u16 sensor_temp_offset;
- u32 sensor_temp_mask;
- u32 pdiv, pdiv_ate, pdiv_mask;
- u32 pllx_hotspot_diff, pllx_hotspot_mask;
-};
-
-struct tegra_tsensor_configuration {
- u32 tall, tiddq_en, ten_count, tsample, tsample_ate;
-};
-
-struct tegra_tsensor {
- const struct tegra_tsensor_configuration *config;
- u32 base, calib_fuse_offset;
- /* Correction values used to modify values read from calibration fuses */
- s32 fuse_corr_alpha, fuse_corr_beta;
- const struct tegra_tsensor_group *group;
-};
-
struct tegra_thermctl_zone {
void __iomem *reg;
u32 mask;
};
-static const struct tegra_tsensor_configuration t124_tsensor_config = {
- .tall = 16300,
- .tiddq_en = 1,
- .ten_count = 1,
- .tsample = 120,
- .tsample_ate = 480,
-};
-
-static struct tegra_tsensor_group tegra124_tsensor_group_cpu = {
- .id = TEGRA124_SOCTHERM_SENSOR_CPU,
- .name = "cpu",
- .sensor_temp_offset = SENSOR_TEMP1,
- .sensor_temp_mask = SENSOR_TEMP1_CPU_TEMP_MASK,
- .pdiv = 8,
- .pdiv_ate = 8,
- .pdiv_mask = SENSOR_PDIV_CPU_MASK,
- .pllx_hotspot_diff = 10,
- .pllx_hotspot_mask = SENSOR_HOTSPOT_CPU_MASK,
-};
-
-static struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
- .id = TEGRA124_SOCTHERM_SENSOR_GPU,
- .name = "gpu",
- .sensor_temp_offset = SENSOR_TEMP1,
- .sensor_temp_mask = SENSOR_TEMP1_GPU_TEMP_MASK,
- .pdiv = 8,
- .pdiv_ate = 8,
- .pdiv_mask = SENSOR_PDIV_GPU_MASK,
- .pllx_hotspot_diff = 5,
- .pllx_hotspot_mask = SENSOR_HOTSPOT_GPU_MASK,
-};
-
-static struct tegra_tsensor_group tegra124_tsensor_group_pll = {
- .id = TEGRA124_SOCTHERM_SENSOR_PLLX,
- .name = "pll",
- .sensor_temp_offset = SENSOR_TEMP2,
- .sensor_temp_mask = SENSOR_TEMP2_PLLX_TEMP_MASK,
- .pdiv = 8,
- .pdiv_ate = 8,
- .pdiv_mask = SENSOR_PDIV_PLLX_MASK,
- .pllx_hotspot_diff = 0,
- .pllx_hotspot_mask = SENSOR_HOTSPOT_MEM_MASK,
-};
-
-static struct tegra_tsensor_group tegra124_tsensor_group_mem = {
- .id = TEGRA124_SOCTHERM_SENSOR_MEM,
- .name = "mem",
- .sensor_temp_offset = SENSOR_TEMP2,
- .sensor_temp_mask = SENSOR_TEMP2_MEM_TEMP_MASK,
- .pdiv = 8,
- .pdiv_ate = 8,
- .pdiv_mask = SENSOR_PDIV_MEM_MASK,
-};
-
-static struct tegra_tsensor_group *
-tegra124_tsensor_groups[TEGRA124_SOCTHERM_SENSOR_NUM] = {
- &tegra124_tsensor_group_cpu,
- &tegra124_tsensor_group_gpu,
- &tegra124_tsensor_group_pll,
- &tegra124_tsensor_group_mem,
-};
-
-static const struct tegra_tsensor t124_tsensors[] = {
- {
- .config = &t124_tsensor_config,
- .base = 0xc0,
- .calib_fuse_offset = 0x098,
- .fuse_corr_alpha = 1135400,
- .fuse_corr_beta = -6266900,
- .group = &tegra124_tsensor_group_cpu,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0xe0,
- .calib_fuse_offset = 0x084,
- .fuse_corr_alpha = 1122220,
- .fuse_corr_beta = -5700700,
- .group = &tegra124_tsensor_group_cpu,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0x100,
- .calib_fuse_offset = 0x088,
- .fuse_corr_alpha = 1127000,
- .fuse_corr_beta = -6768200,
- .group = &tegra124_tsensor_group_cpu,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0x120,
- .calib_fuse_offset = 0x12c,
- .fuse_corr_alpha = 1110900,
- .fuse_corr_beta = -6232000,
- .group = &tegra124_tsensor_group_cpu,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0x140,
- .calib_fuse_offset = 0x158,
- .fuse_corr_alpha = 1122300,
- .fuse_corr_beta = -5936400,
- .group = &tegra124_tsensor_group_mem,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0x160,
- .calib_fuse_offset = 0x15c,
- .fuse_corr_alpha = 1145700,
- .fuse_corr_beta = -7124600,
- .group = &tegra124_tsensor_group_mem,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0x180,
- .calib_fuse_offset = 0x154,
- .fuse_corr_alpha = 1120100,
- .fuse_corr_beta = -6000500,
- .group = &tegra124_tsensor_group_gpu,
- },
- {
- .config = &t124_tsensor_config,
- .base = 0x1a0,
- .calib_fuse_offset = 0x160,
- .fuse_corr_alpha = 1106500,
- .fuse_corr_beta = -6729300,
- .group = &tegra124_tsensor_group_pll,
- },
-};
-
struct tegra_soctherm {
struct reset_control *reset;
struct clk *clock_tsensor;
@@ -271,103 +74,15 @@ struct tegra_soctherm {
struct thermal_zone_device *thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_NUM];
};
-struct tsensor_shared_calibration {
- u32 base_cp, base_ft;
- u32 actual_temp_cp, actual_temp_ft;
-};
-
-static int calculate_shared_calibration(struct tsensor_shared_calibration *r)
-{
- u32 val, shifted_cp, shifted_ft;
- int err;
-
- err = tegra_fuse_readl(FUSE_TSENSOR8_CALIB, &val);
- if (err)
- return err;
- r->base_cp = val & FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK;
- r->base_ft = (val & FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK)
- >> FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT;
- val = ((val & FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK)
- >> FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT);
- shifted_ft = sign_extend32(val, 4);
-
- err = tegra_fuse_readl(FUSE_SPARE_REALIGNMENT_REG_0, &val);
- if (err)
- return err;
- shifted_cp = sign_extend32(val, 5);
-
- r->actual_temp_cp = 2 * NOMINAL_CALIB_CP_T124 + shifted_cp;
- r->actual_temp_ft = 2 * NOMINAL_CALIB_FT_T124 + shifted_ft;
-
- return 0;
-}
-
-static s64 div64_s64_precise(s64 a, s64 b)
-{
- s64 r, al;
-
- /* Scale up for increased precision division */
- al = a << 16;
-
- r = div64_s64(al * 2 + 1, 2 * b);
- return r >> 16;
-}
-
-static int
-calculate_tsensor_calibration(const struct tegra_tsensor *sensor,
- const struct tsensor_shared_calibration *shared,
- u32 *calib)
-{
- u32 val;
- s32 actual_tsensor_ft, actual_tsensor_cp, delta_sens, delta_temp,
- mult, div;
- s16 therma, thermb;
- s64 tmp;
- int err;
-
- err = tegra_fuse_readl(sensor->calib_fuse_offset, &val);
- if (err)
- return err;
-
- actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12);
- val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK)
- >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT;
- actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12);
-
- delta_sens = actual_tsensor_ft - actual_tsensor_cp;
- delta_temp = shared->actual_temp_ft - shared->actual_temp_cp;
-
- mult = sensor->group->pdiv * sensor->config->tsample_ate;
- div = sensor->config->tsample * sensor->group->pdiv_ate;
-
- therma = div64_s64_precise((s64) delta_temp * (1LL << 13) * mult,
- (s64) delta_sens * div);
-
- tmp = (s64)actual_tsensor_ft * shared->actual_temp_cp -
- (s64)actual_tsensor_cp * shared->actual_temp_ft;
- thermb = div64_s64_precise(tmp, (s64)delta_sens);
-
- therma = div64_s64_precise((s64)therma * sensor->fuse_corr_alpha,
- (s64)1000000LL);
- thermb = div64_s64_precise((s64)thermb * sensor->fuse_corr_alpha +
- sensor->fuse_corr_beta, (s64)1000000LL);
-
- *calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) |
- ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT);
-
- return 0;
-}
-
static int enable_tsensor(struct tegra_soctherm *tegra,
- const struct tegra_tsensor *sensor,
+ struct tegra_tsensor *sensor,
const struct tsensor_shared_calibration *shared)
{
void __iomem *base = tegra->regs + sensor->base;
unsigned int val;
- u32 calib;
int err;
- err = calculate_tsensor_calibration(sensor, shared, &calib);
+ err = tegra_soctherm_calculate_tsensor_calibration(sensor, shared);
if (err)
return err;
@@ -380,7 +95,7 @@ static int enable_tsensor(struct tegra_soctherm *tegra,
val |= SENSOR_CONFIG1_TEMP_ENABLE;
writel(val, base + SENSOR_CONFIG1);
- writel(calib, base + SENSOR_CONFIG2);
+ writel(sensor->calib, base + SENSOR_CONFIG2);
return 0;
}
@@ -422,13 +137,10 @@ static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
.get_temp = tegra_thermctl_get_temp,
};
-static const struct of_device_id tegra_soctherm_of_match[] = {
- { .compatible = "nvidia,tegra124-soctherm" },
- { },
-};
-MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
-
-static int tegra_soctherm_probe(struct platform_device *pdev)
+int tegra_soctherm_probe(struct platform_device *pdev,
+ struct tegra_tsensor *tsensors,
+ const struct tegra_tsensor_group **ttgs,
+ const struct tegra_soctherm_fuse *tfuse)
{
struct tegra_soctherm *tegra;
struct thermal_zone_device *tz;
@@ -438,9 +150,6 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
int err;
u32 pdiv, hotspot;
- const struct tegra_tsensor *tsensors = t124_tsensors;
- struct tegra_tsensor_group **ttgs = tegra124_tsensor_groups;
-
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
if (!tegra)
return -ENOMEM;
@@ -484,11 +193,11 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
/* Initialize raw sensors */
- err = calculate_shared_calibration(&shared_calib);
+ err = tegra_soctherm_calculate_shared_calibration(tfuse, &shared_calib);
if (err)
goto disable_clocks;
- for (i = 0; i < ARRAY_SIZE(t124_tsensors); ++i) {
+ for (i = 0; tsensors[i].name; ++i) {
err = enable_tsensor(tegra, tsensors + i, &shared_calib);
if (err)
goto disable_clocks;
@@ -548,7 +257,7 @@ disable_clocks:
return err;
}
-static int tegra_soctherm_remove(struct platform_device *pdev)
+int tegra_soctherm_remove(struct platform_device *pdev)
{
struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
unsigned int i;
@@ -564,16 +273,6 @@ static int tegra_soctherm_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver tegra_soctherm_driver = {
- .probe = tegra_soctherm_probe,
- .remove = tegra_soctherm_remove,
- .driver = {
- .name = "tegra-soctherm",
- .of_match_table = tegra_soctherm_of_match,
- },
-};
-module_platform_driver(tegra_soctherm_driver);
-
MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/tegra/tegra_soctherm.h b/drivers/thermal/tegra/tegra_soctherm.h
new file mode 100644
index 000000000000..8d06f4f75ff9
--- /dev/null
+++ b/drivers/thermal/tegra/tegra_soctherm.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
+#define __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
+
+#define SENSOR_CONFIG2 8
+#define SENSOR_CONFIG2_THERMA_SHIFT 16
+#define SENSOR_CONFIG2_THERMB_SHIFT 0
+
+#define SENSOR_PDIV 0x1c0
+#define SENSOR_PDIV_CPU_MASK (0xf << 12)
+#define SENSOR_PDIV_GPU_MASK (0xf << 8)
+#define SENSOR_PDIV_MEM_MASK (0xf << 4)
+#define SENSOR_PDIV_PLLX_MASK (0xf << 0)
+
+#define SENSOR_HOTSPOT_OFF 0x1c4
+#define SENSOR_HOTSPOT_CPU_MASK (0xff << 16)
+#define SENSOR_HOTSPOT_GPU_MASK (0xff << 8)
+#define SENSOR_HOTSPOT_MEM_MASK (0xff << 0)
+
+#define SENSOR_TEMP1 0x1c8
+#define SENSOR_TEMP1_CPU_TEMP_MASK (0xffff << 16)
+#define SENSOR_TEMP1_GPU_TEMP_MASK 0xffff
+#define SENSOR_TEMP2 0x1cc
+#define SENSOR_TEMP2_MEM_TEMP_MASK (0xffff << 16)
+#define SENSOR_TEMP2_PLLX_TEMP_MASK 0xffff
+
+/**
+ * struct tegra_tsensor_group - SOC_THERM sensor group data
+ * @name: short name of the temperature sensor group
+ * @id: numeric ID of the temperature sensor group
+ * @sensor_temp_offset: offset of the SENSOR_TEMP* register
+ * @sensor_temp_mask: bit mask for this sensor group in SENSOR_TEMP* register
+ * @pdiv: the sensor count post-divider to use during runtime
+ * @pdiv_ate: the sensor count post-divider used during automated test
+ * @pdiv_mask: register bitfield mask for the PDIV field for this sensor
+ * @pllx_hotspot_diff: hotspot offset from the PLLX sensor, must be 0 for
+ PLLX sensor group
+ * @pllx_hotspot_mask: register bitfield mask for the HOTSPOT field
+ */
+struct tegra_tsensor_group {
+ const char *name;
+ u8 id;
+ u16 sensor_temp_offset;
+ u32 sensor_temp_mask;
+ u32 pdiv, pdiv_ate, pdiv_mask;
+ u32 pllx_hotspot_diff, pllx_hotspot_mask;
+};
+
+struct tegra_tsensor_configuration {
+ u32 tall, tiddq_en, ten_count, pdiv, pdiv_ate, tsample, tsample_ate;
+};
+
+struct tegra_tsensor {
+ const char *name;
+ u32 base;
+ const struct tegra_tsensor_configuration *config;
+ u32 calib_fuse_offset;
+ /*
+ * Correction values used to modify values read from
+ * calibration fuses
+ */
+ s32 fuse_corr_alpha, fuse_corr_beta;
+ u32 calib;
+ const struct tegra_tsensor_group *group;
+};
+
+struct tegra_soctherm_fuse {
+ u32 fuse_base_cp_mask, fuse_base_cp_shift;
+ u32 fuse_base_ft_mask, fuse_base_ft_shift;
+ u32 fuse_shift_ft_mask, fuse_shift_ft_shift;
+ u32 fuse_spare_realignment;
+};
+
+struct tsensor_shared_calibration {
+ u32 base_cp, base_ft;
+ u32 actual_temp_cp, actual_temp_ft;
+};
+
+int tegra_soctherm_calculate_shared_calibration(
+ const struct tegra_soctherm_fuse *tfuse,
+ struct tsensor_shared_calibration *shared);
+int tegra_soctherm_calculate_tsensor_calibration(
+ struct tegra_tsensor *sensor,
+ const struct tsensor_shared_calibration *shared);
+
+int tegra_soctherm_probe(struct platform_device *pdev,
+ struct tegra_tsensor *tsensors,
+ const struct tegra_tsensor_group **ttgs,
+ const struct tegra_soctherm_fuse *tfuse);
+int tegra_soctherm_remove(struct platform_device *pdev);
+
+#endif
+
diff --git a/drivers/thermal/tegra/tegra_soctherm_fuse.c b/drivers/thermal/tegra/tegra_soctherm_fuse.c
new file mode 100644
index 000000000000..7c608698f1ae
--- /dev/null
+++ b/drivers/thermal/tegra/tegra_soctherm_fuse.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <soc/tegra/fuse.h>
+
+#include "tegra_soctherm.h"
+
+#define NOMINAL_CALIB_FT 105
+#define NOMINAL_CALIB_CP 25
+
+#define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff
+#define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13)
+#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
+
+#define FUSE_TSENSOR_COMMON 0x180
+
+/*
+ * T12x, etc: FUSE_TSENSOR_COMMON:
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |-----------| SHFT_FT | BASE_FT | BASE_CP |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * FUSE_SPARE_REALIGNMENT_REG:
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |---------------------------------------------------| SHIFT_CP |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+static s64 div64_s64_precise(s64 a, s64 b)
+{
+ s64 r, al;
+
+ /* Scale up for increased precision division */
+ al = a << 16;
+
+ r = div64_s64(al * 2 + 1, 2 * b);
+ return r >> 16;
+}
+
+int tegra_soctherm_calculate_shared_calibration(
+ const struct tegra_soctherm_fuse *tfuse,
+ struct tsensor_shared_calibration *r)
+{
+ u32 val;
+ s32 shifted_cp, shifted_ft;
+ int err;
+
+ err = tegra_fuse_readl(FUSE_TSENSOR_COMMON, &val);
+ if (err)
+ return err;
+
+ r->base_cp = (val & tfuse->fuse_base_cp_mask)
+ >> tfuse->fuse_base_cp_shift;
+ r->base_ft = (val & tfuse->fuse_base_ft_mask)
+ >> tfuse->fuse_base_ft_shift;
+
+ shifted_ft = (val & tfuse->fuse_shift_ft_mask)
+ >> tfuse->fuse_shift_ft_shift;
+ shifted_ft = sign_extend32(shifted_ft, 4);
+
+ if (tfuse->fuse_spare_realignment) {
+ err = tegra_fuse_readl(tfuse->fuse_spare_realignment, &val);
+ if (err)
+ return err;
+ }
+
+ shifted_cp = sign_extend32(val, 5);
+
+ r->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp;
+ r->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft;
+
+ return 0;
+}
+
+int tegra_soctherm_calculate_tsensor_calibration(
+ struct tegra_tsensor *sensor,
+ const struct tsensor_shared_calibration *shared)
+{
+ const struct tegra_tsensor_group *sensor_group;
+ u32 val, calib;
+ s32 actual_tsensor_ft, actual_tsensor_cp;
+ s32 delta_sens, delta_temp;
+ s32 mult, div;
+ s16 therma, thermb;
+ int err;
+
+ sensor_group = sensor->group;
+
+ err = tegra_fuse_readl(sensor->calib_fuse_offset, &val);
+ if (err)
+ return err;
+
+ actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12);
+ val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK)
+ >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT;
+ actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12);
+
+ delta_sens = actual_tsensor_ft - actual_tsensor_cp;
+ delta_temp = shared->actual_temp_ft - shared->actual_temp_cp;
+
+ mult = sensor_group->pdiv * sensor->config->tsample_ate;
+ div = sensor->config->tsample * sensor_group->pdiv_ate;
+
+ therma = div64_s64_precise((s64)delta_temp * (1LL << 13) * mult,
+ (s64)delta_sens * div);
+ thermb = div64_s64_precise(
+ ((s64)actual_tsensor_ft * shared->actual_temp_cp) -
+ ((s64)actual_tsensor_cp * shared->actual_temp_ft),
+ (s64)delta_sens);
+
+ therma = div64_s64_precise((s64)therma * sensor->fuse_corr_alpha,
+ (s64)1000000LL);
+ thermb = div64_s64_precise((s64)thermb * sensor->fuse_corr_alpha +
+ sensor->fuse_corr_beta,
+ (s64)1000000LL);
+ calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) |
+ ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT);
+
+ sensor->calib = calib;
+
+ return 0;
+}
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("Tegra SOCTHERM fuse management");
+MODULE_LICENSE("GPL v2");
--
1.9.1
[toc] | [next] | [standalone]
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2016-01-13 16:10 +0100 |
| Message-ID | <qQvdF-1tl-45@gated-at.bofh.it> |
| In reply to | #1308135 |
[Multipart message — attachments visible in raw view] — view raw
On Wed, Jan 13, 2016 at 03:58:42PM +0800, Wei Ni wrote:
> Split most of the T124 data and code into a T124-specific driver.
> Split most of the fuse-related code into a fuse-related source file.
> Now drivers/thermal/tegra_soctherm.c contains common SOC_THERM library
That path no longer exists since patch 01/10.
> diff --git a/drivers/thermal/tegra/Kconfig b/drivers/thermal/tegra/Kconfig
> index a6e6cd4528dc..ae7e5e93dab9 100644
> --- a/drivers/thermal/tegra/Kconfig
> +++ b/drivers/thermal/tegra/Kconfig
> @@ -1,6 +1,10 @@
> config TEGRA_SOCTHERM
> - tristate "Tegra SOCTHERM thermal management"
> - depends on ARCH_TEGRA
> + bool
> +
> +config TEGRA124_SOCTHERM
> + bool "Tegra124 SOCTHERM thermal management"
> + depends on ARCH_TEGRA_124_SOC
> + select TEGRA_SOCTHERM
> help
> Enable this option for integrated thermal management support on NVIDIA
> Tegra124 systems-on-chip. The driver supports four thermal zones
I'd like to do this differently to reduce the number of Kconfig symbols.
The alternate proposal would be for the TEGRA_SOCTHERM symbol to remain
as it is and then build in driver support depending on the selected
ARCH_TEGRA_*_SOC options.
> diff --git a/drivers/thermal/tegra/Makefile b/drivers/thermal/tegra/Makefile
> index 8c51076e4b1e..7a864ec07a25 100644
> --- a/drivers/thermal/tegra/Makefile
> +++ b/drivers/thermal/tegra/Makefile
> @@ -3,4 +3,5 @@
> #
>
> # Tegra soc thermal drivers
> -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
> +obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o tegra_soctherm_fuse.o
> +obj-$(CONFIG_TEGRA124_SOCTHERM) += tegra124_soctherm.o
So this would look roughly like:
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
tegra-soctherm-y := soctherm.c
tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
Two things to note here: I've replaced the underscore in the filename
with a dash, because that's more commonly used in filenames for other
drivers on Tegra. This could be done in patch 01/10 since the file is
already moved anyway. The second thing to note here is that the SoC-
generation specific drivers don't contain the redundant _soctherm
suffix. I suppose that if this directory will ever contain anything
other than soctherm drivers it might be useful to have the suffix to
differentiate between different drivers, so feel free to ignore that
suggestion if you have plans to add other thermal-related drivers to
this directory.
The advantage of the above is that we'll have a single Kconfig option
to worry about and also everything will be included in a single driver
rather than per-SoC "drivers" that merely provide the SoC-specific
data. This will require some slight changes to the driver code, see
below.
> diff --git a/drivers/thermal/tegra/tegra124_soctherm.c b/drivers/thermal/tegra/tegra124_soctherm.c
[...]
> +static const struct tegra_tsensor_group *
> +tegra124_tsensor_groups[TEGRA124_SOCTHERM_SENSOR_NUM] = {
> + &tegra124_tsensor_group_cpu,
> + &tegra124_tsensor_group_gpu,
> + &tegra124_tsensor_group_pll,
> + &tegra124_tsensor_group_mem,
> +};
> +
> +static struct tegra_tsensor tegra124_tsensors[] = {
[...]
> + { .name = NULL },
> +};
I think it'd be good not to rely on this sentinel entry being there.
It's more error-prone than simply storing the number of entries in a
separate location. See below.
> +static const struct of_device_id tegra124_soctherm_of_match[] = {
> + { .compatible = "nvidia,tegra124-soctherm" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
The general idea would be to keep the of_device_id table in the
tegra_soctherm.c file and have it include entries depending on which SoC
generation is being supported. See for example the memory controller
driver in drivers/memory/tegra for a reference that uses this style of
multi-SoC support.
> +
> +static int tegra124_soctherm_probe(struct platform_device *pdev)
> +{
> + return tegra_soctherm_probe(pdev,
> + tegra124_tsensors,
> + tegra124_tsensor_groups,
> + &tegra124_soctherm_fuse);
> +}
> +
> +static struct platform_driver tegra124_soctherm_driver = {
> + .probe = tegra124_soctherm_probe,
> + .remove = tegra_soctherm_remove,
> + .driver = {
> + .name = "tegra124_soctherm",
> + .of_match_table = tegra124_soctherm_of_match,
> + },
> +};
> +module_platform_driver(tegra124_soctherm_driver);
> +
> +MODULE_AUTHOR("NVIDIA");
> +MODULE_DESCRIPTION("Tegra124 SOCTHERM thermal management driver");
> +MODULE_LICENSE("GPL v2");
With the alternate proposal you can get rid of all of this, which has a
number of other advantages like not having to export all of the library
functions that these subdrivers rely on.
What you'd do instead is add a new structure, along the lines of this:
struct tegra_soctherm_soc {
const struct tegra_tsensor_groups *groups;
unsigned int num_groups;
const struct tegra_tsensor *sensors;
unsigned int num_sensors;
const struct tegra_soctherm_fuse *fuse;
};
and create one of these with the SoC-specific groups, sensors and FUSE
parameters. Then you pass these structures to the generic driver as the
struct of_device_id's .data field:
static const struct of_device_id tegra_soctherm_of_match[] = {
{ .compatible = "nvidia,tegra124-soctherm", .data = &tegra124_soctherm },
{ .compatible = "nvidia,tegra210-soctherm", .data = &tegra210_soctherm },
{ }
};
Also, please use your name and email address if you're the author.
Companies don't write code, people do.
> -static int tegra_soctherm_probe(struct platform_device *pdev)
> +int tegra_soctherm_probe(struct platform_device *pdev,
> + struct tegra_tsensor *tsensors,
> + const struct tegra_tsensor_group **ttgs,
> + const struct tegra_soctherm_fuse *tfuse)
> {
[...]
> }
>
> -static int tegra_soctherm_remove(struct platform_device *pdev)
> +int tegra_soctherm_remove(struct platform_device *pdev)
> {
> struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
> unsigned int i;
> @@ -564,16 +273,6 @@ static int tegra_soctherm_remove(struct platform_device *pdev)
> return 0;
> }
Both the tegra_soctherm_probe() and tegra_soctherm_remove() functions
would need to be exported with this type of driver design, otherwise
building everything as modules the per-SoC drivers couldn't access the
functions.
If you create a single driver there is no need to export any of the
symbols because they are never required by another module.
Thierry
[toc] | [prev] | [next] | [standalone]
| From | Wei Ni <wni@nvidia.com> |
|---|---|
| Date | 2016-01-14 11:00 +0100 |
| Message-ID | <qQMRc-5dh-15@gated-at.bofh.it> |
| In reply to | #1308490 |
Thierry,
On 2016年01月13日 23:04, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Wed, Jan 13, 2016 at 03:58:42PM +0800, Wei Ni wrote:
>> Split most of the T124 data and code into a T124-specific driver.
>> Split most of the fuse-related code into a fuse-related source file.
>> Now drivers/thermal/tegra_soctherm.c contains common SOC_THERM library
>
> That path no longer exists since patch 01/10.
Yes, will remove it.
>
>> diff --git a/drivers/thermal/tegra/Kconfig b/drivers/thermal/tegra/Kconfig
>> index a6e6cd4528dc..ae7e5e93dab9 100644
>> --- a/drivers/thermal/tegra/Kconfig
>> +++ b/drivers/thermal/tegra/Kconfig
>> @@ -1,6 +1,10 @@
>> config TEGRA_SOCTHERM
>> - tristate "Tegra SOCTHERM thermal management"
>> - depends on ARCH_TEGRA
>> + bool
>> +
>> +config TEGRA124_SOCTHERM
>> + bool "Tegra124 SOCTHERM thermal management"
>> + depends on ARCH_TEGRA_124_SOC
>> + select TEGRA_SOCTHERM
>> help
>> Enable this option for integrated thermal management support on NVIDIA
>> Tegra124 systems-on-chip. The driver supports four thermal zones
>
> I'd like to do this differently to reduce the number of Kconfig symbols.
> The alternate proposal would be for the TEGRA_SOCTHERM symbol to remain
> as it is and then build in driver support depending on the selected
> ARCH_TEGRA_*_SOC options.
Yes, it will make the kconfig more clear. Will change it.
>
>> diff --git a/drivers/thermal/tegra/Makefile b/drivers/thermal/tegra/Makefile
>> index 8c51076e4b1e..7a864ec07a25 100644
>> --- a/drivers/thermal/tegra/Makefile
>> +++ b/drivers/thermal/tegra/Makefile
>> @@ -3,4 +3,5 @@
>> #
>>
>> # Tegra soc thermal drivers
>> -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
>> +obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o tegra_soctherm_fuse.o
>> +obj-$(CONFIG_TEGRA124_SOCTHERM) += tegra124_soctherm.o
>
> So this would look roughly like:
>
> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
>
> tegra-soctherm-y := soctherm.c
> tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
> tegra-soctherm-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
>
> Two things to note here: I've replaced the underscore in the filename
> with a dash, because that's more commonly used in filenames for other
> drivers on Tegra. This could be done in patch 01/10 since the file is
Yes, will change to use dash.
> already moved anyway. The second thing to note here is that the SoC-
> generation specific drivers don't contain the redundant _soctherm
> suffix. I suppose that if this directory will ever contain anything
> other than soctherm drivers it might be useful to have the suffix to
> differentiate between different drivers, so feel free to ignore that
> suggestion if you have plans to add other thermal-related drivers to
> this directory.
Yes, I plan to add thermal-throttle driver in this directory, so will keep the
name tegraxxx_soctherm.c
>
> The advantage of the above is that we'll have a single Kconfig option
> to worry about and also everything will be included in a single driver
> rather than per-SoC "drivers" that merely provide the SoC-specific
> data. This will require some slight changes to the driver code, see
> below.
>
>> diff --git a/drivers/thermal/tegra/tegra124_soctherm.c b/drivers/thermal/tegra/tegra124_soctherm.c
> [...]
>> +static const struct tegra_tsensor_group *
>> +tegra124_tsensor_groups[TEGRA124_SOCTHERM_SENSOR_NUM] = {
>> + &tegra124_tsensor_group_cpu,
>> + &tegra124_tsensor_group_gpu,
>> + &tegra124_tsensor_group_pll,
>> + &tegra124_tsensor_group_mem,
>> +};
>> +
>> +static struct tegra_tsensor tegra124_tsensors[] = {
> [...]
>> + { .name = NULL },
>> +};
>
> I think it'd be good not to rely on this sentinel entry being there.
> It's more error-prone than simply storing the number of entries in a
> separate location. See below.
Ok, will do it.
>
>> +static const struct of_device_id tegra124_soctherm_of_match[] = {
>> + { .compatible = "nvidia,tegra124-soctherm" },
>> + { },
>> +};
>> +MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
>
> The general idea would be to keep the of_device_id table in the
> tegra_soctherm.c file and have it include entries depending on which SoC
> generation is being supported. See for example the memory controller
> driver in drivers/memory/tegra for a reference that uses this style of
> multi-SoC support.
Got it, will do it.
>
>> +
>> +static int tegra124_soctherm_probe(struct platform_device *pdev)
>> +{
>> + return tegra_soctherm_probe(pdev,
>> + tegra124_tsensors,
>> + tegra124_tsensor_groups,
>> + &tegra124_soctherm_fuse);
>> +}
>> +
>> +static struct platform_driver tegra124_soctherm_driver = {
>> + .probe = tegra124_soctherm_probe,
>> + .remove = tegra_soctherm_remove,
>> + .driver = {
>> + .name = "tegra124_soctherm",
>> + .of_match_table = tegra124_soctherm_of_match,
>> + },
>> +};
>> +module_platform_driver(tegra124_soctherm_driver);
>> +
>> +MODULE_AUTHOR("NVIDIA");
>> +MODULE_DESCRIPTION("Tegra124 SOCTHERM thermal management driver");
>> +MODULE_LICENSE("GPL v2");
>
> With the alternate proposal you can get rid of all of this, which has a
> number of other advantages like not having to export all of the library
> functions that these subdrivers rely on.
>
> What you'd do instead is add a new structure, along the lines of this:
>
> struct tegra_soctherm_soc {
> const struct tegra_tsensor_groups *groups;
> unsigned int num_groups;
> const struct tegra_tsensor *sensors;
> unsigned int num_sensors;
> const struct tegra_soctherm_fuse *fuse;
> };
>
> and create one of these with the SoC-specific groups, sensors and FUSE
> parameters. Then you pass these structures to the generic driver as the
> struct of_device_id's .data field:
>
> static const struct of_device_id tegra_soctherm_of_match[] = {
> { .compatible = "nvidia,tegra124-soctherm", .data = &tegra124_soctherm },
> { .compatible = "nvidia,tegra210-soctherm", .data = &tegra210_soctherm },
> { }
> };
>
> Also, please use your name and email address if you're the author.
> Companies don't write code, people do.
Will do it.
>
>> -static int tegra_soctherm_probe(struct platform_device *pdev)
>> +int tegra_soctherm_probe(struct platform_device *pdev,
>> + struct tegra_tsensor *tsensors,
>> + const struct tegra_tsensor_group **ttgs,
>> + const struct tegra_soctherm_fuse *tfuse)
>> {
> [...]
>> }
>>
>> -static int tegra_soctherm_remove(struct platform_device *pdev)
>> +int tegra_soctherm_remove(struct platform_device *pdev)
>> {
>> struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
>> unsigned int i;
>> @@ -564,16 +273,6 @@ static int tegra_soctherm_remove(struct platform_device *pdev)
>> return 0;
>> }
>
> Both the tegra_soctherm_probe() and tegra_soctherm_remove() functions
> would need to be exported with this type of driver design, otherwise
> building everything as modules the per-SoC drivers couldn't access the
> functions.
>
> If you create a single driver there is no need to export any of the
> symbols because they are never required by another module.
I will use the new type, so will not export them.
>
> Thierry
>
> * Unknown Key
> * 0x7F3EB3A1
>
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web