Short term bandaid fixes to add support for more versions of the TSENS IP
is not proving to be very scalable. Here is a series to finally convert the
driver's core to use regmap_fields so that register addresses and bitfields
can be abstracted away from the code.
This series is posted as one to give a complete view of where I'm going
with this refactor. We can probably split it into smaller sets if required.
Currently it consists of the following parts:
- Patch 01-06: Style changes to make code easier to read (mostly naming
related). This has no functional change in the driver, it is a series of
search and replace operations. Ideally this will get merged first,
otherwise everything else will become painful :-)
- Patch 07-09: Merge the 8916 and 8974 source files into a single one
called v0_1.c denoting the version of the IP and open up more
opportunities for reuse.
- Patch 10: This is the core patch that adds IP-specific data based on two
data structures: tsens_features has bit flags to identify if a certain
feature is available in a version or not and an array of reg_field
pointers.
regfield_ids list the important fields across IP versions and are used as
an index.
This patch converts over all platforms except 8960 which currently
doesn't use DT data for tsens and has custom functions for everything. We
will get to it eventually, but it's conversion is not a necessity for
this series to be merged.
- Patch 11-16: Clean ups and new functionality based on regmap_field
- Patch 17-19: Refactor the get_temp routine. We expect to have a single
get_temp routine once all the conversion is finished.
- Patch 20-23: Introduce qcs404 support using new regmap infrastructure.
Testing
-------
Since these changes affect every platform using TSENS, it should be
clarified that I have only been focussing on developing/testing this on
sdm845 and qcs404. I will test this more thoroughly on msm8916, msm8996,
msm8998 but it is still pending.
Future work
-----------
a. Get rid of get_temp_common in favour of get_temp_tsens_valid
b. irq support
c. Convert over 8960 to use regmap_field and as a result common functions
Regards,
Amit
Amit Kucheria (24):
drivers: thermal: tsens: Document the data structures
drivers: thermal: tsens: Rename tsens_data
drivers: thermal: tsens: Rename tsens_device
drivers: thermal: tsens: Rename variable tmdev
drivers: thermal: tsens: Use consistent names for variables
drivers: thermal: tsens: Function prototypes should have argument
names
drivers: thermal: tsens: Rename tsens-8916 to prepare to merge with
tsens-8974
drivers: thermal: tsens: Rename constants to prepare to merge with
tsens-8974
drivers: thermal: tsens: Merge tsens-8974 into tsens-v0_1
drivers: thermal: tsens: Introduce reg_fields to deal with register
description
drivers: thermal: tsens: Save reference to the device pointer and use
it
drivers: thermal: tsens: Don't print error message on -EPROBE_DEFER
drivers: thermal: tsens: Print IP version
drivers: thermal: tsens: Add new operation to check if a sensor is
enabled
drivers: thermal: tsens: change data type for sensor IDs
drivers: thermal: tsens: Introduce IP-specific max_sensor count
drivers: thermal: tsens: simplify get_temp_tsens_v2 routine
drivers: thermal: tsens: Move get_temp_tsens_v2 to allow sharing
drivers: thermal: tsens: Common get_temp() learns to do ADC conversion
dt: thermal: tsens: Add bindings for qcs404
drivers: thermal: tsens: Add generic support for TSENS v1 IP
arm64: dts: qcom: qcs404: Add tsens controller
arm64: dts: qcom: qcs404: Add thermal zones for each sensor
drivers: thermal: tsens: Move calibration constants to header file
.../bindings/thermal/qcom-tsens.txt | 14 +
arch/arm64/boot/dts/qcom/qcs404.dtsi | 263 ++++++++++++++++++
drivers/thermal/qcom/Makefile | 4 +-
drivers/thermal/qcom/tsens-8916.c | 105 -------
drivers/thermal/qcom/tsens-8960.c | 84 +++---
drivers/thermal/qcom/tsens-common.c | 172 +++++++++---
.../qcom/{tsens-8974.c => tsens-v0_1.c} | 167 ++++++++++-
drivers/thermal/qcom/tsens-v1.c | 229 +++++++++++++++
drivers/thermal/qcom/tsens-v2.c | 148 ++++++----
drivers/thermal/qcom/tsens.c | 100 ++++---
drivers/thermal/qcom/tsens.h | 238 ++++++++++++++--
11 files changed, 1191 insertions(+), 333 deletions(-)
delete mode 100644 drivers/thermal/qcom/tsens-8916.c
rename drivers/thermal/qcom/{tsens-8974.c => tsens-v0_1.c} (55%)
create mode 100644 drivers/thermal/qcom/tsens-v1.c
--
2.17.1
Describe how the TSENS device and the various sensors connected to it
are described in the driver
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens.h | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 7b7feee5dc46..89318523c848 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -14,6 +14,16 @@
struct tsens_device;
+/**
+ * struct tsens_sensor - data for each sensor connected to the tsens device
+ * @tmdev: tsens device instance that this sensor is connected to
+ * @tzd: pointer to the thermal zone that this sensor is in
+ * @offset: offset of temperature adjustment curve
+ * @id: Sensor ID
+ * @hw_id: HW ID can be used in case of platform-specific IDs
+ * @slope: slope of temperature adjustment curve
+ * @status: 8960-specific variable to track 8960 and 8660 status register offset
+ */
struct tsens_sensor {
struct tsens_device *tmdev;
struct thermal_zone_device *tzd;
@@ -55,8 +65,8 @@ enum reg_list {
};
/**
- * struct tsens_data - tsens instance specific data
- * @num_sensors: Max number of sensors supported by platform
+ * struct tsens_data - tsens platform data
+ * @num_sensors: Number of sensors supported by platform
* @ops: operations the tsens instance supports
* @hw_ids: Subset of sensors ids supported by platform, if not the first n
* @reg_offsets: Register offsets for commonly used registers
@@ -68,12 +78,27 @@ struct tsens_data {
unsigned int *hw_ids;
};
-/* Registers to be saved/restored across a context loss */
+/**
+ * struct tsens_context - Registers to be saved/restored across a context loss
+ */
struct tsens_context {
int threshold;
int control;
};
+/**
+ * struct tsens_device - private data for each instance of the tsens IP
+ * @dev: pointer to struct device
+ * @num_sensors: number of sensors enabled on this device
+ * @tm_map: pointer to TM register address space
+ * @srot_map: pointer to SROT register address space
+ * @tm_offset: deal with old device trees that don't address TM and SROT
+ * address space separately
+ * @reg_offsets: array of offsets to important regs for this version of IP
+ * @ctx: registers to be saved and restored during suspend/resume
+ * @ops: pointer to list of callbacks supported by this device
+ * @sensor: list of sensors attached to this device
+ */
struct tsens_device {
struct device *dev;
u32 num_sensors;
--
2.17.1
Rename to tsens_plat_data to denote that it is platform-data passed in
at compile-time.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-8916.c | 2 +-
drivers/thermal/qcom/tsens-8960.c | 2 +-
drivers/thermal/qcom/tsens-8974.c | 2 +-
drivers/thermal/qcom/tsens-v2.c | 4 ++--
drivers/thermal/qcom/tsens.c | 2 +-
drivers/thermal/qcom/tsens.h | 8 ++++----
6 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
index c6dd620ac029..66edcfca1526 100644
--- a/drivers/thermal/qcom/tsens-8916.c
+++ b/drivers/thermal/qcom/tsens-8916.c
@@ -97,7 +97,7 @@ static const struct tsens_ops ops_8916 = {
.get_temp = get_temp_common,
};
-const struct tsens_data data_8916 = {
+const struct tsens_plat_data data_8916 = {
.num_sensors = 5,
.ops = &ops_8916,
.reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
index 0f0adb302a7b..f3c3820e6e8e 100644
--- a/drivers/thermal/qcom/tsens-8960.c
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -277,7 +277,7 @@ static const struct tsens_ops ops_8960 = {
.resume = resume_8960,
};
-const struct tsens_data data_8960 = {
+const struct tsens_plat_data data_8960 = {
.num_sensors = 11,
.ops = &ops_8960,
};
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
index 3d3fda3d731b..5023f20afc14 100644
--- a/drivers/thermal/qcom/tsens-8974.c
+++ b/drivers/thermal/qcom/tsens-8974.c
@@ -229,7 +229,7 @@ static const struct tsens_ops ops_8974 = {
.get_temp = get_temp_common,
};
-const struct tsens_data data_8974 = {
+const struct tsens_plat_data data_8974 = {
.num_sensors = 11,
.ops = &ops_8974,
.reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 381a212872bf..cc98a61e093b 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -66,13 +66,13 @@ static const struct tsens_ops ops_generic_v2 = {
.get_temp = get_temp_tsens_v2,
};
-const struct tsens_data data_tsens_v2 = {
+const struct tsens_plat_data data_tsens_v2 = {
.ops = &ops_generic_v2,
.reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 },
};
/* Kept around for backward compatibility with old msm8996.dtsi */
-const struct tsens_data data_8996 = {
+const struct tsens_plat_data data_8996 = {
.num_sensors = 13,
.ops = &ops_generic_v2,
.reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 },
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index f1ec9bbe4717..065ec2189bd3 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -102,7 +102,7 @@ static int tsens_probe(struct platform_device *pdev)
struct device *dev;
struct device_node *np;
struct tsens_device *tmdev;
- const struct tsens_data *data;
+ const struct tsens_plat_data *data;
const struct of_device_id *id;
u32 num_sensors;
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 89318523c848..232376c690cc 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -65,13 +65,13 @@ enum reg_list {
};
/**
- * struct tsens_data - tsens platform data
+ * struct tsens_plat_data - tsens compile-time platform data
* @num_sensors: Number of sensors supported by platform
* @ops: operations the tsens instance supports
* @hw_ids: Subset of sensors ids supported by platform, if not the first n
* @reg_offsets: Register offsets for commonly used registers
*/
-struct tsens_data {
+struct tsens_plat_data {
const u32 num_sensors;
const struct tsens_ops *ops;
const u16 reg_offsets[REG_ARRAY_SIZE];
@@ -117,8 +117,8 @@ int init_common(struct tsens_device *);
int get_temp_common(struct tsens_device *, int, int *);
/* TSENS v1 targets */
-extern const struct tsens_data data_8916, data_8974, data_8960;
+extern const struct tsens_plat_data data_8916, data_8974, data_8960;
/* TSENS v2 targets */
-extern const struct tsens_data data_8996, data_tsens_v2;
+extern const struct tsens_plat_data data_8996, data_tsens_v2;
#endif /* __QCOM_TSENS_H__ */
--
2.17.1
tsens_get_temp() uses the name 'data' for the void pointer, use the same
in tsens_get_trend() for consistency.
Remove a stray space while we're at it.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 4582d2b30e94..0b5be08d515f 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -20,13 +20,13 @@ static int tsens_get_temp(void *data, int *temp)
return priv->ops->get_temp(priv, s->id, temp);
}
-static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
+static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend)
{
- const struct tsens_sensor *s = p;
+ const struct tsens_sensor *s = data;
struct tsens_priv *priv = s->priv;
if (priv->ops->get_trend)
- return priv->ops->get_trend(priv, s->id, trend);
+ return priv->ops->get_trend(priv, s->id, trend);
return -ENOTSUPP;
}
--
2.17.1
Rename to tsens_priv to denote that it is private data for each tsens
instance.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-8916.c | 2 +-
drivers/thermal/qcom/tsens-8960.c | 14 +++++++-------
drivers/thermal/qcom/tsens-8974.c | 2 +-
drivers/thermal/qcom/tsens-common.c | 6 +++---
drivers/thermal/qcom/tsens-v2.c | 2 +-
drivers/thermal/qcom/tsens.c | 14 +++++++-------
drivers/thermal/qcom/tsens.h | 30 ++++++++++++++---------------
7 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
index 66edcfca1526..7b8f83c9a033 100644
--- a/drivers/thermal/qcom/tsens-8916.c
+++ b/drivers/thermal/qcom/tsens-8916.c
@@ -39,7 +39,7 @@
#define CAL_SEL_MASK 0xe0000000
#define CAL_SEL_SHIFT 29
-static int calibrate_8916(struct tsens_device *tmdev)
+static int calibrate_8916(struct tsens_priv *tmdev)
{
int base0 = 0, base1 = 0, i;
u32 p1[5], p2[5];
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
index f3c3820e6e8e..7e340eea48da 100644
--- a/drivers/thermal/qcom/tsens-8960.c
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -56,7 +56,7 @@
#define TRDY_MASK BIT(7)
#define TIMEOUT_US 100
-static int suspend_8960(struct tsens_device *tmdev)
+static int suspend_8960(struct tsens_priv *tmdev)
{
int ret;
unsigned int mask;
@@ -82,7 +82,7 @@ static int suspend_8960(struct tsens_device *tmdev)
return 0;
}
-static int resume_8960(struct tsens_device *tmdev)
+static int resume_8960(struct tsens_priv *tmdev)
{
int ret;
struct regmap *map = tmdev->tm_map;
@@ -112,7 +112,7 @@ static int resume_8960(struct tsens_device *tmdev)
return 0;
}
-static int enable_8960(struct tsens_device *tmdev, int id)
+static int enable_8960(struct tsens_priv *tmdev, int id)
{
int ret;
u32 reg, mask;
@@ -138,7 +138,7 @@ static int enable_8960(struct tsens_device *tmdev, int id)
return 0;
}
-static void disable_8960(struct tsens_device *tmdev)
+static void disable_8960(struct tsens_priv *tmdev)
{
int ret;
u32 reg_cntl;
@@ -162,7 +162,7 @@ static void disable_8960(struct tsens_device *tmdev)
regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
}
-static int init_8960(struct tsens_device *tmdev)
+static int init_8960(struct tsens_priv *tmdev)
{
int ret, i;
u32 reg_cntl;
@@ -212,7 +212,7 @@ static int init_8960(struct tsens_device *tmdev)
return 0;
}
-static int calibrate_8960(struct tsens_device *tmdev)
+static int calibrate_8960(struct tsens_priv *tmdev)
{
int i;
char *data;
@@ -243,7 +243,7 @@ static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
return adc_code * slope + offset;
}
-static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
+static int get_temp_8960(struct tsens_priv *tmdev, int id, int *temp)
{
int ret;
u32 code, trdy;
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
index 5023f20afc14..f983f98f2176 100644
--- a/drivers/thermal/qcom/tsens-8974.c
+++ b/drivers/thermal/qcom/tsens-8974.c
@@ -91,7 +91,7 @@
#define BIT_APPEND 0x3
-static int calibrate_8974(struct tsens_device *tmdev)
+static int calibrate_8974(struct tsens_priv *tmdev)
{
int base1 = 0, base2 = 0, i;
u32 p1[11], p2[11];
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index 78652cac7f3d..128ee3621b41 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -46,7 +46,7 @@ char *qfprom_read(struct device *dev, const char *cname)
* and offset values are derived from tz->tzp->slope and tz->tzp->offset
* resp.
*/
-void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+void compute_intercept_slope(struct tsens_priv *tmdev, u32 *p1,
u32 *p2, u32 mode)
{
int i;
@@ -95,7 +95,7 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
return degc;
}
-int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
+int get_temp_common(struct tsens_priv *tmdev, int id, int *temp)
{
struct tsens_sensor *s = &tmdev->sensor[id];
u32 code;
@@ -127,7 +127,7 @@ static const struct regmap_config tsens_srot_config = {
.reg_stride = 4,
};
-int __init init_common(struct tsens_device *tmdev)
+int __init init_common(struct tsens_priv *tmdev)
{
void __iomem *tm_base, *srot_base;
struct resource *res;
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index cc98a61e093b..d812fd3f4567 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -12,7 +12,7 @@
#define LAST_TEMP_MASK 0xfff
#define STATUS_VALID_BIT BIT(21)
-static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp)
+static int get_temp_tsens_v2(struct tsens_priv *tmdev, int id, int *temp)
{
struct tsens_sensor *s = &tmdev->sensor[id];
u32 code;
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 065ec2189bd3..074fbb4d70f2 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -15,7 +15,7 @@
static int tsens_get_temp(void *data, int *temp)
{
const struct tsens_sensor *s = data;
- struct tsens_device *tmdev = s->tmdev;
+ struct tsens_priv *tmdev = s->tmdev;
return tmdev->ops->get_temp(tmdev, s->id, temp);
}
@@ -23,7 +23,7 @@ static int tsens_get_temp(void *data, int *temp)
static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
{
const struct tsens_sensor *s = p;
- struct tsens_device *tmdev = s->tmdev;
+ struct tsens_priv *tmdev = s->tmdev;
if (tmdev->ops->get_trend)
return tmdev->ops->get_trend(tmdev, s->id, trend);
@@ -33,7 +33,7 @@ static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
static int __maybe_unused tsens_suspend(struct device *dev)
{
- struct tsens_device *tmdev = dev_get_drvdata(dev);
+ struct tsens_priv *tmdev = dev_get_drvdata(dev);
if (tmdev->ops && tmdev->ops->suspend)
return tmdev->ops->suspend(tmdev);
@@ -43,7 +43,7 @@ static int __maybe_unused tsens_suspend(struct device *dev)
static int __maybe_unused tsens_resume(struct device *dev)
{
- struct tsens_device *tmdev = dev_get_drvdata(dev);
+ struct tsens_priv *tmdev = dev_get_drvdata(dev);
if (tmdev->ops && tmdev->ops->resume)
return tmdev->ops->resume(tmdev);
@@ -76,7 +76,7 @@ static const struct thermal_zone_of_device_ops tsens_of_ops = {
.get_trend = tsens_get_trend,
};
-static int tsens_register(struct tsens_device *tmdev)
+static int tsens_register(struct tsens_priv *tmdev)
{
int i;
struct thermal_zone_device *tzd;
@@ -101,7 +101,7 @@ static int tsens_probe(struct platform_device *pdev)
int ret, i;
struct device *dev;
struct device_node *np;
- struct tsens_device *tmdev;
+ struct tsens_priv *tmdev;
const struct tsens_plat_data *data;
const struct of_device_id *id;
u32 num_sensors;
@@ -174,7 +174,7 @@ static int tsens_probe(struct platform_device *pdev)
static int tsens_remove(struct platform_device *pdev)
{
- struct tsens_device *tmdev = platform_get_drvdata(pdev);
+ struct tsens_priv *tmdev = platform_get_drvdata(pdev);
if (tmdev->ops->disable)
tmdev->ops->disable(tmdev);
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 232376c690cc..936bdc7b1bc2 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -12,7 +12,7 @@
#include <linux/thermal.h>
-struct tsens_device;
+struct tsens_priv;
/**
* struct tsens_sensor - data for each sensor connected to the tsens device
@@ -25,7 +25,7 @@ struct tsens_device;
* @status: 8960-specific variable to track 8960 and 8660 status register offset
*/
struct tsens_sensor {
- struct tsens_device *tmdev;
+ struct tsens_priv *tmdev;
struct thermal_zone_device *tzd;
int offset;
int id;
@@ -47,15 +47,15 @@ struct tsens_sensor {
*/
struct tsens_ops {
/* mandatory callbacks */
- int (*init)(struct tsens_device *);
- int (*calibrate)(struct tsens_device *);
- int (*get_temp)(struct tsens_device *, int, int *);
+ int (*init)(struct tsens_priv *);
+ int (*calibrate)(struct tsens_priv *);
+ int (*get_temp)(struct tsens_priv *, int, int *);
/* optional callbacks */
- int (*enable)(struct tsens_device *, int);
- void (*disable)(struct tsens_device *);
- int (*suspend)(struct tsens_device *);
- int (*resume)(struct tsens_device *);
- int (*get_trend)(struct tsens_device *, int, enum thermal_trend *);
+ int (*enable)(struct tsens_priv *, int);
+ void (*disable)(struct tsens_priv *);
+ int (*suspend)(struct tsens_priv *);
+ int (*resume)(struct tsens_priv *);
+ int (*get_trend)(struct tsens_priv *, int, enum thermal_trend *);
};
enum reg_list {
@@ -87,7 +87,7 @@ struct tsens_context {
};
/**
- * struct tsens_device - private data for each instance of the tsens IP
+ * struct tsens_priv - private data for each instance of the tsens IP
* @dev: pointer to struct device
* @num_sensors: number of sensors enabled on this device
* @tm_map: pointer to TM register address space
@@ -99,7 +99,7 @@ struct tsens_context {
* @ops: pointer to list of callbacks supported by this device
* @sensor: list of sensors attached to this device
*/
-struct tsens_device {
+struct tsens_priv {
struct device *dev;
u32 num_sensors;
struct regmap *tm_map;
@@ -112,9 +112,9 @@ struct tsens_device {
};
char *qfprom_read(struct device *, const char *);
-void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
-int init_common(struct tsens_device *);
-int get_temp_common(struct tsens_device *, int, int *);
+void compute_intercept_slope(struct tsens_priv *, u32 *, u32 *, u32);
+int init_common(struct tsens_priv *);
+int get_temp_common(struct tsens_priv *, int, int *);
/* TSENS v1 targets */
extern const struct tsens_plat_data data_8916, data_8974, data_8960;
--
2.17.1
tmdev seems to imply that this is a device pointer when in fact it is
just private platform data for each tsens device. Rename it to priv
improve code readability.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-8916.c | 16 +++---
drivers/thermal/qcom/tsens-8960.c | 82 ++++++++++++++---------------
drivers/thermal/qcom/tsens-8974.c | 16 +++---
drivers/thermal/qcom/tsens-common.c | 52 +++++++++---------
drivers/thermal/qcom/tsens-v2.c | 12 ++---
drivers/thermal/qcom/tsens.c | 80 ++++++++++++++--------------
drivers/thermal/qcom/tsens.h | 4 +-
7 files changed, 131 insertions(+), 131 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
index 7b8f83c9a033..d4ad4082c800 100644
--- a/drivers/thermal/qcom/tsens-8916.c
+++ b/drivers/thermal/qcom/tsens-8916.c
@@ -39,23 +39,23 @@
#define CAL_SEL_MASK 0xe0000000
#define CAL_SEL_SHIFT 29
-static int calibrate_8916(struct tsens_priv *tmdev)
+static int calibrate_8916(struct tsens_priv *priv)
{
int base0 = 0, base1 = 0, i;
u32 p1[5], p2[5];
int mode = 0;
u32 *qfprom_cdata, *qfprom_csel;
- qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
+ qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
if (IS_ERR(qfprom_cdata))
return PTR_ERR(qfprom_cdata);
- qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
+ qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
if (IS_ERR(qfprom_csel))
return PTR_ERR(qfprom_csel);
mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
- dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
+ dev_dbg(priv->dev, "calibration mode is %d\n", mode);
switch (mode) {
case TWO_PT_CALIB:
@@ -65,7 +65,7 @@ static int calibrate_8916(struct tsens_priv *tmdev)
p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
- for (i = 0; i < tmdev->num_sensors; i++)
+ for (i = 0; i < priv->num_sensors; i++)
p2[i] = ((base1 + p2[i]) << 3);
/* Fall through */
case ONE_PT_CALIB2:
@@ -75,18 +75,18 @@ static int calibrate_8916(struct tsens_priv *tmdev)
p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
- for (i = 0; i < tmdev->num_sensors; i++)
+ for (i = 0; i < priv->num_sensors; i++)
p1[i] = (((base0) + p1[i]) << 3);
break;
default:
- for (i = 0; i < tmdev->num_sensors; i++) {
+ for (i = 0; i < priv->num_sensors; i++) {
p1[i] = 500;
p2[i] = 780;
}
break;
}
- compute_intercept_slope(tmdev, p1, p2, mode);
+ compute_intercept_slope(priv, p1, p2, mode);
return 0;
}
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
index 7e340eea48da..8d9b721dadb6 100644
--- a/drivers/thermal/qcom/tsens-8960.c
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -56,21 +56,21 @@
#define TRDY_MASK BIT(7)
#define TIMEOUT_US 100
-static int suspend_8960(struct tsens_priv *tmdev)
+static int suspend_8960(struct tsens_priv *priv)
{
int ret;
unsigned int mask;
- struct regmap *map = tmdev->tm_map;
+ struct regmap *map = priv->tm_map;
- ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
+ ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
if (ret)
return ret;
- ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
+ ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
if (ret)
return ret;
- if (tmdev->num_sensors > 1)
+ if (priv->num_sensors > 1)
mask = SLP_CLK_ENA | EN;
else
mask = SLP_CLK_ENA_8660 | EN;
@@ -82,10 +82,10 @@ static int suspend_8960(struct tsens_priv *tmdev)
return 0;
}
-static int resume_8960(struct tsens_priv *tmdev)
+static int resume_8960(struct tsens_priv *priv)
{
int ret;
- struct regmap *map = tmdev->tm_map;
+ struct regmap *map = priv->tm_map;
ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
if (ret)
@@ -95,80 +95,80 @@ static int resume_8960(struct tsens_priv *tmdev)
* Separate CONFIG restore is not needed only for 8660 as
* config is part of CTRL Addr and its restored as such
*/
- if (tmdev->num_sensors > 1) {
+ if (priv->num_sensors > 1) {
ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
if (ret)
return ret;
}
- ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
+ ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
if (ret)
return ret;
- ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
+ ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
if (ret)
return ret;
return 0;
}
-static int enable_8960(struct tsens_priv *tmdev, int id)
+static int enable_8960(struct tsens_priv *priv, int id)
{
int ret;
u32 reg, mask;
- ret = regmap_read(tmdev->tm_map, CNTL_ADDR, ®);
+ ret = regmap_read(priv->tm_map, CNTL_ADDR, ®);
if (ret)
return ret;
mask = BIT(id + SENSOR0_SHIFT);
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg | SW_RST);
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
if (ret)
return ret;
- if (tmdev->num_sensors > 1)
+ if (priv->num_sensors > 1)
reg |= mask | SLP_CLK_ENA | EN;
else
reg |= mask | SLP_CLK_ENA_8660 | EN;
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg);
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
if (ret)
return ret;
return 0;
}
-static void disable_8960(struct tsens_priv *tmdev)
+static void disable_8960(struct tsens_priv *priv)
{
int ret;
u32 reg_cntl;
u32 mask;
- mask = GENMASK(tmdev->num_sensors - 1, 0);
+ mask = GENMASK(priv->num_sensors - 1, 0);
mask <<= SENSOR0_SHIFT;
mask |= EN;
- ret = regmap_read(tmdev->tm_map, CNTL_ADDR, ®_cntl);
+ ret = regmap_read(priv->tm_map, CNTL_ADDR, ®_cntl);
if (ret)
return;
reg_cntl &= ~mask;
- if (tmdev->num_sensors > 1)
+ if (priv->num_sensors > 1)
reg_cntl &= ~SLP_CLK_ENA;
else
reg_cntl &= ~SLP_CLK_ENA_8660;
- regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+ regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
}
-static int init_8960(struct tsens_priv *tmdev)
+static int init_8960(struct tsens_priv *priv)
{
int ret, i;
u32 reg_cntl;
- tmdev->tm_map = dev_get_regmap(tmdev->dev, NULL);
- if (!tmdev->tm_map)
+ priv->tm_map = dev_get_regmap(priv->dev, NULL);
+ if (!priv->tm_map)
return -ENODEV;
/*
@@ -177,21 +177,21 @@ static int init_8960(struct tsens_priv *tmdev)
* but the control registers stay in the same place, i.e
* directly after the first 5 status registers.
*/
- for (i = 0; i < tmdev->num_sensors; i++) {
+ for (i = 0; i < priv->num_sensors; i++) {
if (i >= 5)
- tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
- tmdev->sensor[i].status += i * 4;
+ priv->sensor[i].status = S0_STATUS_ADDR + 40;
+ priv->sensor[i].status += i * 4;
}
reg_cntl = SW_RST;
- ret = regmap_update_bits(tmdev->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
+ ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
if (ret)
return ret;
- if (tmdev->num_sensors > 1) {
+ if (priv->num_sensors > 1) {
reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
reg_cntl &= ~SW_RST;
- ret = regmap_update_bits(tmdev->tm_map, CONFIG_ADDR,
+ ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR,
CONFIG_MASK, CONFIG);
} else {
reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
@@ -199,30 +199,30 @@ static int init_8960(struct tsens_priv *tmdev)
reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
}
- reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+ reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT;
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
if (ret)
return ret;
reg_cntl |= EN;
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
if (ret)
return ret;
return 0;
}
-static int calibrate_8960(struct tsens_priv *tmdev)
+static int calibrate_8960(struct tsens_priv *priv)
{
int i;
char *data;
- ssize_t num_read = tmdev->num_sensors;
- struct tsens_sensor *s = tmdev->sensor;
+ ssize_t num_read = priv->num_sensors;
+ struct tsens_sensor *s = priv->sensor;
- data = qfprom_read(tmdev->dev, "calib");
+ data = qfprom_read(priv->dev, "calib");
if (IS_ERR(data))
- data = qfprom_read(tmdev->dev, "calib_backup");
+ data = qfprom_read(priv->dev, "calib_backup");
if (IS_ERR(data))
return PTR_ERR(data);
@@ -243,21 +243,21 @@ static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
return adc_code * slope + offset;
}
-static int get_temp_8960(struct tsens_priv *tmdev, int id, int *temp)
+static int get_temp_8960(struct tsens_priv *priv, int id, int *temp)
{
int ret;
u32 code, trdy;
- const struct tsens_sensor *s = &tmdev->sensor[id];
+ const struct tsens_sensor *s = &priv->sensor[id];
unsigned long timeout;
timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
do {
- ret = regmap_read(tmdev->tm_map, INT_STATUS_ADDR, &trdy);
+ ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy);
if (ret)
return ret;
if (!(trdy & TRDY_MASK))
continue;
- ret = regmap_read(tmdev->tm_map, s->status, &code);
+ ret = regmap_read(priv->tm_map, s->status, &code);
if (ret)
return ret;
*temp = code_to_mdegC(code, s);
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
index f983f98f2176..303157fd00be 100644
--- a/drivers/thermal/qcom/tsens-8974.c
+++ b/drivers/thermal/qcom/tsens-8974.c
@@ -91,7 +91,7 @@
#define BIT_APPEND 0x3
-static int calibrate_8974(struct tsens_priv *tmdev)
+static int calibrate_8974(struct tsens_priv *priv)
{
int base1 = 0, base2 = 0, i;
u32 p1[11], p2[11];
@@ -99,11 +99,11 @@ static int calibrate_8974(struct tsens_priv *tmdev)
u32 *calib, *bkp;
u32 calib_redun_sel;
- calib = (u32 *)qfprom_read(tmdev->dev, "calib");
+ calib = (u32 *)qfprom_read(priv->dev, "calib");
if (IS_ERR(calib))
return PTR_ERR(calib);
- bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
+ bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
if (IS_ERR(bkp))
return PTR_ERR(bkp);
@@ -184,25 +184,25 @@ static int calibrate_8974(struct tsens_priv *tmdev)
switch (mode) {
case ONE_PT_CALIB:
- for (i = 0; i < tmdev->num_sensors; i++)
+ for (i = 0; i < priv->num_sensors; i++)
p1[i] += (base1 << 2) | BIT_APPEND;
break;
case TWO_PT_CALIB:
- for (i = 0; i < tmdev->num_sensors; i++) {
+ for (i = 0; i < priv->num_sensors; i++) {
p2[i] += base2;
p2[i] <<= 2;
p2[i] |= BIT_APPEND;
}
/* Fall through */
case ONE_PT_CALIB2:
- for (i = 0; i < tmdev->num_sensors; i++) {
+ for (i = 0; i < priv->num_sensors; i++) {
p1[i] += base1;
p1[i] <<= 2;
p1[i] |= BIT_APPEND;
}
break;
default:
- for (i = 0; i < tmdev->num_sensors; i++)
+ for (i = 0; i < priv->num_sensors; i++)
p2[i] = 780;
p1[0] = 502;
p1[1] = 509;
@@ -218,7 +218,7 @@ static int calibrate_8974(struct tsens_priv *tmdev)
break;
}
- compute_intercept_slope(tmdev, p1, p2, mode);
+ compute_intercept_slope(priv, p1, p2, mode);
return 0;
}
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index 128ee3621b41..af87216ee407 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -46,18 +46,18 @@ char *qfprom_read(struct device *dev, const char *cname)
* and offset values are derived from tz->tzp->slope and tz->tzp->offset
* resp.
*/
-void compute_intercept_slope(struct tsens_priv *tmdev, u32 *p1,
+void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
u32 *p2, u32 mode)
{
int i;
int num, den;
- for (i = 0; i < tmdev->num_sensors; i++) {
- dev_dbg(tmdev->dev,
+ for (i = 0; i < priv->num_sensors; i++) {
+ dev_dbg(priv->dev,
"sensor%d - data_point1:%#x data_point2:%#x\n",
i, p1[i], p2[i]);
- tmdev->sensor[i].slope = SLOPE_DEFAULT;
+ priv->sensor[i].slope = SLOPE_DEFAULT;
if (mode == TWO_PT_CALIB) {
/*
* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
@@ -66,13 +66,13 @@ void compute_intercept_slope(struct tsens_priv *tmdev, u32 *p1,
num = p2[i] - p1[i];
num *= SLOPE_FACTOR;
den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
- tmdev->sensor[i].slope = num / den;
+ priv->sensor[i].slope = num / den;
}
- tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
+ priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
(CAL_DEGC_PT1 *
- tmdev->sensor[i].slope);
- dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
+ priv->sensor[i].slope);
+ dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset);
}
}
@@ -95,15 +95,15 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
return degc;
}
-int get_temp_common(struct tsens_priv *tmdev, int id, int *temp)
+int get_temp_common(struct tsens_priv *priv, int id, int *temp)
{
- struct tsens_sensor *s = &tmdev->sensor[id];
+ struct tsens_sensor *s = &priv->sensor[id];
u32 code;
unsigned int status_reg;
int last_temp = 0, ret;
- status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET;
- ret = regmap_read(tmdev->tm_map, status_reg, &code);
+ status_reg = priv->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET;
+ ret = regmap_read(priv->tm_map, status_reg, &code);
if (ret)
return ret;
last_temp = code & SN_ST_TEMP_MASK;
@@ -127,34 +127,34 @@ static const struct regmap_config tsens_srot_config = {
.reg_stride = 4,
};
-int __init init_common(struct tsens_priv *tmdev)
+int __init init_common(struct tsens_priv *priv)
{
void __iomem *tm_base, *srot_base;
struct resource *res;
u32 code;
int ret;
- struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node);
- u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET];
+ struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
+ u16 ctrl_offset = priv->reg_offsets[SROT_CTRL_OFFSET];
if (!op)
return -EINVAL;
if (op->num_resources > 1) {
/* DT with separate SROT and TM address space */
- tmdev->tm_offset = 0;
+ priv->tm_offset = 0;
res = platform_get_resource(op, IORESOURCE_MEM, 1);
srot_base = devm_ioremap_resource(&op->dev, res);
if (IS_ERR(srot_base))
return PTR_ERR(srot_base);
- tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base,
+ priv->srot_map = devm_regmap_init_mmio(priv->dev, srot_base,
&tsens_srot_config);
- if (IS_ERR(tmdev->srot_map))
- return PTR_ERR(tmdev->srot_map);
+ if (IS_ERR(priv->srot_map))
+ return PTR_ERR(priv->srot_map);
} else {
/* old DTs where SROT and TM were in a contiguous 2K block */
- tmdev->tm_offset = 0x1000;
+ priv->tm_offset = 0x1000;
}
res = platform_get_resource(op, IORESOURCE_MEM, 0);
@@ -162,16 +162,16 @@ int __init init_common(struct tsens_priv *tmdev)
if (IS_ERR(tm_base))
return PTR_ERR(tm_base);
- tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config);
- if (IS_ERR(tmdev->tm_map))
- return PTR_ERR(tmdev->tm_map);
+ priv->tm_map = devm_regmap_init_mmio(priv->dev, tm_base, &tsens_config);
+ if (IS_ERR(priv->tm_map))
+ return PTR_ERR(priv->tm_map);
- if (tmdev->srot_map) {
- ret = regmap_read(tmdev->srot_map, ctrl_offset, &code);
+ if (priv->srot_map) {
+ ret = regmap_read(priv->srot_map, ctrl_offset, &code);
if (ret)
return ret;
if (!(code & TSENS_EN)) {
- dev_err(tmdev->dev, "tsens device is not enabled\n");
+ dev_err(priv->dev, "tsens device is not enabled\n");
return -ENODEV;
}
}
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index d812fd3f4567..8b700772d903 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -12,16 +12,16 @@
#define LAST_TEMP_MASK 0xfff
#define STATUS_VALID_BIT BIT(21)
-static int get_temp_tsens_v2(struct tsens_priv *tmdev, int id, int *temp)
+static int get_temp_tsens_v2(struct tsens_priv *priv, int id, int *temp)
{
- struct tsens_sensor *s = &tmdev->sensor[id];
+ struct tsens_sensor *s = &priv->sensor[id];
u32 code;
unsigned int status_reg;
u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0;
int ret;
- status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4;
- ret = regmap_read(tmdev->tm_map, status_reg, &code);
+ status_reg = priv->tm_offset + STATUS_OFFSET + s->hw_id * 4;
+ ret = regmap_read(priv->tm_map, status_reg, &code);
if (ret)
return ret;
last_temp = code & LAST_TEMP_MASK;
@@ -29,7 +29,7 @@ static int get_temp_tsens_v2(struct tsens_priv *tmdev, int id, int *temp)
goto done;
/* Try a second time */
- ret = regmap_read(tmdev->tm_map, status_reg, &code);
+ ret = regmap_read(priv->tm_map, status_reg, &code);
if (ret)
return ret;
if (code & STATUS_VALID_BIT) {
@@ -40,7 +40,7 @@ static int get_temp_tsens_v2(struct tsens_priv *tmdev, int id, int *temp)
}
/* Try a third/last time */
- ret = regmap_read(tmdev->tm_map, status_reg, &code);
+ ret = regmap_read(priv->tm_map, status_reg, &code);
if (ret)
return ret;
if (code & STATUS_VALID_BIT) {
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 074fbb4d70f2..4582d2b30e94 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -15,38 +15,38 @@
static int tsens_get_temp(void *data, int *temp)
{
const struct tsens_sensor *s = data;
- struct tsens_priv *tmdev = s->tmdev;
+ struct tsens_priv *priv = s->priv;
- return tmdev->ops->get_temp(tmdev, s->id, temp);
+ return priv->ops->get_temp(priv, s->id, temp);
}
static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
{
const struct tsens_sensor *s = p;
- struct tsens_priv *tmdev = s->tmdev;
+ struct tsens_priv *priv = s->priv;
- if (tmdev->ops->get_trend)
- return tmdev->ops->get_trend(tmdev, s->id, trend);
+ if (priv->ops->get_trend)
+ return priv->ops->get_trend(priv, s->id, trend);
return -ENOTSUPP;
}
static int __maybe_unused tsens_suspend(struct device *dev)
{
- struct tsens_priv *tmdev = dev_get_drvdata(dev);
+ struct tsens_priv *priv = dev_get_drvdata(dev);
- if (tmdev->ops && tmdev->ops->suspend)
- return tmdev->ops->suspend(tmdev);
+ if (priv->ops && priv->ops->suspend)
+ return priv->ops->suspend(priv);
return 0;
}
static int __maybe_unused tsens_resume(struct device *dev)
{
- struct tsens_priv *tmdev = dev_get_drvdata(dev);
+ struct tsens_priv *priv = dev_get_drvdata(dev);
- if (tmdev->ops && tmdev->ops->resume)
- return tmdev->ops->resume(tmdev);
+ if (priv->ops && priv->ops->resume)
+ return priv->ops->resume(priv);
return 0;
}
@@ -76,22 +76,22 @@ static const struct thermal_zone_of_device_ops tsens_of_ops = {
.get_trend = tsens_get_trend,
};
-static int tsens_register(struct tsens_priv *tmdev)
+static int tsens_register(struct tsens_priv *priv)
{
int i;
struct thermal_zone_device *tzd;
- for (i = 0; i < tmdev->num_sensors; i++) {
- tmdev->sensor[i].tmdev = tmdev;
- tmdev->sensor[i].id = i;
- tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i,
- &tmdev->sensor[i],
+ for (i = 0; i < priv->num_sensors; i++) {
+ priv->sensor[i].priv = priv;
+ priv->sensor[i].id = i;
+ tzd = devm_thermal_zone_of_sensor_register(priv->dev, i,
+ &priv->sensor[i],
&tsens_of_ops);
if (IS_ERR(tzd))
continue;
- tmdev->sensor[i].tzd = tzd;
- if (tmdev->ops->enable)
- tmdev->ops->enable(tmdev, i);
+ priv->sensor[i].tzd = tzd;
+ if (priv->ops->enable)
+ priv->ops->enable(priv, i);
}
return 0;
}
@@ -101,7 +101,7 @@ static int tsens_probe(struct platform_device *pdev)
int ret, i;
struct device *dev;
struct device_node *np;
- struct tsens_priv *tmdev;
+ struct tsens_priv *priv;
const struct tsens_plat_data *data;
const struct of_device_id *id;
u32 num_sensors;
@@ -129,55 +129,55 @@ static int tsens_probe(struct platform_device *pdev)
return -EINVAL;
}
- tmdev = devm_kzalloc(dev,
- struct_size(tmdev, sensor, num_sensors),
+ priv = devm_kzalloc(dev,
+ struct_size(priv, sensor, num_sensors),
GFP_KERNEL);
- if (!tmdev)
+ if (!priv)
return -ENOMEM;
- tmdev->dev = dev;
- tmdev->num_sensors = num_sensors;
- tmdev->ops = data->ops;
- for (i = 0; i < tmdev->num_sensors; i++) {
+ priv->dev = dev;
+ priv->num_sensors = num_sensors;
+ priv->ops = data->ops;
+ for (i = 0; i < priv->num_sensors; i++) {
if (data->hw_ids)
- tmdev->sensor[i].hw_id = data->hw_ids[i];
+ priv->sensor[i].hw_id = data->hw_ids[i];
else
- tmdev->sensor[i].hw_id = i;
+ priv->sensor[i].hw_id = i;
}
for (i = 0; i < REG_ARRAY_SIZE; i++) {
- tmdev->reg_offsets[i] = data->reg_offsets[i];
+ priv->reg_offsets[i] = data->reg_offsets[i];
}
- if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
+ if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
return -EINVAL;
- ret = tmdev->ops->init(tmdev);
+ ret = priv->ops->init(priv);
if (ret < 0) {
dev_err(dev, "tsens init failed\n");
return ret;
}
- if (tmdev->ops->calibrate) {
- ret = tmdev->ops->calibrate(tmdev);
+ if (priv->ops->calibrate) {
+ ret = priv->ops->calibrate(priv);
if (ret < 0) {
dev_err(dev, "tsens calibration failed\n");
return ret;
}
}
- ret = tsens_register(tmdev);
+ ret = tsens_register(priv);
- platform_set_drvdata(pdev, tmdev);
+ platform_set_drvdata(pdev, priv);
return ret;
}
static int tsens_remove(struct platform_device *pdev)
{
- struct tsens_priv *tmdev = platform_get_drvdata(pdev);
+ struct tsens_priv *priv = platform_get_drvdata(pdev);
- if (tmdev->ops->disable)
- tmdev->ops->disable(tmdev);
+ if (priv->ops->disable)
+ priv->ops->disable(priv);
return 0;
}
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 936bdc7b1bc2..61ca2905ee7a 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -16,7 +16,7 @@ struct tsens_priv;
/**
* struct tsens_sensor - data for each sensor connected to the tsens device
- * @tmdev: tsens device instance that this sensor is connected to
+ * @priv: tsens device instance that this sensor is connected to
* @tzd: pointer to the thermal zone that this sensor is in
* @offset: offset of temperature adjustment curve
* @id: Sensor ID
@@ -25,7 +25,7 @@ struct tsens_priv;
* @status: 8960-specific variable to track 8960 and 8660 status register offset
*/
struct tsens_sensor {
- struct tsens_priv *tmdev;
+ struct tsens_priv *priv;
struct thermal_zone_device *tzd;
int offset;
int id;
--
2.17.1
is_sensor_enabled() checks if the sensors are enabled on this platform.
It is possible that the SoC might choose not to enable all the sensors
that the IP block is capable of supporting.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 14 ++++++++++++++
drivers/thermal/qcom/tsens-v0_1.c | 1 +
drivers/thermal/qcom/tsens-v2.c | 1 +
drivers/thermal/qcom/tsens.c | 5 +++++
drivers/thermal/qcom/tsens.h | 1 +
5 files changed, 22 insertions(+)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index 39cd5733fd44..020409d8daf0 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -69,6 +69,20 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
}
}
+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id)
+{
+ u32 val;
+ int ret;
+
+ if ((hw_id > (priv->num_sensors - 1)) || (hw_id < 0))
+ return -EINVAL;
+ ret = regmap_field_read(priv->rf[SENSOR_EN], &val);
+ if (ret)
+ return ret;
+
+ return val & (1 << hw_id);
+}
+
static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
{
int degc, num, den;
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index 02907751c201..ad1052e05e45 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -332,6 +332,7 @@ const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = {
/* CTRL_OFFSET */
[TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
[TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
/* ----- TM ------ */
/* UPPER_LOWER_INTERRUPT_CTRL */
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 962e47c54dca..e0aac59d72ec 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -99,6 +99,7 @@ const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
/* CTRL_OFF */
[TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
[TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 18),
/* ----- TM ------ */
/* INTERRUPT ENABLE */
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 057b33353ba3..fc44cac31fa5 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -82,6 +82,11 @@ static int tsens_register(struct tsens_priv *priv)
struct thermal_zone_device *tzd;
for (i = 0; i < priv->num_sensors; i++) {
+ if (!is_sensor_enabled(priv, priv->sensor[i].hw_id)) {
+ dev_err(priv->dev, "sensor %d: disabled\n",
+ priv->sensor[i].hw_id);
+ continue;
+ }
priv->sensor[i].priv = priv;
priv->sensor[i].id = i;
tzd = devm_thermal_zone_of_sensor_register(priv->dev, i,
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 20d89f8a6c3e..da4cfb23dfe9 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -254,6 +254,7 @@ char *qfprom_read(struct device *dev, const char *cname);
void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
int init_common(struct tsens_priv *priv);
int get_temp_common(struct tsens_priv *priv, int i, int *temp);
+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id);
/* TSENS target */
extern const struct tsens_plat_data data_8960;
--
2.17.1
The IDs cannot be negative, fix the data type.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index da4cfb23dfe9..e0c1ca1a7467 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -29,8 +29,8 @@ struct tsens_sensor {
struct tsens_priv *priv;
struct thermal_zone_device *tzd;
int offset;
- int id;
- int hw_id;
+ unsigned int id;
+ unsigned int hw_id;
int slope;
u32 status;
};
--
2.17.1
The IP can support 'm' sensors while the platform can enable 'n' sensors
of the 'm' where n <= m.
Track maximum sensors supported by the IP so that we can correctly track
what subset of the sensors are supported on the platform.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 4 ++--
drivers/thermal/qcom/tsens-v0_1.c | 1 +
drivers/thermal/qcom/tsens-v2.c | 1 +
drivers/thermal/qcom/tsens.h | 2 ++
4 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index 020409d8daf0..d981effed493 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -208,13 +208,13 @@ int __init init_common(struct tsens_priv *priv)
return PTR_ERR(priv->rf[SENSOR_EN]);
/* now alloc regmap_fields in tm_map */
- for (i = 0, j = LAST_TEMP_0; i < priv->num_sensors; i++, j++) {
+ for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) {
priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
priv->fields[j]);
if (IS_ERR(priv->rf[j]))
return PTR_ERR(priv->rf[j]);
}
- for (i = 0, j = VALID_0; i < priv->num_sensors; i++, j++) {
+ for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) {
priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
priv->fields[j]);
if (IS_ERR(priv->rf[j]))
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index ad1052e05e45..4f17b4b781b0 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -324,6 +324,7 @@ const struct tsens_features tsens_v0_1_feat = {
.crit_int = 0,
.adc = 1,
.srot_split = 1,
+ .max_sensors = 11,
};
/* v0.1: 8916, 8974 */
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index e0aac59d72ec..8052266447f5 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -88,6 +88,7 @@ const struct tsens_features tsens_v2_feat = {
.crit_int = 1,
.adc = 0,
.srot_split = 1,
+ .max_sensors = 16,
};
const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index e0c1ca1a7467..9db89dffb719 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -189,12 +189,14 @@ enum regfield_ids {
* @adc: do the sensors only output adc code (instead of temperature)?
* @srot_split: does the IP neatly splits the register space into SROT and TM,
* with SROT only being available to secure boot firmware?
+ * @max_sensors: maximum sensors supported by this version of the IP
*/
struct tsens_features {
unsigned int ver_info:1;
unsigned int crit_int:1;
unsigned int adc:1;
unsigned int srot_split:1;
+ unsigned int max_sensors;
};
/**
--
2.17.1
The current implementation is based on an algorithm published in the
docs. Instead of reading the temperature thrice w/o any explanation,
improve the algorithm.
This will become the basis for a common get_temp routine in the future.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-v2.c | 55 ++++++++++-----------------------
1 file changed, 17 insertions(+), 38 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 8052266447f5..0ea93b89bc65 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -25,58 +25,37 @@
#define TM_Sn_STATUS_OFF 0x00a0
#define TM_TRDY_OFF 0x00e4
-#define LAST_TEMP_MASK 0xfff
-
-static int get_temp_tsens_v2(struct tsens_priv *priv, int id, int *temp)
+static int get_temp_tsens_v2(struct tsens_priv *priv, int i, int *temp)
{
- struct tsens_sensor *s = &priv->sensor[id];
+ struct tsens_sensor *s = &priv->sensor[i];
u32 temp_idx = LAST_TEMP_0 + s->hw_id;
u32 valid_idx = VALID_0 + s->hw_id;
- u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0, valid;
+ u32 last_temp = 0, valid, mask;
int ret;
- ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
- if (ret)
- return ret;
-
ret = regmap_field_read(priv->rf[valid_idx], &valid);
if (ret)
return ret;
-
- if (valid)
- goto done;
-
- /* Try a second time */
- ret = regmap_field_read(priv->rf[valid_idx], &valid);
- if (ret)
- return ret;
- ret = regmap_field_read(priv->rf[temp_idx], &last_temp2);
- if (ret)
- return ret;
- if (valid) {
- last_temp = last_temp2;
- goto done;
+ while (!valid) {
+ /* Valid bit is 0 for 6 AHB clock cycles.
+ * At 19.2MHz, 1 AHB clock is ~60ns.
+ * We should enter this loop very, very rarely.
+ */
+ ndelay(400);
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
+ if (ret)
+ return ret;
}
- /* Try a third/last time */
- ret = regmap_field_read(priv->rf[valid_idx], &valid);
- if (ret)
- return ret;
- ret = regmap_field_read(priv->rf[temp_idx], &last_temp3);
+ /* Valid bit is set, OK to read the temperature */
+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
if (ret)
return ret;
- if (valid) {
- last_temp = last_temp3;
- goto done;
- }
- if (last_temp == last_temp2)
- last_temp = last_temp2;
- else if (last_temp2 == last_temp3)
- last_temp = last_temp3;
-done:
+ mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
+ priv->fields[LAST_TEMP_0].lsb);
/* Convert temperature from deciCelsius to milliCelsius */
- *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100;
+ *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
return 0;
}
--
2.17.1
Just rename the function and move it to allow code sharing with future
versions of TSENS IP
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 35 +++++++++++++++++++++++++++
drivers/thermal/qcom/tsens-v2.c | 37 +----------------------------
drivers/thermal/qcom/tsens.h | 1 +
3 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index d981effed493..ed975a2430d9 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -102,6 +102,41 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
return degc;
}
+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp)
+{
+ struct tsens_sensor *s = &priv->sensor[i];
+ u32 temp_idx = LAST_TEMP_0 + s->hw_id;
+ u32 valid_idx = VALID_0 + s->hw_id;
+ u32 last_temp = 0, valid, mask;
+ int ret;
+
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
+ if (ret)
+ return ret;
+ while (!valid) {
+ /* Valid bit is 0 for 6 AHB clock cycles.
+ * At 19.2MHz, 1 AHB clock is ~60ns.
+ * We should enter this loop very, very rarely.
+ */
+ ndelay(400);
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
+ if (ret)
+ return ret;
+ }
+
+ /* Valid bit is set, OK to read the temperature */
+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
+ if (ret)
+ return ret;
+
+ mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
+ priv->fields[LAST_TEMP_0].lsb);
+ /* Convert temperature from deciCelsius to milliCelsius */
+ *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
+
+ return 0;
+}
+
int get_temp_common(struct tsens_priv *priv, int i, int *temp)
{
struct tsens_sensor *s = &priv->sensor[i];
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 0ea93b89bc65..d436b96a6f18 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -25,41 +25,6 @@
#define TM_Sn_STATUS_OFF 0x00a0
#define TM_TRDY_OFF 0x00e4
-static int get_temp_tsens_v2(struct tsens_priv *priv, int i, int *temp)
-{
- struct tsens_sensor *s = &priv->sensor[i];
- u32 temp_idx = LAST_TEMP_0 + s->hw_id;
- u32 valid_idx = VALID_0 + s->hw_id;
- u32 last_temp = 0, valid, mask;
- int ret;
-
- ret = regmap_field_read(priv->rf[valid_idx], &valid);
- if (ret)
- return ret;
- while (!valid) {
- /* Valid bit is 0 for 6 AHB clock cycles.
- * At 19.2MHz, 1 AHB clock is ~60ns.
- * We should enter this loop very, very rarely.
- */
- ndelay(400);
- ret = regmap_field_read(priv->rf[valid_idx], &valid);
- if (ret)
- return ret;
- }
-
- /* Valid bit is set, OK to read the temperature */
- ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
- if (ret)
- return ret;
-
- mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
- priv->fields[LAST_TEMP_0].lsb);
- /* Convert temperature from deciCelsius to milliCelsius */
- *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
-
- return 0;
-}
-
/* v2.x: 8996, 8998, sdm845 */
const struct tsens_features tsens_v2_feat = {
@@ -136,7 +101,7 @@ const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
static const struct tsens_ops ops_generic_v2 = {
.init = init_common,
- .get_temp = get_temp_tsens_v2,
+ .get_temp = get_temp_tsens_valid,
};
const struct tsens_plat_data data_tsens_v2 = {
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 9db89dffb719..4b3d71b26c97 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -255,6 +255,7 @@ struct tsens_priv {
char *qfprom_read(struct device *dev, const char *cname);
void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
int init_common(struct tsens_priv *priv);
+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp);
int get_temp_common(struct tsens_priv *priv, int i, int *temp);
bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id);
--
2.17.1
get_temp() learns to return temperature regardless of whether it is
returned as ADC code or direct temperature.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index ed975a2430d9..a935d2335eea 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -129,10 +129,15 @@ int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp)
if (ret)
return ret;
- mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
- priv->fields[LAST_TEMP_0].lsb);
- /* Convert temperature from deciCelsius to milliCelsius */
- *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
+ if (priv->feat->adc) {
+ /* Convert temperature from ADC code to milliCelsius */
+ *temp = code_to_degc(last_temp, s) * 1000;
+ } else {
+ mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
+ priv->fields[LAST_TEMP_0].lsb);
+ /* Convert temperature from deciCelsius to milliCelsius */
+ *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
+ }
return 0;
}
--
2.17.1
qcs404 has 10 sensors connected to the single TSENS IP. Define a thermal
zone for each of those sensors to expose the temperature of each zone.
Signed-off-by: Amit Kucheria <[email protected]>
---
arch/arm64/boot/dts/qcom/qcs404.dtsi | 243 +++++++++++++++++++++++++++
1 file changed, 243 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
index 57d14d8f0c90..ca99c45864df 100644
--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -3,6 +3,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-qcs404.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
interrupt-parent = <&intc>;
@@ -30,6 +31,7 @@
reg = <0x100>;
enable-method = "psci";
next-level-cache = <&L2_0>;
+ #cooling-cells= <2>;
};
CPU1: cpu@101 {
@@ -38,6 +40,7 @@
reg = <0x101>;
enable-method = "psci";
next-level-cache = <&L2_0>;
+ #cooling-cells= <2>;
};
CPU2: cpu@102 {
@@ -46,6 +49,7 @@
reg = <0x102>;
enable-method = "psci";
next-level-cache = <&L2_0>;
+ #cooling-cells= <2>;
};
CPU3: cpu@103 {
@@ -54,6 +58,7 @@
reg = <0x103>;
enable-method = "psci";
next-level-cache = <&L2_0>;
+ #cooling-cells= <2>;
};
L2_0: l2-cache {
@@ -507,4 +512,242 @@
#interrupt-cells = <2>;
};
};
+
+ thermal-zones {
+ aoss-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 0>;
+
+ trips {
+ aoss_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ aoss_crit: aoss_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ dsp-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 1>;
+
+ trips {
+ dsp_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ dsp_crit: dsp_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ lpass-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 2>;
+
+ trips {
+ lpass_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ lpass_crit: lpass_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ wlan-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 3>;
+
+ trips {
+ wlan_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ wlan_crit: wlan_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cluster-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 4>;
+
+ trips {
+ cluster_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cluster_crit: cluster_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 5>;
+
+ trips {
+ cpu0_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu0_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&cpu0_alert0>;
+ cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ cpu1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 6>;
+
+ trips {
+ cpu1_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu1_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&cpu1_alert0>;
+ cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ cpu2-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 7>;
+
+ trips {
+ cpu2_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu2_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&cpu2_alert0>;
+ cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ cpu3-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 8>;
+
+ trips {
+ cpu3_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu3_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&cpu3_alert0>;
+ cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ gpu-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 9>;
+
+ trips {
+ gpu_alert0: trip-point@0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ gpu_crit: gpu_crit {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
};
--
2.17.1
qcs404 uses v1 of the TSENS IP block. Create a fallback DT property
"qcom,tsens-v1" to gather common code
Signed-off-by: Amit Kucheria <[email protected]>
---
.../devicetree/bindings/thermal/qcom-tsens.txt | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
index 1d9e8cf61018..673cc1831ee9 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -6,11 +6,14 @@ Required properties:
- "qcom,msm8916-tsens" (MSM8916)
- "qcom,msm8974-tsens" (MSM8974)
- "qcom,msm8996-tsens" (MSM8996)
+ - "qcom,qcs404-tsens", "qcom,tsens-v1" (QCS404)
- "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998)
- "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845)
The generic "qcom,tsens-v2" property must be used as a fallback for any SoC
with version 2 of the TSENS IP. MSM8996 is the only exception because the
generic property did not exist when support was added.
+ Similarly, the generic "qcom,tsens-v1" property must be used as a fallback for
+ any SoC with version 1 of the TSENS IP.
- reg: Address range of the thermal registers.
New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM
@@ -39,3 +42,14 @@ tsens0: thermal-sensor@c263000 {
#qcom,sensors = <13>;
#thermal-sensor-cells = <1>;
};
+
+Example 3 (for any platform containing v1 of the TSENS IP):
+tsens: thermal-sensor@4a9000 {
+ compatible = "qcom,qcs404-tsens", "qcom,tsens-v1";
+ reg = <0x004a9000 0x1000>, /* TM */
+ <0x004a8000 0x1000>; /* SROT */
+ nvmem-cells = <&tsens_caldata>;
+ nvmem-cell-names = "calib";
+ #qcom,sensors = <10>;
+ #thermal-sensor-cells = <1>;
+ };
--
2.17.1
This will allow calibration routines to correctly include the constants
from anywhere and allow more code sharing.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 5 -----
drivers/thermal/qcom/tsens.h | 5 +++++
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index a935d2335eea..35e82aaaef59 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -12,11 +12,6 @@
#include <linux/regmap.h>
#include "tsens.h"
-#define CAL_DEGC_PT1 30
-#define CAL_DEGC_PT2 120
-#define SLOPE_FACTOR 1000
-#define SLOPE_DEFAULT 3200
-
char *qfprom_read(struct device *dev, const char *cname)
{
struct nvmem_cell *cell;
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 4ed07e607cbc..8a747ab892f5 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -9,6 +9,11 @@
#define ONE_PT_CALIB 0x1
#define ONE_PT_CALIB2 0x2
#define TWO_PT_CALIB 0x3
+#define CAL_DEGC_PT1 30
+#define CAL_DEGC_PT2 120
+#define SLOPE_FACTOR 1000
+#define SLOPE_DEFAULT 3200
+
#include <linux/thermal.h>
#include <linux/regmap.h>
--
2.17.1
check_patch complains a lot as follows:
WARNING: function definition argument 'struct tsens_priv *' should also have an identifier name
+ int (*init)(struct tsens_priv *);
Fix it.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens.h | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 61ca2905ee7a..4d6a406f8dca 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -47,15 +47,15 @@ struct tsens_sensor {
*/
struct tsens_ops {
/* mandatory callbacks */
- int (*init)(struct tsens_priv *);
- int (*calibrate)(struct tsens_priv *);
- int (*get_temp)(struct tsens_priv *, int, int *);
+ int (*init)(struct tsens_priv *priv);
+ int (*calibrate)(struct tsens_priv *priv);
+ int (*get_temp)(struct tsens_priv *priv, int i, int *temp);
/* optional callbacks */
- int (*enable)(struct tsens_priv *, int);
- void (*disable)(struct tsens_priv *);
- int (*suspend)(struct tsens_priv *);
- int (*resume)(struct tsens_priv *);
- int (*get_trend)(struct tsens_priv *, int, enum thermal_trend *);
+ int (*enable)(struct tsens_priv *priv, int i);
+ void (*disable)(struct tsens_priv *priv);
+ int (*suspend)(struct tsens_priv *priv);
+ int (*resume)(struct tsens_priv *priv);
+ int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend *trend);
};
enum reg_list {
@@ -111,10 +111,10 @@ struct tsens_priv {
struct tsens_sensor sensor[0];
};
-char *qfprom_read(struct device *, const char *);
-void compute_intercept_slope(struct tsens_priv *, u32 *, u32 *, u32);
-int init_common(struct tsens_priv *);
-int get_temp_common(struct tsens_priv *, int, int *);
+char *qfprom_read(struct device *dev, const char *cname);
+void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
+int init_common(struct tsens_priv *priv);
+int get_temp_common(struct tsens_priv *priv, int i, int *temp);
/* TSENS v1 targets */
extern const struct tsens_plat_data data_8916, data_8974, data_8960;
--
2.17.1
8916 and 8974 use v0.1.0 of the TSENS IP. Rename tsens-8916 to prepare
it for merging with tsens-8974 in a later commit.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/Makefile | 2 +-
drivers/thermal/qcom/{tsens-8916.c => tsens-v0_1.c} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename drivers/thermal/qcom/{tsens-8916.c => tsens-v0_1.c} (100%)
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 717a08600bb5..1f2fafd43dff 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
-qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o
+qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o tsens-8974.o tsens-8960.o tsens-v2.o
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-v0_1.c
similarity index 100%
rename from drivers/thermal/qcom/tsens-8916.c
rename to drivers/thermal/qcom/tsens-v0_1.c
--
2.17.1
Some #defines in tsens-v_0_1.c clash with those in tsens-8974.c. Prefix
them with 8916 to avoid the clash so we can merge the two files.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-v0_1.c | 88 +++++++++++++++----------------
1 file changed, 44 insertions(+), 44 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index d4ad4082c800..30909594b1cf 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -7,37 +7,37 @@
#include "tsens.h"
/* eeprom layout data for 8916 */
-#define BASE0_MASK 0x0000007f
-#define BASE1_MASK 0xfe000000
-#define BASE0_SHIFT 0
-#define BASE1_SHIFT 25
-
-#define S0_P1_MASK 0x00000f80
-#define S1_P1_MASK 0x003e0000
-#define S2_P1_MASK 0xf8000000
-#define S3_P1_MASK 0x000003e0
-#define S4_P1_MASK 0x000f8000
-
-#define S0_P2_MASK 0x0001f000
-#define S1_P2_MASK 0x07c00000
-#define S2_P2_MASK 0x0000001f
-#define S3_P2_MASK 0x00007c00
-#define S4_P2_MASK 0x01f00000
-
-#define S0_P1_SHIFT 7
-#define S1_P1_SHIFT 17
-#define S2_P1_SHIFT 27
-#define S3_P1_SHIFT 5
-#define S4_P1_SHIFT 15
-
-#define S0_P2_SHIFT 12
-#define S1_P2_SHIFT 22
-#define S2_P2_SHIFT 0
-#define S3_P2_SHIFT 10
-#define S4_P2_SHIFT 20
-
-#define CAL_SEL_MASK 0xe0000000
-#define CAL_SEL_SHIFT 29
+#define MSM8916_BASE0_MASK 0x0000007f
+#define MSM8916_BASE1_MASK 0xfe000000
+#define MSM8916_BASE0_SHIFT 0
+#define MSM8916_BASE1_SHIFT 25
+
+#define MSM8916_S0_P1_MASK 0x00000f80
+#define MSM8916_S1_P1_MASK 0x003e0000
+#define MSM8916_S2_P1_MASK 0xf8000000
+#define MSM8916_S3_P1_MASK 0x000003e0
+#define MSM8916_S4_P1_MASK 0x000f8000
+
+#define MSM8916_S0_P2_MASK 0x0001f000
+#define MSM8916_S1_P2_MASK 0x07c00000
+#define MSM8916_S2_P2_MASK 0x0000001f
+#define MSM8916_S3_P2_MASK 0x00007c00
+#define MSM8916_S4_P2_MASK 0x01f00000
+
+#define MSM8916_S0_P1_SHIFT 7
+#define MSM8916_S1_P1_SHIFT 17
+#define MSM8916_S2_P1_SHIFT 27
+#define MSM8916_S3_P1_SHIFT 5
+#define MSM8916_S4_P1_SHIFT 15
+
+#define MSM8916_S0_P2_SHIFT 12
+#define MSM8916_S1_P2_SHIFT 22
+#define MSM8916_S2_P2_SHIFT 0
+#define MSM8916_S3_P2_SHIFT 10
+#define MSM8916_S4_P2_SHIFT 20
+
+#define MSM8916_CAL_SEL_MASK 0xe0000000
+#define MSM8916_CAL_SEL_SHIFT 29
static int calibrate_8916(struct tsens_priv *priv)
{
@@ -54,27 +54,27 @@ static int calibrate_8916(struct tsens_priv *priv)
if (IS_ERR(qfprom_csel))
return PTR_ERR(qfprom_csel);
- mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
+ mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT;
dev_dbg(priv->dev, "calibration mode is %d\n", mode);
switch (mode) {
case TWO_PT_CALIB:
- base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
- p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
- p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
- p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
- p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
- p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
+ base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT;
+ p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT;
+ p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT;
+ p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT;
+ p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT;
+ p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT;
for (i = 0; i < priv->num_sensors; i++)
p2[i] = ((base1 + p2[i]) << 3);
/* Fall through */
case ONE_PT_CALIB2:
- base0 = (qfprom_cdata[0] & BASE0_MASK);
- p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
- p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
- p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
- p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
- p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
+ base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK);
+ p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT;
+ p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT;
+ p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT;
+ p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT;
+ p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT;
for (i = 0; i < priv->num_sensors; i++)
p1[i] = (((base0) + p1[i]) << 3);
break;
--
2.17.1
qcs404 has a single TSENS IP block with 10 sensors. It uses version 1.4
of the TSENS IP, functionality for which is encapsulated inside the
qcom,tsens-v1 compatible.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/Makefile | 4 +-
drivers/thermal/qcom/tsens-v1.c | 229 ++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 3 +
drivers/thermal/qcom/tsens.h | 3 +
4 files changed, 238 insertions(+), 1 deletion(-)
create mode 100644 drivers/thermal/qcom/tsens-v1.c
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 7fa3cadce760..fc6fe50cdde4 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,3 +1,5 @@
obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
-qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o tsens-8960.o tsens-v2.o
+
+qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o \
+ tsens-8960.o tsens-v2.o tsens-v1.o
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c
new file mode 100644
index 000000000000..417e2c2de1a1
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include "tsens.h"
+
+/* ----- SROT ------ */
+#define SROT_HW_VER_OFF 0x0000
+#define SROT_CTRL_OFF 0x0004
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF 0x0000
+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
+#define TM_Sn_STATUS_OFF 0x0044
+#define TM_TRDY_OFF 0x0084
+
+/* eeprom layout data for qcs404/405 (v1) */
+#define BASE0_MASK 0x000007f8
+#define BASE1_MASK 0x0007f800
+#define BASE0_SHIFT 3
+#define BASE1_SHIFT 11
+
+#define S0_P1_MASK 0x0000003f
+#define S1_P1_MASK 0x0003f000
+#define S2_P1_MASK 0x3f000000
+#define S3_P1_MASK 0x000003f0
+#define S4_P1_MASK 0x003f0000
+#define S5_P1_MASK 0x0000003f
+#define S6_P1_MASK 0x0003f000
+#define S7_P1_MASK 0x3f000000
+#define S8_P1_MASK 0x000003f0
+#define S9_P1_MASK 0x003f0000
+
+#define S0_P2_MASK 0x00000fc0
+#define S1_P2_MASK 0x00fc0000
+#define S2_P2_MASK_1_0 0xc0000000
+#define S2_P2_MASK_5_2 0x0000000f
+#define S3_P2_MASK 0x0000fc00
+#define S4_P2_MASK 0x0fc00000
+#define S5_P2_MASK 0x00000fc0
+#define S6_P2_MASK 0x00fc0000
+#define S7_P2_MASK_1_0 0xc0000000
+#define S7_P2_MASK_5_2 0x0000000f
+#define S8_P2_MASK 0x0000fc00
+#define S9_P2_MASK 0x0fc00000
+
+#define S0_P1_SHIFT 0
+#define S0_P2_SHIFT 6
+#define S1_P1_SHIFT 12
+#define S1_P2_SHIFT 18
+#define S2_P1_SHIFT 24
+#define S2_P2_SHIFT_1_0 30
+
+#define S2_P2_SHIFT_5_2 0
+#define S3_P1_SHIFT 4
+#define S3_P2_SHIFT 10
+#define S4_P1_SHIFT 16
+#define S4_P2_SHIFT 22
+
+#define S5_P1_SHIFT 0
+#define S5_P2_SHIFT 6
+#define S6_P1_SHIFT 12
+#define S6_P2_SHIFT 18
+#define S7_P1_SHIFT 24
+#define S7_P2_SHIFT_1_0 30
+
+#define S7_P2_SHIFT_5_2 0
+#define S8_P1_SHIFT 4
+#define S8_P2_SHIFT 10
+#define S9_P1_SHIFT 16
+#define S9_P2_SHIFT 22
+
+#define CAL_SEL_MASK 7
+#define CAL_SEL_SHIFT 0
+
+static int calibrate_v1(struct tsens_priv *priv)
+{
+ u32 base0 = 0, base1 = 0;
+ u32 p1[10], p2[10];
+ u32 mode = 0, lsb = 0, msb = 0;
+ u32 *qfprom_cdata;
+ int i;
+
+ qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
+ if (IS_ERR(qfprom_cdata))
+ return PTR_ERR(qfprom_cdata);
+
+ mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
+ dev_dbg(priv->dev, "calibration mode is %d\n", mode);
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
+ p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
+ p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
+ /* This value is split over two registers, 2 bits and 4 bits */
+ lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
+ msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
+ p2[2] = msb << 2 | lsb;
+ p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
+ p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
+ p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
+ p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
+ /* This value is split over two registers, 2 bits and 4 bits */
+ lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
+ msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
+ p2[7] = msb << 2 | lsb;
+ p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
+ p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
+ for (i = 0; i < priv->num_sensors; i++)
+ p2[i] = ((base1 + p2[i]) << 2);
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
+ p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+ p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
+ p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
+ p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
+ p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
+ p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
+ p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
+ for (i = 0; i < priv->num_sensors; i++)
+ p1[i] = (((base0) + p1[i]) << 2);
+ break;
+ default:
+ for (i = 0; i < priv->num_sensors; i++) {
+ p1[i] = 500;
+ p2[i] = 780;
+ }
+ break;
+ }
+
+ compute_intercept_slope(priv, p1, p2, mode);
+
+ return 0;
+}
+
+/* v1.x: qcs404,405 */
+
+const struct tsens_features tsens_v1_feat = {
+ .ver_info = 1,
+ .crit_int = 0,
+ .adc = 1,
+ .srot_split = 1,
+ .max_sensors = 11,
+};
+
+const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
+ /* ----- SROT ------ */
+ /* VERSION */
+ [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
+ [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
+ [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
+ /* CTRL_OFFSET */
+ [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
+ [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
+
+ /* ----- TM ------ */
+ /* UPPER_LOWER_INTERRUPT_CTRL */
+ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+ /* Sn_UPPER_LOWER_STATUS_CTRL */
+ REG_BANK(LOW_THRESH, 0, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 0, 9),
+ REG_BANK(LOW_THRESH, 1, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 4, 0, 9),
+ REG_BANK(LOW_THRESH, 2, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 8, 0, 9),
+ REG_BANK(LOW_THRESH, 3, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 12, 0, 9),
+ REG_BANK(LOW_THRESH, 4, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 16, 0, 9),
+ REG_BANK(LOW_THRESH, 5, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 20, 0, 9),
+ REG_BANK(LOW_THRESH, 6, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 24, 0, 9),
+ REG_BANK(LOW_THRESH, 7, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 28, 0, 9),
+ REG_BANK(LOW_THRESH, 8, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 32, 0, 9),
+ REG_BANK(LOW_THRESH, 9, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 36, 0, 9),
+ REG_BANK(LOW_THRESH, 10, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 40, 0, 9),
+ REG_BANK(UP_THRESH, 0, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19),
+ REG_BANK(UP_THRESH, 1, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 4, 10, 19),
+ REG_BANK(UP_THRESH, 2, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 8, 10, 19),
+ REG_BANK(UP_THRESH, 3, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 12, 10, 19),
+ REG_BANK(UP_THRESH, 4, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 16, 10, 19),
+ REG_BANK(UP_THRESH, 5, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 20, 10, 19),
+ REG_BANK(UP_THRESH, 6, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 24, 10, 19),
+ REG_BANK(UP_THRESH, 7, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 28, 10, 19),
+ REG_BANK(UP_THRESH, 8, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 32, 10, 19),
+ REG_BANK(UP_THRESH, 9, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 36, 10, 19),
+ REG_BANK(UP_THRESH, 10, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 40, 10, 19),
+ /* Sn_STATUS */
+ REG_BANK(LAST_TEMP, 0, TM_Sn_STATUS_OFF, 0, 9),
+ REG_BANK(LAST_TEMP, 1, TM_Sn_STATUS_OFF + 4, 0, 9),
+ REG_BANK(LAST_TEMP, 2, TM_Sn_STATUS_OFF + 8, 0, 9),
+ REG_BANK(LAST_TEMP, 3, TM_Sn_STATUS_OFF + 12, 0, 9),
+ REG_BANK(LAST_TEMP, 4, TM_Sn_STATUS_OFF + 16, 0, 9),
+ REG_BANK(LAST_TEMP, 5, TM_Sn_STATUS_OFF + 20, 0, 9),
+ REG_BANK(LAST_TEMP, 6, TM_Sn_STATUS_OFF + 24, 0, 9),
+ REG_BANK(LAST_TEMP, 7, TM_Sn_STATUS_OFF + 28, 0, 9),
+ REG_BANK(LAST_TEMP, 8, TM_Sn_STATUS_OFF + 32, 0, 9),
+ REG_BANK(LAST_TEMP, 9, TM_Sn_STATUS_OFF + 36, 0, 9),
+ REG_BANK(LAST_TEMP, 10, TM_Sn_STATUS_OFF + 40, 0, 9),
+ REG_BANK(VALID, 0, TM_Sn_STATUS_OFF, 14, 14),
+ REG_BANK(VALID, 1, TM_Sn_STATUS_OFF + 4, 14, 14),
+ REG_BANK(VALID, 2, TM_Sn_STATUS_OFF + 8, 14, 14),
+ REG_BANK(VALID, 3, TM_Sn_STATUS_OFF + 12, 14, 14),
+ REG_BANK(VALID, 4, TM_Sn_STATUS_OFF + 16, 14, 14),
+ REG_BANK(VALID, 5, TM_Sn_STATUS_OFF + 20, 14, 14),
+ REG_BANK(VALID, 6, TM_Sn_STATUS_OFF + 24, 14, 14),
+ REG_BANK(VALID, 7, TM_Sn_STATUS_OFF + 28, 14, 14),
+ REG_BANK(VALID, 8, TM_Sn_STATUS_OFF + 32, 14, 14),
+ REG_BANK(VALID, 9, TM_Sn_STATUS_OFF + 36, 14, 14),
+ REG_BANK(VALID, 10, TM_Sn_STATUS_OFF + 40, 14, 14),
+ /* TRDY */
+ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
+static const struct tsens_ops ops_generic_v1 = {
+ .init = init_common,
+ .calibrate = calibrate_v1,
+ .get_temp = get_temp_tsens_valid,
+};
+
+const struct tsens_plat_data data_tsens_v1 = {
+ .ops = &ops_generic_v1,
+ .feat = &tsens_v1_feat,
+ .fields = tsens_v1_regfields,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index fc44cac31fa5..36b0b52db524 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -63,6 +63,9 @@ static const struct of_device_id tsens_table[] = {
}, {
.compatible = "qcom,msm8996-tsens",
.data = &data_8996,
+ }, {
+ .compatible = "qcom,tsens-v1",
+ .data = &data_tsens_v1,
}, {
.compatible = "qcom,tsens-v2",
.data = &data_tsens_v2,
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 4b3d71b26c97..4ed07e607cbc 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -265,6 +265,9 @@ extern const struct tsens_plat_data data_8960;
/* TSENS v0.1 targets */
extern const struct tsens_plat_data data_8916, data_8974;
+/* TSENS v1 targets */
+extern const struct tsens_plat_data data_tsens_v1;
+
/* TSENS v2 targets */
extern const struct tsens_plat_data data_8996, data_tsens_v2;
--
2.17.1
qcs404 has a single TSENS IP block with 10 sensors. The calibration data
is stored in an eeprom (qfprom) that is accessed through the nvmem
framework. We add the qfprom node to allow the tsens sensors to be
calibrated correctly.
Signed-off-by: Amit Kucheria <[email protected]>
---
arch/arm64/boot/dts/qcom/qcs404.dtsi | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
index 9b5c16562bbe..57d14d8f0c90 100644
--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -253,6 +253,16 @@
reg = <0x00060000 0x6000>;
};
+ qfprom: qfprom@a4000 {
+ compatible = "qcom,qfprom";
+ reg = <0x000a4000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ tsens_caldata: caldata@d0 {
+ reg = <0x1f8 0x14>;
+ };
+ };
+
rng: rng@e3000 {
compatible = "qcom,prng-ee";
reg = <0x000e3000 0x1000>;
@@ -260,6 +270,16 @@
clock-names = "core";
};
+ tsens: thermal-sensor@4a9000 {
+ compatible = "qcom,qcs404-tsens", "qcom,tsens-v1";
+ reg = <0x004a9000 0x1000>, /* TM */
+ <0x004a8000 0x1000>; /* SROT */
+ nvmem-cells = <&tsens_caldata>;
+ nvmem-cell-names = "calib";
+ #qcom,sensors = <10>;
+ #thermal-sensor-cells = <1>;
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,qcs404-pinctrl";
reg = <0x01000000 0x200000>,
--
2.17.1
On some TSENS IP, version is stored. Print that version at init.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index aae3d71d7eed..39cd5733fd44 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -121,7 +121,7 @@ int __init init_common(struct tsens_priv *priv)
void __iomem *tm_base, *srot_base;
struct device *dev = priv->dev;
struct resource *res;
- u32 enabled;
+ u32 enabled, maj_ver, min_ver;
int ret, i, j;
struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
@@ -155,6 +155,27 @@ int __init init_common(struct tsens_priv *priv)
if (IS_ERR(priv->tm_map))
return PTR_ERR(priv->tm_map);
+ for (i = 0; i < MAX_REGFIELDS; i++) {
+ priv->rf[i] = NULL;
+ }
+
+ /* alloc regmap_fields in srot_map */
+ if (priv->feat->ver_info) {
+ for (i = 0, j = VER_MAJOR; i < 2; i++, j++) {
+ priv->rf[j] = devm_regmap_field_alloc(dev, priv->srot_map,
+ priv->fields[j]);
+ if (IS_ERR(priv->rf[j]))
+ return PTR_ERR(priv->rf[j]);
+ }
+ ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver);
+ if (ret)
+ return ret;
+ ret = regmap_field_read(priv->rf[VER_MINOR], &min_ver);
+ if (ret)
+ return ret;
+ dev_info(dev, "version: %d.%d\n", maj_ver, min_ver);
+ }
+
priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
priv->fields[TSENS_EN]);
if (IS_ERR(priv->rf[TSENS_EN]))
--
2.17.1
8974 and 8916 have the same version of the TSENS IP. Merge the files to
allow for better code reuse.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/Makefile | 2 +-
drivers/thermal/qcom/tsens-8974.c | 236 ------------------------------
drivers/thermal/qcom/tsens-v0_1.c | 229 +++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.h | 8 +-
4 files changed, 236 insertions(+), 239 deletions(-)
delete mode 100644 drivers/thermal/qcom/tsens-8974.c
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 1f2fafd43dff..7fa3cadce760 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
-qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o tsens-8974.o tsens-8960.o tsens-v2.o
+qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o tsens-8960.o tsens-v2.o
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
deleted file mode 100644
index 303157fd00be..000000000000
--- a/drivers/thermal/qcom/tsens-8974.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/platform_device.h>
-#include "tsens.h"
-
-/* eeprom layout data for 8974 */
-#define BASE1_MASK 0xff
-#define S0_P1_MASK 0x3f00
-#define S1_P1_MASK 0xfc000
-#define S2_P1_MASK 0x3f00000
-#define S3_P1_MASK 0xfc000000
-#define S4_P1_MASK 0x3f
-#define S5_P1_MASK 0xfc0
-#define S6_P1_MASK 0x3f000
-#define S7_P1_MASK 0xfc0000
-#define S8_P1_MASK 0x3f000000
-#define S8_P1_MASK_BKP 0x3f
-#define S9_P1_MASK 0x3f
-#define S9_P1_MASK_BKP 0xfc0
-#define S10_P1_MASK 0xfc0
-#define S10_P1_MASK_BKP 0x3f000
-#define CAL_SEL_0_1 0xc0000000
-#define CAL_SEL_2 0x40000000
-#define CAL_SEL_SHIFT 30
-#define CAL_SEL_SHIFT_2 28
-
-#define S0_P1_SHIFT 8
-#define S1_P1_SHIFT 14
-#define S2_P1_SHIFT 20
-#define S3_P1_SHIFT 26
-#define S5_P1_SHIFT 6
-#define S6_P1_SHIFT 12
-#define S7_P1_SHIFT 18
-#define S8_P1_SHIFT 24
-#define S9_P1_BKP_SHIFT 6
-#define S10_P1_SHIFT 6
-#define S10_P1_BKP_SHIFT 12
-
-#define BASE2_SHIFT 12
-#define BASE2_BKP_SHIFT 18
-#define S0_P2_SHIFT 20
-#define S0_P2_BKP_SHIFT 26
-#define S1_P2_SHIFT 26
-#define S2_P2_BKP_SHIFT 6
-#define S3_P2_SHIFT 6
-#define S3_P2_BKP_SHIFT 12
-#define S4_P2_SHIFT 12
-#define S4_P2_BKP_SHIFT 18
-#define S5_P2_SHIFT 18
-#define S5_P2_BKP_SHIFT 24
-#define S6_P2_SHIFT 24
-#define S7_P2_BKP_SHIFT 6
-#define S8_P2_SHIFT 6
-#define S8_P2_BKP_SHIFT 12
-#define S9_P2_SHIFT 12
-#define S9_P2_BKP_SHIFT 18
-#define S10_P2_SHIFT 18
-#define S10_P2_BKP_SHIFT 24
-
-#define BASE2_MASK 0xff000
-#define BASE2_BKP_MASK 0xfc0000
-#define S0_P2_MASK 0x3f00000
-#define S0_P2_BKP_MASK 0xfc000000
-#define S1_P2_MASK 0xfc000000
-#define S1_P2_BKP_MASK 0x3f
-#define S2_P2_MASK 0x3f
-#define S2_P2_BKP_MASK 0xfc0
-#define S3_P2_MASK 0xfc0
-#define S3_P2_BKP_MASK 0x3f000
-#define S4_P2_MASK 0x3f000
-#define S4_P2_BKP_MASK 0xfc0000
-#define S5_P2_MASK 0xfc0000
-#define S5_P2_BKP_MASK 0x3f000000
-#define S6_P2_MASK 0x3f000000
-#define S6_P2_BKP_MASK 0x3f
-#define S7_P2_MASK 0x3f
-#define S7_P2_BKP_MASK 0xfc0
-#define S8_P2_MASK 0xfc0
-#define S8_P2_BKP_MASK 0x3f000
-#define S9_P2_MASK 0x3f000
-#define S9_P2_BKP_MASK 0xfc0000
-#define S10_P2_MASK 0xfc0000
-#define S10_P2_BKP_MASK 0x3f000000
-
-#define BKP_SEL 0x3
-#define BKP_REDUN_SEL 0xe0000000
-#define BKP_REDUN_SHIFT 29
-
-#define BIT_APPEND 0x3
-
-static int calibrate_8974(struct tsens_priv *priv)
-{
- int base1 = 0, base2 = 0, i;
- u32 p1[11], p2[11];
- int mode = 0;
- u32 *calib, *bkp;
- u32 calib_redun_sel;
-
- calib = (u32 *)qfprom_read(priv->dev, "calib");
- if (IS_ERR(calib))
- return PTR_ERR(calib);
-
- bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
- if (IS_ERR(bkp))
- return PTR_ERR(bkp);
-
- calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
- calib_redun_sel >>= BKP_REDUN_SHIFT;
-
- if (calib_redun_sel == BKP_SEL) {
- mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
- mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
-
- switch (mode) {
- case TWO_PT_CALIB:
- base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
- p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
- p2[1] = (bkp[3] & S1_P2_BKP_MASK);
- p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
- p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
- p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
- p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
- p2[6] = (calib[5] & S6_P2_BKP_MASK);
- p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
- p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
- p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
- p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
- /* Fall through */
- case ONE_PT_CALIB:
- case ONE_PT_CALIB2:
- base1 = bkp[0] & BASE1_MASK;
- p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
- p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
- p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
- p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
- p1[4] = (bkp[1] & S4_P1_MASK);
- p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
- p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
- p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
- p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
- p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
- p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
- break;
- }
- } else {
- mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
- mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
-
- switch (mode) {
- case TWO_PT_CALIB:
- base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
- p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
- p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
- p2[2] = (calib[3] & S2_P2_MASK);
- p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
- p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
- p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
- p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
- p2[7] = (calib[4] & S7_P2_MASK);
- p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
- p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
- p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
- /* Fall through */
- case ONE_PT_CALIB:
- case ONE_PT_CALIB2:
- base1 = calib[0] & BASE1_MASK;
- p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
- p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
- p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
- p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
- p1[4] = (calib[1] & S4_P1_MASK);
- p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
- p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
- p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
- p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
- p1[9] = (calib[2] & S9_P1_MASK);
- p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
- break;
- }
- }
-
- switch (mode) {
- case ONE_PT_CALIB:
- for (i = 0; i < priv->num_sensors; i++)
- p1[i] += (base1 << 2) | BIT_APPEND;
- break;
- case TWO_PT_CALIB:
- for (i = 0; i < priv->num_sensors; i++) {
- p2[i] += base2;
- p2[i] <<= 2;
- p2[i] |= BIT_APPEND;
- }
- /* Fall through */
- case ONE_PT_CALIB2:
- for (i = 0; i < priv->num_sensors; i++) {
- p1[i] += base1;
- p1[i] <<= 2;
- p1[i] |= BIT_APPEND;
- }
- break;
- default:
- for (i = 0; i < priv->num_sensors; i++)
- p2[i] = 780;
- p1[0] = 502;
- p1[1] = 509;
- p1[2] = 503;
- p1[3] = 509;
- p1[4] = 505;
- p1[5] = 509;
- p1[6] = 507;
- p1[7] = 510;
- p1[8] = 508;
- p1[9] = 509;
- p1[10] = 508;
- break;
- }
-
- compute_intercept_slope(priv, p1, p2, mode);
-
- return 0;
-}
-
-static const struct tsens_ops ops_8974 = {
- .init = init_common,
- .calibrate = calibrate_8974,
- .get_temp = get_temp_common,
-};
-
-const struct tsens_plat_data data_8974 = {
- .num_sensors = 11,
- .ops = &ops_8974,
- .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
-};
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index 30909594b1cf..a6e26be1234f 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -39,6 +39,91 @@
#define MSM8916_CAL_SEL_MASK 0xe0000000
#define MSM8916_CAL_SEL_SHIFT 29
+/* eeprom layout data for 8974 */
+#define BASE1_MASK 0xff
+#define S0_P1_MASK 0x3f00
+#define S1_P1_MASK 0xfc000
+#define S2_P1_MASK 0x3f00000
+#define S3_P1_MASK 0xfc000000
+#define S4_P1_MASK 0x3f
+#define S5_P1_MASK 0xfc0
+#define S6_P1_MASK 0x3f000
+#define S7_P1_MASK 0xfc0000
+#define S8_P1_MASK 0x3f000000
+#define S8_P1_MASK_BKP 0x3f
+#define S9_P1_MASK 0x3f
+#define S9_P1_MASK_BKP 0xfc0
+#define S10_P1_MASK 0xfc0
+#define S10_P1_MASK_BKP 0x3f000
+#define CAL_SEL_0_1 0xc0000000
+#define CAL_SEL_2 0x40000000
+#define CAL_SEL_SHIFT 30
+#define CAL_SEL_SHIFT_2 28
+
+#define S0_P1_SHIFT 8
+#define S1_P1_SHIFT 14
+#define S2_P1_SHIFT 20
+#define S3_P1_SHIFT 26
+#define S5_P1_SHIFT 6
+#define S6_P1_SHIFT 12
+#define S7_P1_SHIFT 18
+#define S8_P1_SHIFT 24
+#define S9_P1_BKP_SHIFT 6
+#define S10_P1_SHIFT 6
+#define S10_P1_BKP_SHIFT 12
+
+#define BASE2_SHIFT 12
+#define BASE2_BKP_SHIFT 18
+#define S0_P2_SHIFT 20
+#define S0_P2_BKP_SHIFT 26
+#define S1_P2_SHIFT 26
+#define S2_P2_BKP_SHIFT 6
+#define S3_P2_SHIFT 6
+#define S3_P2_BKP_SHIFT 12
+#define S4_P2_SHIFT 12
+#define S4_P2_BKP_SHIFT 18
+#define S5_P2_SHIFT 18
+#define S5_P2_BKP_SHIFT 24
+#define S6_P2_SHIFT 24
+#define S7_P2_BKP_SHIFT 6
+#define S8_P2_SHIFT 6
+#define S8_P2_BKP_SHIFT 12
+#define S9_P2_SHIFT 12
+#define S9_P2_BKP_SHIFT 18
+#define S10_P2_SHIFT 18
+#define S10_P2_BKP_SHIFT 24
+
+#define BASE2_MASK 0xff000
+#define BASE2_BKP_MASK 0xfc0000
+#define S0_P2_MASK 0x3f00000
+#define S0_P2_BKP_MASK 0xfc000000
+#define S1_P2_MASK 0xfc000000
+#define S1_P2_BKP_MASK 0x3f
+#define S2_P2_MASK 0x3f
+#define S2_P2_BKP_MASK 0xfc0
+#define S3_P2_MASK 0xfc0
+#define S3_P2_BKP_MASK 0x3f000
+#define S4_P2_MASK 0x3f000
+#define S4_P2_BKP_MASK 0xfc0000
+#define S5_P2_MASK 0xfc0000
+#define S5_P2_BKP_MASK 0x3f000000
+#define S6_P2_MASK 0x3f000000
+#define S6_P2_BKP_MASK 0x3f
+#define S7_P2_MASK 0x3f
+#define S7_P2_BKP_MASK 0xfc0
+#define S8_P2_MASK 0xfc0
+#define S8_P2_BKP_MASK 0x3f000
+#define S9_P2_MASK 0x3f000
+#define S9_P2_BKP_MASK 0xfc0000
+#define S10_P2_MASK 0xfc0000
+#define S10_P2_BKP_MASK 0x3f000000
+
+#define BKP_SEL 0x3
+#define BKP_REDUN_SEL 0xe0000000
+#define BKP_REDUN_SHIFT 29
+
+#define BIT_APPEND 0x3
+
static int calibrate_8916(struct tsens_priv *priv)
{
int base0 = 0, base1 = 0, i;
@@ -91,6 +176,138 @@ static int calibrate_8916(struct tsens_priv *priv)
return 0;
}
+static int calibrate_8974(struct tsens_priv *priv)
+{
+ int base1 = 0, base2 = 0, i;
+ u32 p1[11], p2[11];
+ int mode = 0;
+ u32 *calib, *bkp;
+ u32 calib_redun_sel;
+
+ calib = (u32 *)qfprom_read(priv->dev, "calib");
+ if (IS_ERR(calib))
+ return PTR_ERR(calib);
+
+ bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
+ if (IS_ERR(bkp))
+ return PTR_ERR(bkp);
+
+ calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
+ calib_redun_sel >>= BKP_REDUN_SHIFT;
+
+ if (calib_redun_sel == BKP_SEL) {
+ mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+ mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
+ p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
+ p2[1] = (bkp[3] & S1_P2_BKP_MASK);
+ p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
+ p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
+ p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
+ p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
+ p2[6] = (calib[5] & S6_P2_BKP_MASK);
+ p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
+ p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
+ p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
+ p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
+ /* Fall through */
+ case ONE_PT_CALIB:
+ case ONE_PT_CALIB2:
+ base1 = bkp[0] & BASE1_MASK;
+ p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+ p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (bkp[1] & S4_P1_MASK);
+ p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+ p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+ p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+ p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
+ p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
+ p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
+ break;
+ }
+ } else {
+ mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+ mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
+ p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
+ p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
+ p2[2] = (calib[3] & S2_P2_MASK);
+ p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
+ p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
+ p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
+ p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
+ p2[7] = (calib[4] & S7_P2_MASK);
+ p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
+ p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
+ p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
+ /* Fall through */
+ case ONE_PT_CALIB:
+ case ONE_PT_CALIB2:
+ base1 = calib[0] & BASE1_MASK;
+ p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+ p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (calib[1] & S4_P1_MASK);
+ p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+ p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+ p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+ p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
+ p1[9] = (calib[2] & S9_P1_MASK);
+ p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
+ break;
+ }
+ }
+
+ switch (mode) {
+ case ONE_PT_CALIB:
+ for (i = 0; i < priv->num_sensors; i++)
+ p1[i] += (base1 << 2) | BIT_APPEND;
+ break;
+ case TWO_PT_CALIB:
+ for (i = 0; i < priv->num_sensors; i++) {
+ p2[i] += base2;
+ p2[i] <<= 2;
+ p2[i] |= BIT_APPEND;
+ }
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ for (i = 0; i < priv->num_sensors; i++) {
+ p1[i] += base1;
+ p1[i] <<= 2;
+ p1[i] |= BIT_APPEND;
+ }
+ break;
+ default:
+ for (i = 0; i < priv->num_sensors; i++)
+ p2[i] = 780;
+ p1[0] = 502;
+ p1[1] = 509;
+ p1[2] = 503;
+ p1[3] = 509;
+ p1[4] = 505;
+ p1[5] = 509;
+ p1[6] = 507;
+ p1[7] = 510;
+ p1[8] = 508;
+ p1[9] = 509;
+ p1[10] = 508;
+ break;
+ }
+
+ compute_intercept_slope(priv, p1, p2, mode);
+
+ return 0;
+}
+
static const struct tsens_ops ops_8916 = {
.init = init_common,
.calibrate = calibrate_8916,
@@ -103,3 +320,15 @@ const struct tsens_plat_data data_8916 = {
.reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
.hw_ids = (unsigned int []){0, 1, 2, 4, 5 },
};
+
+static const struct tsens_ops ops_8974 = {
+ .init = init_common,
+ .calibrate = calibrate_8974,
+ .get_temp = get_temp_common,
+};
+
+const struct tsens_plat_data data_8974 = {
+ .num_sensors = 11,
+ .ops = &ops_8974,
+ .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
+};
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 4d6a406f8dca..27b8f74829d9 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -116,8 +116,12 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mo
int init_common(struct tsens_priv *priv);
int get_temp_common(struct tsens_priv *priv, int i, int *temp);
-/* TSENS v1 targets */
-extern const struct tsens_plat_data data_8916, data_8974, data_8960;
+/* TSENS target */
+extern const struct tsens_plat_data data_8960;
+
+/* TSENS v0.1 targets */
+extern const struct tsens_plat_data data_8916, data_8974;
+
/* TSENS v2 targets */
extern const struct tsens_plat_data data_8996, data_tsens_v2;
--
2.17.1
Code cleanup making it easier to read
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index a82e4c928a78..aae3d71d7eed 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -119,6 +119,7 @@ static const struct regmap_config tsens_srot_config = {
int __init init_common(struct tsens_priv *priv)
{
void __iomem *tm_base, *srot_base;
+ struct device *dev = priv->dev;
struct resource *res;
u32 enabled;
int ret, i, j;
@@ -135,7 +136,7 @@ int __init init_common(struct tsens_priv *priv)
if (IS_ERR(srot_base))
return PTR_ERR(srot_base);
- priv->srot_map = devm_regmap_init_mmio(priv->dev, srot_base,
+ priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
&tsens_srot_config);
if (IS_ERR(priv->srot_map))
return PTR_ERR(priv->srot_map);
@@ -150,11 +151,11 @@ int __init init_common(struct tsens_priv *priv)
if (IS_ERR(tm_base))
return PTR_ERR(tm_base);
- priv->tm_map = devm_regmap_init_mmio(priv->dev, tm_base, &tsens_config);
+ priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
if (IS_ERR(priv->tm_map))
return PTR_ERR(priv->tm_map);
- priv->rf[TSENS_EN] = devm_regmap_field_alloc(priv->dev, priv->srot_map,
+ priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
priv->fields[TSENS_EN]);
if (IS_ERR(priv->rf[TSENS_EN]))
return PTR_ERR(priv->rf[TSENS_EN]);
@@ -162,24 +163,24 @@ int __init init_common(struct tsens_priv *priv)
if (ret)
return ret;
if (!enabled) {
- dev_err(priv->dev, "tsens device is not enabled\n");
+ dev_err(dev, "tsens device is not enabled\n");
return -ENODEV;
}
- priv->rf[SENSOR_EN] = devm_regmap_field_alloc(priv->dev, priv->srot_map,
+ priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
priv->fields[SENSOR_EN]);
if (IS_ERR(priv->rf[SENSOR_EN]))
return PTR_ERR(priv->rf[SENSOR_EN]);
/* now alloc regmap_fields in tm_map */
for (i = 0, j = LAST_TEMP_0; i < priv->num_sensors; i++, j++) {
- priv->rf[j] = devm_regmap_field_alloc(priv->dev, priv->tm_map,
+ priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
priv->fields[j]);
if (IS_ERR(priv->rf[j]))
return PTR_ERR(priv->rf[j]);
}
for (i = 0, j = VALID_0; i < priv->num_sensors; i++, j++) {
- priv->rf[j] = devm_regmap_field_alloc(priv->dev, priv->tm_map,
+ priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
priv->fields[j]);
if (IS_ERR(priv->rf[j]))
return PTR_ERR(priv->rf[j]);
--
2.17.1
As we add support for newer versions of the TSENS IP, the current
approach isn't scaling because registers and bitfields get moved around,
requiring platform-specific hacks in the code. By moving to regmap, we
can hide the register level differences away from the code.
Define a common set of registers and bit-fields that we care about
across the various tsens IP versions.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens-common.c | 59 ++++++-----
drivers/thermal/qcom/tsens-v0_1.c | 51 +++++++++-
drivers/thermal/qcom/tsens-v2.c | 140 ++++++++++++++++++++-----
drivers/thermal/qcom/tsens.c | 5 +-
drivers/thermal/qcom/tsens.h | 153 ++++++++++++++++++++++++++--
5 files changed, 348 insertions(+), 60 deletions(-)
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index af87216ee407..a82e4c928a78 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -12,13 +12,6 @@
#include <linux/regmap.h>
#include "tsens.h"
-/* SROT */
-#define TSENS_EN BIT(0)
-
-/* TM */
-#define STATUS_OFFSET 0x30
-#define SN_ADDR_OFFSET 0x4
-#define SN_ST_TEMP_MASK 0x3ff
#define CAL_DEGC_PT1 30
#define CAL_DEGC_PT2 120
#define SLOPE_FACTOR 1000
@@ -95,18 +88,14 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
return degc;
}
-int get_temp_common(struct tsens_priv *priv, int id, int *temp)
+int get_temp_common(struct tsens_priv *priv, int i, int *temp)
{
- struct tsens_sensor *s = &priv->sensor[id];
- u32 code;
- unsigned int status_reg;
+ struct tsens_sensor *s = &priv->sensor[i];
int last_temp = 0, ret;
- status_reg = priv->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET;
- ret = regmap_read(priv->tm_map, status_reg, &code);
+ ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp);
if (ret)
return ret;
- last_temp = code & SN_ST_TEMP_MASK;
*temp = code_to_degc(last_temp, s) * 1000;
@@ -131,10 +120,9 @@ int __init init_common(struct tsens_priv *priv)
{
void __iomem *tm_base, *srot_base;
struct resource *res;
- u32 code;
- int ret;
+ u32 enabled;
+ int ret, i, j;
struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
- u16 ctrl_offset = priv->reg_offsets[SROT_CTRL_OFFSET];
if (!op)
return -EINVAL;
@@ -166,14 +154,35 @@ int __init init_common(struct tsens_priv *priv)
if (IS_ERR(priv->tm_map))
return PTR_ERR(priv->tm_map);
- if (priv->srot_map) {
- ret = regmap_read(priv->srot_map, ctrl_offset, &code);
- if (ret)
- return ret;
- if (!(code & TSENS_EN)) {
- dev_err(priv->dev, "tsens device is not enabled\n");
- return -ENODEV;
- }
+ priv->rf[TSENS_EN] = devm_regmap_field_alloc(priv->dev, priv->srot_map,
+ priv->fields[TSENS_EN]);
+ if (IS_ERR(priv->rf[TSENS_EN]))
+ return PTR_ERR(priv->rf[TSENS_EN]);
+ ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
+ if (ret)
+ return ret;
+ if (!enabled) {
+ dev_err(priv->dev, "tsens device is not enabled\n");
+ return -ENODEV;
+ }
+
+ priv->rf[SENSOR_EN] = devm_regmap_field_alloc(priv->dev, priv->srot_map,
+ priv->fields[SENSOR_EN]);
+ if (IS_ERR(priv->rf[SENSOR_EN]))
+ return PTR_ERR(priv->rf[SENSOR_EN]);
+
+ /* now alloc regmap_fields in tm_map */
+ for (i = 0, j = LAST_TEMP_0; i < priv->num_sensors; i++, j++) {
+ priv->rf[j] = devm_regmap_field_alloc(priv->dev, priv->tm_map,
+ priv->fields[j]);
+ if (IS_ERR(priv->rf[j]))
+ return PTR_ERR(priv->rf[j]);
+ }
+ for (i = 0, j = VALID_0; i < priv->num_sensors; i++, j++) {
+ priv->rf[j] = devm_regmap_field_alloc(priv->dev, priv->tm_map,
+ priv->fields[j]);
+ if (IS_ERR(priv->rf[j]))
+ return PTR_ERR(priv->rf[j]);
}
return 0;
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index a6e26be1234f..02907751c201 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -6,6 +6,15 @@
#include <linux/platform_device.h>
#include "tsens.h"
+/* ----- SROT ------ */
+#define SROT_CTRL_OFF 0x0000
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF 0x0000
+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
+#define TM_Sn_STATUS_OFF 0x0030
+#define TM_TRDY_OFF 0x005c
+
/* eeprom layout data for 8916 */
#define MSM8916_BASE0_MASK 0x0000007f
#define MSM8916_BASE1_MASK 0xfe000000
@@ -308,6 +317,41 @@ static int calibrate_8974(struct tsens_priv *priv)
return 0;
}
+/* v0.1: 8916, 8974 */
+
+const struct tsens_features tsens_v0_1_feat = {
+ .ver_info = 0,
+ .crit_int = 0,
+ .adc = 1,
+ .srot_split = 1,
+};
+
+/* v0.1: 8916, 8974 */
+const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = {
+ /* ----- SROT ------ */
+ /* CTRL_OFFSET */
+ [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
+ [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
+
+ /* ----- TM ------ */
+ /* UPPER_LOWER_INTERRUPT_CTRL */
+ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+ /* Sn_STATUS */
+ REG_BANK(LAST_TEMP, 0, TM_Sn_STATUS_OFF, 0, 9),
+ REG_BANK(LAST_TEMP, 1, TM_Sn_STATUS_OFF + 4, 0, 9),
+ REG_BANK(LAST_TEMP, 2, TM_Sn_STATUS_OFF + 8, 0, 9),
+ REG_BANK(LAST_TEMP, 3, TM_Sn_STATUS_OFF + 12, 0, 9),
+ REG_BANK(LAST_TEMP, 4, TM_Sn_STATUS_OFF + 16, 0, 9),
+ REG_BANK(LAST_TEMP, 5, TM_Sn_STATUS_OFF + 20, 0, 9),
+ REG_BANK(LAST_TEMP, 6, TM_Sn_STATUS_OFF + 24, 0, 9),
+ REG_BANK(LAST_TEMP, 7, TM_Sn_STATUS_OFF + 28, 0, 9),
+ REG_BANK(LAST_TEMP, 8, TM_Sn_STATUS_OFF + 32, 0, 9),
+ REG_BANK(LAST_TEMP, 9, TM_Sn_STATUS_OFF + 36, 0, 9),
+ REG_BANK(LAST_TEMP, 10, TM_Sn_STATUS_OFF + 40, 0, 9),
+ /* TRDY */
+ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
static const struct tsens_ops ops_8916 = {
.init = init_common,
.calibrate = calibrate_8916,
@@ -317,8 +361,10 @@ static const struct tsens_ops ops_8916 = {
const struct tsens_plat_data data_8916 = {
.num_sensors = 5,
.ops = &ops_8916,
- .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
.hw_ids = (unsigned int []){0, 1, 2, 4, 5 },
+
+ .feat = &tsens_v0_1_feat,
+ .fields = tsens_v0_1_regfields,
};
static const struct tsens_ops ops_8974 = {
@@ -330,5 +376,6 @@ static const struct tsens_ops ops_8974 = {
const struct tsens_plat_data data_8974 = {
.num_sensors = 11,
.ops = &ops_8974,
- .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
+ .feat = &tsens_v0_1_feat,
+ .fields = tsens_v0_1_regfields,
};
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 8b700772d903..962e47c54dca 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -4,50 +4,70 @@
* Copyright (c) 2018, Linaro Limited
*/
-#include <linux/regmap.h>
#include <linux/bitops.h>
+#include <linux/regmap.h>
#include "tsens.h"
-#define STATUS_OFFSET 0xa0
+/* ----- SROT ------ */
+#define SROT_HW_VER_OFF 0x0000
+#define SROT_CTRL_OFF 0x0004
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF 0x0004
+#define TM_UPPER_LOWER_INT_STATUS_OFF 0x0008
+#define TM_UPPER_LOWER_INT_CLEAR_OFF 0x000c
+#define TM_UPPER_LOWER_INT_MASK_OFF 0x0010
+#define TM_CRITICAL_INT_STATUS_OFF 0x0014
+#define TM_CRITICAL_INT_CLEAR_OFF 0x0018
+#define TM_CRITICAL_INT_MASK_OFF 0x001c
+#define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020
+#define TM_Sn_CRITICAL_THRESHOLD_OFF 0x0060
+#define TM_Sn_STATUS_OFF 0x00a0
+#define TM_TRDY_OFF 0x00e4
+
#define LAST_TEMP_MASK 0xfff
-#define STATUS_VALID_BIT BIT(21)
static int get_temp_tsens_v2(struct tsens_priv *priv, int id, int *temp)
{
struct tsens_sensor *s = &priv->sensor[id];
- u32 code;
- unsigned int status_reg;
- u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0;
+ u32 temp_idx = LAST_TEMP_0 + s->hw_id;
+ u32 valid_idx = VALID_0 + s->hw_id;
+ u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0, valid;
int ret;
- status_reg = priv->tm_offset + STATUS_OFFSET + s->hw_id * 4;
- ret = regmap_read(priv->tm_map, status_reg, &code);
+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
if (ret)
return ret;
- last_temp = code & LAST_TEMP_MASK;
- if (code & STATUS_VALID_BIT)
+
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
+ if (ret)
+ return ret;
+
+ if (valid)
goto done;
/* Try a second time */
- ret = regmap_read(priv->tm_map, status_reg, &code);
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
if (ret)
return ret;
- if (code & STATUS_VALID_BIT) {
- last_temp = code & LAST_TEMP_MASK;
+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp2);
+ if (ret)
+ return ret;
+ if (valid) {
+ last_temp = last_temp2;
goto done;
- } else {
- last_temp2 = code & LAST_TEMP_MASK;
}
/* Try a third/last time */
- ret = regmap_read(priv->tm_map, status_reg, &code);
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
if (ret)
return ret;
- if (code & STATUS_VALID_BIT) {
- last_temp = code & LAST_TEMP_MASK;
+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp3);
+ if (ret)
+ return ret;
+ if (valid) {
+ last_temp = last_temp3;
goto done;
- } else {
- last_temp3 = code & LAST_TEMP_MASK;
}
if (last_temp == last_temp2)
@@ -61,19 +81,93 @@ static int get_temp_tsens_v2(struct tsens_priv *priv, int id, int *temp)
return 0;
}
+/* v2.x: 8996, 8998, sdm845 */
+
+const struct tsens_features tsens_v2_feat = {
+ .ver_info = 1,
+ .crit_int = 1,
+ .adc = 0,
+ .srot_split = 1,
+};
+
+const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
+ /* ----- SROT ------ */
+ /* VERSION */
+ [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
+ [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
+ [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
+ /* CTRL_OFF */
+ [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
+ [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
+
+ /* ----- TM ------ */
+ /* INTERRUPT ENABLE */
+ [LOW_INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+ [UP_INT_EN] = REG_FIELD(TM_INT_EN_OFF, 1, 1),
+ [CRIT_INT_EN] = REG_FIELD(TM_INT_EN_OFF, 2, 2),
+ /* UPPER_LOWER_INTERRUPTS */
+ [LOW_INT_STATUS] = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF, 0, 15),
+ [UP_INT_STATUS] = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF, 16, 31),
+ [LOW_INT_CLEAR] = REG_FIELD(TM_UPPER_LOWER_INT_CLEAR_OFF, 0, 15),
+ [UP_INT_CLEAR] = REG_FIELD(TM_UPPER_LOWER_INT_CLEAR_OFF, 16, 31),
+ [LOW_INT_MASK] = REG_FIELD(TM_UPPER_LOWER_INT_MASK_OFF, 0, 15),
+ [UP_INT_MASK] = REG_FIELD(TM_UPPER_LOWER_INT_MASK_OFF, 16, 31),
+ /* CRITICAL_INTERRUPT */
+ [CRIT_INT_STATUS] = REG_FIELD(TM_CRITICAL_INT_STATUS_OFF, 0, 15),
+ [CRIT_INT_CLEAR] = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF, 0, 15),
+ [CRIT_INT_MASK] = REG_FIELD(TM_UPPER_LOWER_INT_STATUS_OFF, 0, 15),
+ /* Sn_STATUS */
+ REG_BANK(LAST_TEMP, 0, TM_Sn_STATUS_OFF, 0, 11),
+ REG_BANK(LAST_TEMP, 1, TM_Sn_STATUS_OFF + 4, 0, 11),
+ REG_BANK(LAST_TEMP, 2, TM_Sn_STATUS_OFF + 8, 0, 11),
+ REG_BANK(LAST_TEMP, 3, TM_Sn_STATUS_OFF + 12, 0, 11),
+ REG_BANK(LAST_TEMP, 4, TM_Sn_STATUS_OFF + 16, 0, 11),
+ REG_BANK(LAST_TEMP, 5, TM_Sn_STATUS_OFF + 20, 0, 11),
+ REG_BANK(LAST_TEMP, 6, TM_Sn_STATUS_OFF + 24, 0, 11),
+ REG_BANK(LAST_TEMP, 7, TM_Sn_STATUS_OFF + 28, 0, 11),
+ REG_BANK(LAST_TEMP, 8, TM_Sn_STATUS_OFF + 32, 0, 11),
+ REG_BANK(LAST_TEMP, 9, TM_Sn_STATUS_OFF + 36, 0, 11),
+ REG_BANK(LAST_TEMP, 10, TM_Sn_STATUS_OFF + 40, 0, 11),
+ REG_BANK(LAST_TEMP, 11, TM_Sn_STATUS_OFF + 44, 0, 11),
+ REG_BANK(LAST_TEMP, 12, TM_Sn_STATUS_OFF + 48, 0, 11),
+ REG_BANK(LAST_TEMP, 13, TM_Sn_STATUS_OFF + 52, 0, 11),
+ REG_BANK(LAST_TEMP, 14, TM_Sn_STATUS_OFF + 56, 0, 11),
+ REG_BANK(LAST_TEMP, 15, TM_Sn_STATUS_OFF + 60, 0, 11),
+ REG_BANK(VALID, 0, TM_Sn_STATUS_OFF, 21, 21),
+ REG_BANK(VALID, 1, TM_Sn_STATUS_OFF + 4, 21, 21),
+ REG_BANK(VALID, 2, TM_Sn_STATUS_OFF + 8, 21, 21),
+ REG_BANK(VALID, 3, TM_Sn_STATUS_OFF + 12, 21, 21),
+ REG_BANK(VALID, 4, TM_Sn_STATUS_OFF + 16, 21, 21),
+ REG_BANK(VALID, 5, TM_Sn_STATUS_OFF + 20, 21, 21),
+ REG_BANK(VALID, 6, TM_Sn_STATUS_OFF + 24, 21, 21),
+ REG_BANK(VALID, 7, TM_Sn_STATUS_OFF + 28, 21, 21),
+ REG_BANK(VALID, 8, TM_Sn_STATUS_OFF + 32, 21, 21),
+ REG_BANK(VALID, 9, TM_Sn_STATUS_OFF + 36, 21, 21),
+ REG_BANK(VALID, 10, TM_Sn_STATUS_OFF + 40, 21, 21),
+ REG_BANK(VALID, 11, TM_Sn_STATUS_OFF + 44, 21, 21),
+ REG_BANK(VALID, 12, TM_Sn_STATUS_OFF + 48, 21, 21),
+ REG_BANK(VALID, 13, TM_Sn_STATUS_OFF + 52, 21, 21),
+ REG_BANK(VALID, 14, TM_Sn_STATUS_OFF + 56, 21, 21),
+ REG_BANK(VALID, 15, TM_Sn_STATUS_OFF + 60, 21, 21),
+ /* TRDY: 1=ready, 0=in progress */
+ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
static const struct tsens_ops ops_generic_v2 = {
.init = init_common,
.get_temp = get_temp_tsens_v2,
};
const struct tsens_plat_data data_tsens_v2 = {
- .ops = &ops_generic_v2,
- .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 },
+ .ops = &ops_generic_v2,
+ .feat = &tsens_v2_feat,
+ .fields = tsens_v2_regfields,
};
/* Kept around for backward compatibility with old msm8996.dtsi */
const struct tsens_plat_data data_8996 = {
.num_sensors = 13,
.ops = &ops_generic_v2,
- .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 },
+ .feat = &tsens_v2_feat,
+ .fields = tsens_v2_regfields,
};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 0b5be08d515f..b91a0b88d33c 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -144,9 +144,8 @@ static int tsens_probe(struct platform_device *pdev)
else
priv->sensor[i].hw_id = i;
}
- for (i = 0; i < REG_ARRAY_SIZE; i++) {
- priv->reg_offsets[i] = data->reg_offsets[i];
- }
+ priv->feat = data->feat;
+ priv->fields = data->fields;
if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
return -EINVAL;
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 27b8f74829d9..20d89f8a6c3e 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -11,6 +11,7 @@
#define TWO_PT_CALIB 0x3
#include <linux/thermal.h>
+#include <linux/regmap.h>
struct tsens_priv;
@@ -58,10 +59,142 @@ struct tsens_ops {
int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend *trend);
};
-enum reg_list {
- SROT_CTRL_OFFSET,
+#define REG_BANK(_name, _index, _offset, _startbit, _stopbit) \
+ [_name##_##_index] = REG_FIELD(_offset, _startbit, _stopbit)
- REG_ARRAY_SIZE,
+/* reg_field IDs to use as an index into an array */
+enum regfield_ids {
+ /* ----- SROT ------ */
+ /* HW_VER */
+ VER_MAJOR = 0,
+ VER_MINOR,
+ VER_STEP,
+ /* CTRL_OFFSET */
+ TSENS_EN = 3,
+ TSENS_SW_RST,
+ SENSOR_EN,
+ CODE_OR_TEMP,
+
+ /* ----- TM ------ */
+ /* STATUS */
+ LAST_TEMP_0 = 7,
+ LAST_TEMP_1,
+ LAST_TEMP_2,
+ LAST_TEMP_3,
+ LAST_TEMP_4,
+ LAST_TEMP_5,
+ LAST_TEMP_6,
+ LAST_TEMP_7,
+ LAST_TEMP_8,
+ LAST_TEMP_9,
+ LAST_TEMP_10,
+ LAST_TEMP_11,
+ LAST_TEMP_12,
+ LAST_TEMP_13,
+ LAST_TEMP_14,
+ LAST_TEMP_15,
+ VALID_0 = 23,
+ VALID_1,
+ VALID_2,
+ VALID_3,
+ VALID_4,
+ VALID_5,
+ VALID_6,
+ VALID_7,
+ VALID_8,
+ VALID_9,
+ VALID_10,
+ VALID_11,
+ VALID_12,
+ VALID_13,
+ VALID_14,
+ VALID_15,
+ /* TRDY */
+ TRDY,
+ /* INTERRUPT ENABLE */
+ INT_EN, /* PRE-V1, V1.x */
+ LOW_INT_EN, /* V2.x */
+ UP_INT_EN, /* V2.x */
+ CRIT_INT_EN, /* V2.x */
+ /* INTERRUPT_STATUS */
+ LOW_INT_STATUS,
+ UP_INT_STATUS,
+ CRIT_INT_STATUS,
+ /* INTERRUPT_CLEAR */
+ LOW_INT_CLEAR,
+ UP_INT_CLEAR,
+ CRIT_INT_CLEAR,
+ /* INTERRUPT_MASK */
+ LOW_INT_MASK,
+ UP_INT_MASK,
+ CRIT_INT_MASK,
+ /* THRESHOLD */
+ LOW_THRESH_0,
+ LOW_THRESH_1,
+ LOW_THRESH_2,
+ LOW_THRESH_3,
+ LOW_THRESH_4,
+ LOW_THRESH_5,
+ LOW_THRESH_6,
+ LOW_THRESH_7,
+ LOW_THRESH_8,
+ LOW_THRESH_9,
+ LOW_THRESH_10,
+ LOW_THRESH_11,
+ LOW_THRESH_12,
+ LOW_THRESH_13,
+ LOW_THRESH_14,
+ LOW_THRESH_15,
+ UP_THRESH_0,
+ UP_THRESH_1,
+ UP_THRESH_2,
+ UP_THRESH_3,
+ UP_THRESH_4,
+ UP_THRESH_5,
+ UP_THRESH_6,
+ UP_THRESH_7,
+ UP_THRESH_8,
+ UP_THRESH_9,
+ UP_THRESH_10,
+ UP_THRESH_11,
+ UP_THRESH_12,
+ UP_THRESH_13,
+ UP_THRESH_14,
+ UP_THRESH_15,
+ CRIT_THRESH_0,
+ CRIT_THRESH_1,
+ CRIT_THRESH_2,
+ CRIT_THRESH_3,
+ CRIT_THRESH_4,
+ CRIT_THRESH_5,
+ CRIT_THRESH_6,
+ CRIT_THRESH_7,
+ CRIT_THRESH_8,
+ CRIT_THRESH_9,
+ CRIT_THRESH_10,
+ CRIT_THRESH_11,
+ CRIT_THRESH_12,
+ CRIT_THRESH_13,
+ CRIT_THRESH_14,
+ CRIT_THRESH_15,
+
+ /* Keep last */
+ MAX_REGFIELDS
+};
+
+/**
+ * struct tsens_features - Features supported by the IP
+ * @ver_info: does the IP export version information?
+ * @crit_int: does the IP support critical interrupts?
+ * @adc: do the sensors only output adc code (instead of temperature)?
+ * @srot_split: does the IP neatly splits the register space into SROT and TM,
+ * with SROT only being available to secure boot firmware?
+ */
+struct tsens_features {
+ unsigned int ver_info:1;
+ unsigned int crit_int:1;
+ unsigned int adc:1;
+ unsigned int srot_split:1;
};
/**
@@ -69,13 +202,15 @@ enum reg_list {
* @num_sensors: Number of sensors supported by platform
* @ops: operations the tsens instance supports
* @hw_ids: Subset of sensors ids supported by platform, if not the first n
- * @reg_offsets: Register offsets for commonly used registers
+ * @feat: features of the IP
+ * @fields: bitfield locations
*/
struct tsens_plat_data {
const u32 num_sensors;
const struct tsens_ops *ops;
- const u16 reg_offsets[REG_ARRAY_SIZE];
unsigned int *hw_ids;
+ const struct tsens_features *feat;
+ const struct reg_field *fields;
};
/**
@@ -94,8 +229,10 @@ struct tsens_context {
* @srot_map: pointer to SROT register address space
* @tm_offset: deal with old device trees that don't address TM and SROT
* address space separately
- * @reg_offsets: array of offsets to important regs for this version of IP
+ * @rf: array of regmap_fields used to store value of the field
* @ctx: registers to be saved and restored during suspend/resume
+ * @feat: features of the IP
+ * @fields: bitfield locations
* @ops: pointer to list of callbacks supported by this device
* @sensor: list of sensors attached to this device
*/
@@ -105,8 +242,10 @@ struct tsens_priv {
struct regmap *tm_map;
struct regmap *srot_map;
u32 tm_offset;
- u16 reg_offsets[REG_ARRAY_SIZE];
+ struct regmap_field *rf[MAX_REGFIELDS];
struct tsens_context ctx;
+ const struct tsens_features *feat;
+ const struct reg_field *fields;
const struct tsens_ops *ops;
struct tsens_sensor sensor[0];
};
--
2.17.1
We print a calibration failure message on -EPROBE_DEFER from
nvmem/qfprom as follows:
[ 3.003090] qcom-tsens 4a9000.thermal-sensor: version: 1.4
[ 3.005376] qcom-tsens 4a9000.thermal-sensor: tsens calibration failed
[ 3.113248] qcom-tsens 4a9000.thermal-sensor: version: 1.4
This confuses people when, in fact, calibration succeeds later when
nvmem/qfprom device is available. Don't print this message on a
-EPROBE_DEFER.
Signed-off-by: Amit Kucheria <[email protected]>
---
drivers/thermal/qcom/tsens.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index b91a0b88d33c..057b33353ba3 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -159,7 +159,8 @@ static int tsens_probe(struct platform_device *pdev)
if (priv->ops->calibrate) {
ret = priv->ops->calibrate(priv);
if (ret < 0) {
- dev_err(dev, "tsens calibration failed\n");
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "tsens calibration failed\n");
return ret;
}
}
--
2.17.1
On Thu, Feb 07, 2019 at 04:19:41PM +0530, Amit Kucheria wrote:
> qcs404 has 10 sensors connected to the single TSENS IP. Define a thermal
> zone for each of those sensors to expose the temperature of each zone.
>
> Signed-off-by: Amit Kucheria <[email protected]>
> ---
> arch/arm64/boot/dts/qcom/qcs404.dtsi | 243 +++++++++++++++++++++++++++
> 1 file changed, 243 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
> index 57d14d8f0c90..ca99c45864df 100644
> --- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
> +++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
> @@ -3,6 +3,7 @@
>
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> #include <dt-bindings/clock/qcom,gcc-qcs404.h>
> +#include <dt-bindings/thermal/thermal.h>
>
> / {
> interrupt-parent = <&intc>;
> @@ -30,6 +31,7 @@
> reg = <0x100>;
> enable-method = "psci";
> next-level-cache = <&L2_0>;
> + #cooling-cells= <2>;
> };
>
> CPU1: cpu@101 {
> @@ -38,6 +40,7 @@
> reg = <0x101>;
> enable-method = "psci";
> next-level-cache = <&L2_0>;
> + #cooling-cells= <2>;
> };
>
> CPU2: cpu@102 {
> @@ -46,6 +49,7 @@
> reg = <0x102>;
> enable-method = "psci";
> next-level-cache = <&L2_0>;
> + #cooling-cells= <2>;
> };
>
> CPU3: cpu@103 {
> @@ -54,6 +58,7 @@
> reg = <0x103>;
> enable-method = "psci";
> next-level-cache = <&L2_0>;
> + #cooling-cells= <2>;
> };
>
> L2_0: l2-cache {
> @@ -507,4 +512,242 @@
> #interrupt-cells = <2>;
> };
> };
> +
> + thermal-zones {
There are several zones with passive trips and no cooling maps.
> + aoss-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 0>;
> +
> + trips {
> + aoss_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + aoss_crit: aoss_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> +
> + dsp-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 1>;
> +
> + trips {
> + dsp_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + dsp_crit: dsp_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> +
> + lpass-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 2>;
> +
> + trips {
> + lpass_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + lpass_crit: lpass_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> +
> + wlan-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 3>;
> +
> + trips {
> + wlan_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + wlan_crit: wlan_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> +
> + cluster-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 4>;
> +
> + trips {
> + cluster_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + cluster_crit: cluster_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> +
> + cpu0-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 5>;
> +
> + trips {
> + cpu0_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + cpu0_crit: cpu_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + cooling-maps {
> + map0 {
> + trip = <&cpu0_alert0>;
> + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> + };
> + };
> + };
> +
> + cpu1-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 6>;
> +
> + trips {
> + cpu1_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + cpu1_crit: cpu_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + cooling-maps {
> + map0 {
> + trip = <&cpu1_alert0>;
> + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> + };
> + };
> + };
> +
> + cpu2-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 7>;
> +
> + trips {
> + cpu2_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + cpu2_crit: cpu_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + cooling-maps {
> + map0 {
> + trip = <&cpu2_alert0>;
> + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> + };
> + };
> + };
> +
> + cpu3-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 8>;
> +
> + trips {
> + cpu3_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + cpu3_crit: cpu_crit {
> + temperature = <110000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + cooling-maps {
> + map0 {
> + trip = <&cpu3_alert0>;
> + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> + };
> + };
> + };
> +
> + gpu-thermal {
> + polling-delay-passive = <250>;
> + polling-delay = <1000>;
> +
> + thermal-sensors = <&tsens 9>;
> +
> + trips {
> + gpu_alert0: trip-point@0 {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "passive";
> + };
> + gpu_crit: gpu_crit {
> + temperature = <95000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> + };
> };
> --
> 2.17.1
>
On Thu, Feb 07, 2019 at 04:19:39PM +0530, Amit Kucheria wrote:
> qcs404 has a single TSENS IP block with 10 sensors. It uses version 1.4
> of the TSENS IP, functionality for which is encapsulated inside the
> qcom,tsens-v1 compatible.
>
> Signed-off-by: Amit Kucheria <[email protected]>
> ---
> drivers/thermal/qcom/Makefile | 4 +-
> drivers/thermal/qcom/tsens-v1.c | 229 ++++++++++++++++++++++++++++++++
> drivers/thermal/qcom/tsens.c | 3 +
> drivers/thermal/qcom/tsens.h | 3 +
> 4 files changed, 238 insertions(+), 1 deletion(-)
> create mode 100644 drivers/thermal/qcom/tsens-v1.c
>
> diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
> index 7fa3cadce760..fc6fe50cdde4 100644
> --- a/drivers/thermal/qcom/Makefile
> +++ b/drivers/thermal/qcom/Makefile
> @@ -1,3 +1,5 @@
> obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
> -qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o tsens-8960.o tsens-v2.o
> +
> +qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o \
> + tsens-8960.o tsens-v2.o tsens-v1.o
> obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
> diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c
> new file mode 100644
> index 000000000000..417e2c2de1a1
> --- /dev/null
> +++ b/drivers/thermal/qcom/tsens-v1.c
> @@ -0,0 +1,229 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, Linaro Limited
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/regmap.h>
> +#include <linux/delay.h>
> +#include "tsens.h"
> +
> +/* ----- SROT ------ */
> +#define SROT_HW_VER_OFF 0x0000
> +#define SROT_CTRL_OFF 0x0004
> +
> +/* ----- TM ------ */
> +#define TM_INT_EN_OFF 0x0000
> +#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
> +#define TM_Sn_STATUS_OFF 0x0044
> +#define TM_TRDY_OFF 0x0084
> +
> +/* eeprom layout data for qcs404/405 (v1) */
> +#define BASE0_MASK 0x000007f8
> +#define BASE1_MASK 0x0007f800
> +#define BASE0_SHIFT 3
> +#define BASE1_SHIFT 11
> +
> +#define S0_P1_MASK 0x0000003f
> +#define S1_P1_MASK 0x0003f000
> +#define S2_P1_MASK 0x3f000000
> +#define S3_P1_MASK 0x000003f0
> +#define S4_P1_MASK 0x003f0000
> +#define S5_P1_MASK 0x0000003f
> +#define S6_P1_MASK 0x0003f000
> +#define S7_P1_MASK 0x3f000000
> +#define S8_P1_MASK 0x000003f0
> +#define S9_P1_MASK 0x003f0000
> +
> +#define S0_P2_MASK 0x00000fc0
> +#define S1_P2_MASK 0x00fc0000
> +#define S2_P2_MASK_1_0 0xc0000000
> +#define S2_P2_MASK_5_2 0x0000000f
> +#define S3_P2_MASK 0x0000fc00
> +#define S4_P2_MASK 0x0fc00000
> +#define S5_P2_MASK 0x00000fc0
> +#define S6_P2_MASK 0x00fc0000
> +#define S7_P2_MASK_1_0 0xc0000000
> +#define S7_P2_MASK_5_2 0x0000000f
> +#define S8_P2_MASK 0x0000fc00
> +#define S9_P2_MASK 0x0fc00000
> +
> +#define S0_P1_SHIFT 0
> +#define S0_P2_SHIFT 6
> +#define S1_P1_SHIFT 12
> +#define S1_P2_SHIFT 18
> +#define S2_P1_SHIFT 24
> +#define S2_P2_SHIFT_1_0 30
> +
> +#define S2_P2_SHIFT_5_2 0
> +#define S3_P1_SHIFT 4
> +#define S3_P2_SHIFT 10
> +#define S4_P1_SHIFT 16
> +#define S4_P2_SHIFT 22
> +
> +#define S5_P1_SHIFT 0
> +#define S5_P2_SHIFT 6
> +#define S6_P1_SHIFT 12
> +#define S6_P2_SHIFT 18
> +#define S7_P1_SHIFT 24
> +#define S7_P2_SHIFT_1_0 30
> +
> +#define S7_P2_SHIFT_5_2 0
> +#define S8_P1_SHIFT 4
> +#define S8_P2_SHIFT 10
> +#define S9_P1_SHIFT 16
> +#define S9_P2_SHIFT 22
> +
> +#define CAL_SEL_MASK 7
Why not using the macros on bits.h?
> +#define CAL_SEL_SHIFT 0
> +
> +static int calibrate_v1(struct tsens_priv *priv)
> +{
> + u32 base0 = 0, base1 = 0;
> + u32 p1[10], p2[10];
> + u32 mode = 0, lsb = 0, msb = 0;
> + u32 *qfprom_cdata;
> + int i;
> +
> + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
> + if (IS_ERR(qfprom_cdata))
> + return PTR_ERR(qfprom_cdata);
> +
> + mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
> + dev_dbg(priv->dev, "calibration mode is %d\n", mode);
> +
> + switch (mode) {
> + case TWO_PT_CALIB:
> + base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
> + p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
> + p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
> + /* This value is split over two registers, 2 bits and 4 bits */
> + lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
> + msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
> + p2[2] = msb << 2 | lsb;
> + p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
> + p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
> + p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
> + p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
> + /* This value is split over two registers, 2 bits and 4 bits */
> + lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
> + msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
> + p2[7] = msb << 2 | lsb;
> + p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
> + p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
> + for (i = 0; i < priv->num_sensors; i++)
> + p2[i] = ((base1 + p2[i]) << 2);
> + /* Fall through */
> + case ONE_PT_CALIB2:
> + base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
> + p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
> + p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
> + p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
> + p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
> + p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
> + p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
> + p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
> + p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
> + p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
> + p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
> + for (i = 0; i < priv->num_sensors; i++)
> + p1[i] = (((base0) + p1[i]) << 2);
> + break;
> + default:
> + for (i = 0; i < priv->num_sensors; i++) {
> + p1[i] = 500;
> + p2[i] = 780;
> + }
> + break;
> + }
> +
> + compute_intercept_slope(priv, p1, p2, mode);
> +
> + return 0;
> +}
> +
> +/* v1.x: qcs404,405 */
> +
> +const struct tsens_features tsens_v1_feat = {
> + .ver_info = 1,
> + .crit_int = 0,
> + .adc = 1,
> + .srot_split = 1,
> + .max_sensors = 11,
> +};
> +
> +const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
> + /* ----- SROT ------ */
> + /* VERSION */
> + [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
> + [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
> + [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
> + /* CTRL_OFFSET */
> + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
> + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
> + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
> +
> + /* ----- TM ------ */
> + /* UPPER_LOWER_INTERRUPT_CTRL */
> + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
> + /* Sn_UPPER_LOWER_STATUS_CTRL */
> + REG_BANK(LOW_THRESH, 0, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 0, 9),
> + REG_BANK(LOW_THRESH, 1, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 4, 0, 9),
> + REG_BANK(LOW_THRESH, 2, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 8, 0, 9),
> + REG_BANK(LOW_THRESH, 3, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 12, 0, 9),
> + REG_BANK(LOW_THRESH, 4, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 16, 0, 9),
> + REG_BANK(LOW_THRESH, 5, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 20, 0, 9),
> + REG_BANK(LOW_THRESH, 6, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 24, 0, 9),
> + REG_BANK(LOW_THRESH, 7, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 28, 0, 9),
> + REG_BANK(LOW_THRESH, 8, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 32, 0, 9),
> + REG_BANK(LOW_THRESH, 9, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 36, 0, 9),
> + REG_BANK(LOW_THRESH, 10, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 40, 0, 9),
> + REG_BANK(UP_THRESH, 0, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19),
> + REG_BANK(UP_THRESH, 1, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 4, 10, 19),
> + REG_BANK(UP_THRESH, 2, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 8, 10, 19),
> + REG_BANK(UP_THRESH, 3, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 12, 10, 19),
> + REG_BANK(UP_THRESH, 4, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 16, 10, 19),
> + REG_BANK(UP_THRESH, 5, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 20, 10, 19),
> + REG_BANK(UP_THRESH, 6, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 24, 10, 19),
> + REG_BANK(UP_THRESH, 7, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 28, 10, 19),
> + REG_BANK(UP_THRESH, 8, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 32, 10, 19),
> + REG_BANK(UP_THRESH, 9, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 36, 10, 19),
> + REG_BANK(UP_THRESH, 10, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF + 40, 10, 19),
> + /* Sn_STATUS */
> + REG_BANK(LAST_TEMP, 0, TM_Sn_STATUS_OFF, 0, 9),
> + REG_BANK(LAST_TEMP, 1, TM_Sn_STATUS_OFF + 4, 0, 9),
> + REG_BANK(LAST_TEMP, 2, TM_Sn_STATUS_OFF + 8, 0, 9),
> + REG_BANK(LAST_TEMP, 3, TM_Sn_STATUS_OFF + 12, 0, 9),
> + REG_BANK(LAST_TEMP, 4, TM_Sn_STATUS_OFF + 16, 0, 9),
> + REG_BANK(LAST_TEMP, 5, TM_Sn_STATUS_OFF + 20, 0, 9),
> + REG_BANK(LAST_TEMP, 6, TM_Sn_STATUS_OFF + 24, 0, 9),
> + REG_BANK(LAST_TEMP, 7, TM_Sn_STATUS_OFF + 28, 0, 9),
> + REG_BANK(LAST_TEMP, 8, TM_Sn_STATUS_OFF + 32, 0, 9),
> + REG_BANK(LAST_TEMP, 9, TM_Sn_STATUS_OFF + 36, 0, 9),
> + REG_BANK(LAST_TEMP, 10, TM_Sn_STATUS_OFF + 40, 0, 9),
> + REG_BANK(VALID, 0, TM_Sn_STATUS_OFF, 14, 14),
> + REG_BANK(VALID, 1, TM_Sn_STATUS_OFF + 4, 14, 14),
> + REG_BANK(VALID, 2, TM_Sn_STATUS_OFF + 8, 14, 14),
> + REG_BANK(VALID, 3, TM_Sn_STATUS_OFF + 12, 14, 14),
> + REG_BANK(VALID, 4, TM_Sn_STATUS_OFF + 16, 14, 14),
> + REG_BANK(VALID, 5, TM_Sn_STATUS_OFF + 20, 14, 14),
> + REG_BANK(VALID, 6, TM_Sn_STATUS_OFF + 24, 14, 14),
> + REG_BANK(VALID, 7, TM_Sn_STATUS_OFF + 28, 14, 14),
> + REG_BANK(VALID, 8, TM_Sn_STATUS_OFF + 32, 14, 14),
> + REG_BANK(VALID, 9, TM_Sn_STATUS_OFF + 36, 14, 14),
> + REG_BANK(VALID, 10, TM_Sn_STATUS_OFF + 40, 14, 14),
> + /* TRDY */
> + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
> +};
> +
> +static const struct tsens_ops ops_generic_v1 = {
> + .init = init_common,
> + .calibrate = calibrate_v1,
> + .get_temp = get_temp_tsens_valid,
> +};
> +
> +const struct tsens_plat_data data_tsens_v1 = {
> + .ops = &ops_generic_v1,
> + .feat = &tsens_v1_feat,
> + .fields = tsens_v1_regfields,
> +};
> diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
> index fc44cac31fa5..36b0b52db524 100644
> --- a/drivers/thermal/qcom/tsens.c
> +++ b/drivers/thermal/qcom/tsens.c
> @@ -63,6 +63,9 @@ static const struct of_device_id tsens_table[] = {
> }, {
> .compatible = "qcom,msm8996-tsens",
> .data = &data_8996,
> + }, {
> + .compatible = "qcom,tsens-v1",
> + .data = &data_tsens_v1,
> }, {
> .compatible = "qcom,tsens-v2",
> .data = &data_tsens_v2,
> diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
> index 4b3d71b26c97..4ed07e607cbc 100644
> --- a/drivers/thermal/qcom/tsens.h
> +++ b/drivers/thermal/qcom/tsens.h
> @@ -265,6 +265,9 @@ extern const struct tsens_plat_data data_8960;
> /* TSENS v0.1 targets */
> extern const struct tsens_plat_data data_8916, data_8974;
>
> +/* TSENS v1 targets */
> +extern const struct tsens_plat_data data_tsens_v1;
> +
> /* TSENS v2 targets */
> extern const struct tsens_plat_data data_8996, data_tsens_v2;
>
> --
> 2.17.1
>
On Thu, Feb 07, 2019 at 04:19:31PM +0530, Amit Kucheria wrote:
> On some TSENS IP, version is stored. Print that version at init.
>
> Signed-off-by: Amit Kucheria <[email protected]>
> ---
> drivers/thermal/qcom/tsens-common.c | 23 ++++++++++++++++++++++-
> 1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
> index aae3d71d7eed..39cd5733fd44 100644
> --- a/drivers/thermal/qcom/tsens-common.c
> +++ b/drivers/thermal/qcom/tsens-common.c
> @@ -121,7 +121,7 @@ int __init init_common(struct tsens_priv *priv)
> void __iomem *tm_base, *srot_base;
> struct device *dev = priv->dev;
> struct resource *res;
> - u32 enabled;
> + u32 enabled, maj_ver, min_ver;
> int ret, i, j;
> struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
>
> @@ -155,6 +155,27 @@ int __init init_common(struct tsens_priv *priv)
> if (IS_ERR(priv->tm_map))
> return PTR_ERR(priv->tm_map);
>
> + for (i = 0; i < MAX_REGFIELDS; i++) {
> + priv->rf[i] = NULL;
> + }
> +
> + /* alloc regmap_fields in srot_map */
> + if (priv->feat->ver_info) {
> + for (i = 0, j = VER_MAJOR; i < 2; i++, j++) {
> + priv->rf[j] = devm_regmap_field_alloc(dev, priv->srot_map,
> + priv->fields[j]);
> + if (IS_ERR(priv->rf[j]))
> + return PTR_ERR(priv->rf[j]);
> + }
> + ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver);
> + if (ret)
> + return ret;
> + ret = regmap_field_read(priv->rf[VER_MINOR], &min_ver);
> + if (ret)
> + return ret;
> + dev_info(dev, "version: %d.%d\n", maj_ver, min_ver);
Is this really needed? Printing stuff into kernel log during boot can
just add a lot of info that ends up just slowing down things. Besides,
if this info is important shouldnt be available somewhere else as the
kernel log is a circular buffer and eventually that line will get
wrapped up?
> + }
> +
> priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
> priv->fields[TSENS_EN]);
> if (IS_ERR(priv->rf[TSENS_EN]))
> --
> 2.17.1
>
On Wed, Feb 20, 2019 at 6:47 AM Eduardo Valentin <[email protected]> wrote:
>
> On Thu, Feb 07, 2019 at 04:19:31PM +0530, Amit Kucheria wrote:
> > On some TSENS IP, version is stored. Print that version at init.
> >
> > Signed-off-by: Amit Kucheria <[email protected]>
> > ---
> > drivers/thermal/qcom/tsens-common.c | 23 ++++++++++++++++++++++-
> > 1 file changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
> > index aae3d71d7eed..39cd5733fd44 100644
> > --- a/drivers/thermal/qcom/tsens-common.c
> > +++ b/drivers/thermal/qcom/tsens-common.c
> > @@ -121,7 +121,7 @@ int __init init_common(struct tsens_priv *priv)
> > void __iomem *tm_base, *srot_base;
> > struct device *dev = priv->dev;
> > struct resource *res;
> > - u32 enabled;
> > + u32 enabled, maj_ver, min_ver;
> > int ret, i, j;
> > struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
> >
> > @@ -155,6 +155,27 @@ int __init init_common(struct tsens_priv *priv)
> > if (IS_ERR(priv->tm_map))
> > return PTR_ERR(priv->tm_map);
> >
> > + for (i = 0; i < MAX_REGFIELDS; i++) {
> > + priv->rf[i] = NULL;
> > + }
> > +
> > + /* alloc regmap_fields in srot_map */
> > + if (priv->feat->ver_info) {
> > + for (i = 0, j = VER_MAJOR; i < 2; i++, j++) {
> > + priv->rf[j] = devm_regmap_field_alloc(dev, priv->srot_map,
> > + priv->fields[j]);
> > + if (IS_ERR(priv->rf[j]))
> > + return PTR_ERR(priv->rf[j]);
> > + }
> > + ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver);
> > + if (ret)
> > + return ret;
> > + ret = regmap_field_read(priv->rf[VER_MINOR], &min_ver);
> > + if (ret)
> > + return ret;
> > + dev_info(dev, "version: %d.%d\n", maj_ver, min_ver);
>
> Is this really needed? Printing stuff into kernel log during boot can
> just add a lot of info that ends up just slowing down things. Besides,
> if this info is important shouldnt be available somewhere else as the
> kernel log is a circular buffer and eventually that line will get
> wrapped up?
Fair point, I'll remove this statement and dump this into debugfs for
which I'll send a separate series adding debugfs support.
On Wed, Feb 20, 2019 at 6:39 AM Eduardo Valentin <[email protected]> wrote:
>
> On Thu, Feb 07, 2019 at 04:19:41PM +0530, Amit Kucheria wrote:
> > qcs404 has 10 sensors connected to the single TSENS IP. Define a thermal
> > zone for each of those sensors to expose the temperature of each zone.
> >
> > Signed-off-by: Amit Kucheria <[email protected]>
> > ---
> > arch/arm64/boot/dts/qcom/qcs404.dtsi | 243 +++++++++++++++++++++++++++
> > 1 file changed, 243 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
> > index 57d14d8f0c90..ca99c45864df 100644
> > --- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
> > @@ -3,6 +3,7 @@
> >
> > #include <dt-bindings/interrupt-controller/arm-gic.h>
> > #include <dt-bindings/clock/qcom,gcc-qcs404.h>
> > +#include <dt-bindings/thermal/thermal.h>
> >
> > / {
> > interrupt-parent = <&intc>;
> > @@ -30,6 +31,7 @@
> > reg = <0x100>;
> > enable-method = "psci";
> > next-level-cache = <&L2_0>;
> > + #cooling-cells= <2>;
> > };
> >
> > CPU1: cpu@101 {
> > @@ -38,6 +40,7 @@
> > reg = <0x101>;
> > enable-method = "psci";
> > next-level-cache = <&L2_0>;
> > + #cooling-cells= <2>;
> > };
> >
> > CPU2: cpu@102 {
> > @@ -46,6 +49,7 @@
> > reg = <0x102>;
> > enable-method = "psci";
> > next-level-cache = <&L2_0>;
> > + #cooling-cells= <2>;
> > };
> >
> > CPU3: cpu@103 {
> > @@ -54,6 +58,7 @@
> > reg = <0x103>;
> > enable-method = "psci";
> > next-level-cache = <&L2_0>;
> > + #cooling-cells= <2>;
> > };
> >
> > L2_0: l2-cache {
> > @@ -507,4 +512,242 @@
> > #interrupt-cells = <2>;
> > };
> > };
> > +
> > + thermal-zones {
>
> There are several zones with passive trips and no cooling maps.
Indeed. The policy bits are still a WIP and in some cases the
throttling is handled by someone in userspace. But I'd like to expose
at least the temperatures at each of the sensors to make it easier for
others to use this information. See my reply to the cover letter.
Regards,
Amit
> > + aoss-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 0>;
> > +
> > + trips {
> > + aoss_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + aoss_crit: aoss_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + };
> > +
> > + dsp-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 1>;
> > +
> > + trips {
> > + dsp_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + dsp_crit: dsp_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + };
> > +
> > + lpass-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 2>;
> > +
> > + trips {
> > + lpass_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + lpass_crit: lpass_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + };
> > +
> > + wlan-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 3>;
> > +
> > + trips {
> > + wlan_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + wlan_crit: wlan_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + };
> > +
> > + cluster-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 4>;
> > +
> > + trips {
> > + cluster_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + cluster_crit: cluster_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + };
> > +
> > + cpu0-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 5>;
> > +
> > + trips {
> > + cpu0_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + cpu0_crit: cpu_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + cooling-maps {
> > + map0 {
> > + trip = <&cpu0_alert0>;
> > + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> > + };
> > + };
> > + };
> > +
> > + cpu1-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 6>;
> > +
> > + trips {
> > + cpu1_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + cpu1_crit: cpu_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + cooling-maps {
> > + map0 {
> > + trip = <&cpu1_alert0>;
> > + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> > + };
> > + };
> > + };
> > +
> > + cpu2-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 7>;
> > +
> > + trips {
> > + cpu2_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + cpu2_crit: cpu_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + cooling-maps {
> > + map0 {
> > + trip = <&cpu2_alert0>;
> > + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> > + };
> > + };
> > + };
> > +
> > + cpu3-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 8>;
> > +
> > + trips {
> > + cpu3_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + cpu3_crit: cpu_crit {
> > + temperature = <110000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + cooling-maps {
> > + map0 {
> > + trip = <&cpu3_alert0>;
> > + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> > + };
> > + };
> > + };
> > +
> > + gpu-thermal {
> > + polling-delay-passive = <250>;
> > + polling-delay = <1000>;
> > +
> > + thermal-sensors = <&tsens 9>;
> > +
> > + trips {
> > + gpu_alert0: trip-point@0 {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "passive";
> > + };
> > + gpu_crit: gpu_crit {
> > + temperature = <95000>;
> > + hysteresis = <2000>;
> > + type = "critical";
> > + };
> > + };
> > + };
> > + };
> > };
> > --
> > 2.17.1
> >
On Thu, 7 Feb 2019 16:19:38 +0530, Amit Kucheria wrote:
> qcs404 uses v1 of the TSENS IP block. Create a fallback DT property
> "qcom,tsens-v1" to gather common code
>
> Signed-off-by: Amit Kucheria <[email protected]>
> ---
> .../devicetree/bindings/thermal/qcom-tsens.txt | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
Reviewed-by: Rob Herring <[email protected]>