Everyone:
This series contains patches adding support for HWMON integration, bug
fixes and general improvements (hopefully) for TMU driver I made while
working on it on i.MX8MQ.
Feedback is welcome!
Thanks,
Andrey Smirnov
Changes since [v7]:
- Rebased on top of 12/05 linux-next
Changes since [v6]:
- Rebased on top of Zhang's "next" branch
- Added "thermal: qoriq: Drop unnecessary drvdata cleanup"
Changes since [v5]
- Rebased on recent linux-next, dropped "thermal: qoriq: Remove
unnecessary DT node is NULL check" since it is already in the
tree
- Dropped dependency on [rfc]
Changes since [v4]
- Collected Tested-by from Lucas
- Collected Reviewed-by from Daniel
- Converted "thermal: qoriq: Enable all sensors before registering
them" to use if instead of switch statement for error checking
Changes since [v3]
- Series reabse on top of [rfc]
- Fixed incorrect goto label in "thermal: qoriq: Pass data to
qoriq_tmu_calibration()"
- Added REGS_TRITSR() register description to "thermal: qoriq: Do
not report invalid temperature reading"
- Reworded commit message of "thermal: qoriq: Remove unnecessary
DT node is NULL check"
Changes since [v2]
- Patches rebased on v5.1-rc1
Changes since [v1]
- Rebased on "linus" branch of
git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
that included latest chagnes adding multi-sensors support
- Dropped
thermal: qoriq: Add support for multiple thremal sites
thermal: qoriq: Be more strict when parsing
thermal: qoriq: Simplify error handling in qoriq_tmu_get_sensor_id()
since they are no longer relevant
- Added
thermal: qoriq: Don't store struct thermal_zone_device reference
thermal: qoriq: Add local struct qoriq_sensor pointer
thermal: qoriq: Embed per-sensor data into struct qoriq_tmu_data
thermal: qoriq: Pass data to qoriq_tmu_register_tmu_zone() directly
to simplify latest codebase
- Changed "thermal: qoriq: Do not report invalid temperature
reading" to use regmap_read_poll_timeout() to make sure that
tmu_get_temp() waits for fist sample to be ready before
reporting it. This case is triggered on my setup if
qoriq_thermal is compiled as a module
[v1] lore.kernel.org/lkml/[email protected]
[v2] lore.kernel.org/lkml/[email protected]
[v3] lore.kernel.org/lkml/[email protected]
[v4] lore.kernel.org/lkml/[email protected]
[v5] lore.kernel.org/lkml/[email protected]
[v6] lore.kernel.org/lkml/[email protected]
[v7] lore.kernel.org/lkml/[email protected]
[rfc] lore.kernel.org/lkml/[email protected]
Andrey Smirnov (12):
thermal: qoriq: Add local struct device pointer
thermal: qoriq: Don't store struct thermal_zone_device reference
thermal: qoriq: Add local struct qoriq_sensor pointer
thermal: qoriq: Embed per-sensor data into struct qoriq_tmu_data
thermal: qoriq: Pass data to qoriq_tmu_register_tmu_zone() directly
thermal: qoriq: Pass data to qoriq_tmu_calibration() directly
thermal: qoriq: Drop unnecessary drvdata cleanup
thermal: qoriq: Convert driver to use regmap API
thermal: qoriq: Enable all sensors before registering them
thermal: qoriq: Do not report invalid temperature reading
thermal_hwmon: Add devres wrapper for thermal_add_hwmon_sysfs()
thermal: qoriq: Add hwmon support
drivers/thermal/qoriq_thermal.c | 336 +++++++++++++++-----------------
drivers/thermal/thermal_hwmon.c | 28 +++
drivers/thermal/thermal_hwmon.h | 7 +
3 files changed, 195 insertions(+), 176 deletions(-)
--
2.21.0
Use a local "struct device *dev" for brevity. No functional change
intended.
Signed-off-by: Andrey Smirnov <[email protected]>
Acked-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 45e9fcb172cc..dd47b31aeecc 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -262,8 +262,9 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
u32 ver;
struct qoriq_tmu_data *data;
struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
- data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data),
+ data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -274,17 +275,17 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
data->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->regs)) {
- dev_err(&pdev->dev, "Failed to get memory region\n");
+ dev_err(dev, "Failed to get memory region\n");
return PTR_ERR(data->regs);
}
- data->clk = devm_clk_get_optional(&pdev->dev, NULL);
+ data->clk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(data->clk))
return PTR_ERR(data->clk);
ret = clk_prepare_enable(data->clk);
if (ret) {
- dev_err(&pdev->dev, "Failed to enable clock\n");
+ dev_err(dev, "Failed to enable clock\n");
return ret;
}
@@ -302,7 +303,7 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
ret = qoriq_tmu_register_tmu_zone(pdev);
if (ret < 0) {
- dev_err(&pdev->dev, "Failed to register sensors\n");
+ dev_err(dev, "Failed to register sensors\n");
ret = -ENODEV;
goto err;
}
--
2.21.0
Add local struct qoriq_sensor pointer in qoriq_tmu_register_tmu_zone()
for brevity.
Signed-off-by: Andrey Smirnov <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Zhang Rui <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 2f2f5ffa8f26..61733d820e1b 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -162,18 +162,22 @@ static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
for (id = 0; id < SITES_MAX; id++) {
struct thermal_zone_device *tzd;
+ struct qoriq_sensor *sensor;
int ret;
- qdata->sensor[id] = devm_kzalloc(&pdev->dev,
- sizeof(struct qoriq_sensor), GFP_KERNEL);
+ sensor = devm_kzalloc(&pdev->dev,
+ sizeof(struct qoriq_sensor),
+ GFP_KERNEL);
if (!qdata->sensor[id])
return -ENOMEM;
- qdata->sensor[id]->id = id;
- qdata->sensor[id]->qdata = qdata;
+ qdata->sensor[id] = sensor;
+
+ sensor->id = id;
+ sensor->qdata = qdata;
tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id,
- qdata->sensor[id],
+ sensor,
&tmu_tz_ops);
ret = PTR_ERR_OR_ZERO(tzd);
if (ret) {
--
2.21.0
Embed per-sensor data into struct qoriq_tmu_data so we can drop the
code allocating it. This also allows us to get rid of per-sensor back
reference to struct qoriq_tmu_data since now its address can be
calculated using container_of().
Signed-off-by: Andrey Smirnov <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Zhang Rui <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 61733d820e1b..9886daf8ac97 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -104,13 +104,10 @@ struct qoriq_tmu_regs_v2 {
u32 ttrcr[4]; /* Temperature Range Control Register */
};
-struct qoriq_tmu_data;
-
/*
* Thermal zone data
*/
struct qoriq_sensor {
- struct qoriq_tmu_data *qdata;
int id;
};
@@ -120,9 +117,14 @@ struct qoriq_tmu_data {
struct qoriq_tmu_regs_v2 __iomem *regs_v2;
struct clk *clk;
bool little_endian;
- struct qoriq_sensor *sensor[SITES_MAX];
+ struct qoriq_sensor sensor[SITES_MAX];
};
+static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s)
+{
+ return container_of(s, struct qoriq_tmu_data, sensor[s->id]);
+}
+
static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
{
if (p->little_endian)
@@ -142,7 +144,7 @@ static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr)
static int tmu_get_temp(void *p, int *temp)
{
struct qoriq_sensor *qsensor = p;
- struct qoriq_tmu_data *qdata = qsensor->qdata;
+ struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
u32 val;
val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
@@ -162,19 +164,10 @@ static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
for (id = 0; id < SITES_MAX; id++) {
struct thermal_zone_device *tzd;
- struct qoriq_sensor *sensor;
+ struct qoriq_sensor *sensor = &qdata->sensor[id];
int ret;
- sensor = devm_kzalloc(&pdev->dev,
- sizeof(struct qoriq_sensor),
- GFP_KERNEL);
- if (!qdata->sensor[id])
- return -ENOMEM;
-
- qdata->sensor[id] = sensor;
-
sensor->id = id;
- sensor->qdata = qdata;
tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id,
sensor,
--
2.21.0
Driver data of underlying struct device will be set to NULL by Linux's
driver infrastructure. Clearing it here is unnecessary.
Signed-off-by: Andrey Smirnov <[email protected]>
Reviewed-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index de8c9cd115aa..11749c673b3b 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -327,8 +327,6 @@ static int qoriq_tmu_remove(struct platform_device *pdev)
clk_disable_unprepare(data->clk);
- platform_set_drvdata(pdev, NULL);
-
return 0;
}
--
2.21.0
Tmu_get_temp will get called as a part of sensor registration via
devm_thermal_zone_of_sensor_register(). To prevent it from retruning
bogus data we need to enable sensor monitoring before that. Looking at
the datasheet (i.MX8MQ RM) there doesn't seem to be any harm in
enabling them all, so, for the sake of simplicity, change the code to
do just that.
Signed-off-by: Andrey Smirnov <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 31 ++++++++++++-------------------
1 file changed, 12 insertions(+), 19 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 6227c940b9b0..6c5e53ea7711 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -29,6 +29,7 @@
#define TMR_DISABLE 0x0
#define TMR_ME 0x80000000
#define TMR_ALPF 0x0c000000
+#define TMR_MSITE_ALL GENMASK(15, 0)
#define REGS_TMTMIR 0x008 /* Temperature measurement interval Register */
#define TMTMIR_DEFAULT 0x0000000f
@@ -93,7 +94,15 @@ static const struct thermal_zone_of_device_ops tmu_tz_ops = {
static int qoriq_tmu_register_tmu_zone(struct device *dev,
struct qoriq_tmu_data *qdata)
{
- int id, sites = 0;
+ int id;
+
+ if (qdata->ver == TMU_VER1) {
+ regmap_write(qdata->regmap, REGS_TMR,
+ TMR_MSITE_ALL | TMR_ME | TMR_ALPF);
+ } else {
+ regmap_write(qdata->regmap, REGS_V2_TMSR, TMR_MSITE_ALL);
+ regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2);
+ }
for (id = 0; id < SITES_MAX; id++) {
struct thermal_zone_device *tzd;
@@ -109,25 +118,9 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev,
if (ret) {
if (ret == -ENODEV)
continue;
- else
- return ret;
- }
- if (qdata->ver == TMU_VER1)
- sites |= 0x1 << (15 - id);
- else
- sites |= 0x1 << id;
- }
-
- /* Enable monitoring */
- if (sites != 0) {
- if (qdata->ver == TMU_VER1) {
- regmap_write(qdata->regmap, REGS_TMR,
- sites | TMR_ME | TMR_ALPF);
- } else {
- regmap_write(qdata->regmap, REGS_V2_TMSR, sites);
- regmap_write(qdata->regmap, REGS_TMR,
- TMR_ME | TMR_ALPF_V2);
+ regmap_write(qdata->regmap, REGS_TMR, TMR_DISABLE);
+ return ret;
}
}
--
2.21.0
Expose thermal readings as a HWMON device, so that it could be
accessed using lm-sensors.
Signed-off-by: Andrey Smirnov <[email protected]>
Reviewed-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index b684d3ceda69..b75d34e07da5 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -13,6 +13,7 @@
#include <linux/thermal.h>
#include "thermal_core.h"
+#include "thermal_hwmon.h"
#define SITES_MAX 16
#define TMR_DISABLE 0x0
@@ -139,6 +140,11 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev,
regmap_write(qdata->regmap, REGS_TMR, TMR_DISABLE);
return ret;
}
+
+ if (devm_thermal_add_hwmon_sysfs(tzd))
+ dev_warn(dev,
+ "Failed to add hwmon sysfs attributes\n");
+
}
return 0;
--
2.21.0
Add devres wrapper for thermal_add_hwmon_sysfs() to simplify driver
code.
Signed-off-by: Andrey Smirnov <[email protected]>
Reviewed-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/thermal_hwmon.c | 28 ++++++++++++++++++++++++++++
drivers/thermal/thermal_hwmon.h | 7 +++++++
2 files changed, 35 insertions(+)
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index dd5d8ee37928..c8d2620f2e42 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -248,3 +248,31 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
kfree(hwmon);
}
EXPORT_SYMBOL_GPL(thermal_remove_hwmon_sysfs);
+
+static void devm_thermal_hwmon_release(struct device *dev, void *res)
+{
+ thermal_remove_hwmon_sysfs(*(struct thermal_zone_device **)res);
+}
+
+int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
+{
+ struct thermal_zone_device **ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_thermal_hwmon_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = thermal_add_hwmon_sysfs(tz);
+ if (ret) {
+ devres_free(ptr);
+ return ret;
+ }
+
+ *ptr = tz;
+ devres_add(&tz->device, ptr);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_thermal_add_hwmon_sysfs);
diff --git a/drivers/thermal/thermal_hwmon.h b/drivers/thermal/thermal_hwmon.h
index a160b9d62dd0..1a9d65f6a6a8 100644
--- a/drivers/thermal/thermal_hwmon.h
+++ b/drivers/thermal/thermal_hwmon.h
@@ -17,6 +17,7 @@
#ifdef CONFIG_THERMAL_HWMON
int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
+int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz);
#else
static inline int
@@ -25,6 +26,12 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
return 0;
}
+static inline int
+devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
+{
+ return 0;
+}
+
static inline void
thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
{
--
2.21.0
Before returning measured temperature data to upper layer we need to
make sure that the reading was marked as "valid" to avoid reporting
bogus data.
Signed-off-by: Andrey Smirnov <[email protected]>
Reviewed-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 6c5e53ea7711..b684d3ceda69 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -48,6 +48,7 @@
#define REGS_TRITSR(n) (0x100 + 16 * (n)) /* Immediate Temperature
* Site Register
*/
+#define TRITSR_V BIT(31)
#define REGS_TTRnCR(n) (0xf10 + 4 * (n)) /* Temperature Range n
* Control Register
*/
@@ -80,8 +81,24 @@ static int tmu_get_temp(void *p, int *temp)
struct qoriq_sensor *qsensor = p;
struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
u32 val;
+ /*
+ * REGS_TRITSR(id) has the following layout:
+ *
+ * 31 ... 7 6 5 4 3 2 1 0
+ * V TEMP
+ *
+ * Where V bit signifies if the measurement is ready and is
+ * within sensor range. TEMP is an 8 bit value representing
+ * temperature in C.
+ */
+ if (regmap_read_poll_timeout(qdata->regmap,
+ REGS_TRITSR(qsensor->id),
+ val,
+ val & TRITSR_V,
+ USEC_PER_MSEC,
+ 10 * USEC_PER_MSEC))
+ return -ENODATA;
- regmap_read(qdata->regmap, REGS_TRITSR(qsensor->id), &val);
*temp = (val & 0xff) * 1000;
return 0;
--
2.21.0
Convert driver to use regmap API, drop custom LE/BE IO helpers and
simplify bit manipulation using regmap_update_bits(). This also allows
us to convert some register initialization to use loops and adds
convenient debug access to TMU registers via debugfs.
Signed-off-by: Andrey Smirnov <[email protected]>
Reviewed-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
Yuantian, Anson:
I don't have access to Layerscape HW that has v2 register layout, so
if you could give this patch a try and verify that I got the
'qoriq_yes_ranges' right, I'd really appreciate it.
Thanks,
Andrey Smirnov
drivers/thermal/qoriq_thermal.c | 228 ++++++++++++++------------------
1 file changed, 98 insertions(+), 130 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 11749c673b3b..6227c940b9b0 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -9,6 +9,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/thermal.h>
#include "thermal_core.h"
@@ -24,85 +25,35 @@
#define TMU_VER1 0x1
#define TMU_VER2 0x2
-/*
- * QorIQ TMU Registers
- */
-struct qoriq_tmu_site_regs {
- u32 tritsr; /* Immediate Temperature Site Register */
- u32 tratsr; /* Average Temperature Site Register */
- u8 res0[0x8];
-};
+#define REGS_TMR 0x000 /* Mode Register */
+#define TMR_DISABLE 0x0
+#define TMR_ME 0x80000000
+#define TMR_ALPF 0x0c000000
-struct qoriq_tmu_regs_v1 {
- u32 tmr; /* Mode Register */
- u32 tsr; /* Status Register */
- u32 tmtmir; /* Temperature measurement interval Register */
- u8 res0[0x14];
- u32 tier; /* Interrupt Enable Register */
- u32 tidr; /* Interrupt Detect Register */
- u32 tiscr; /* Interrupt Site Capture Register */
- u32 ticscr; /* Interrupt Critical Site Capture Register */
- u8 res1[0x10];
- u32 tmhtcrh; /* High Temperature Capture Register */
- u32 tmhtcrl; /* Low Temperature Capture Register */
- u8 res2[0x8];
- u32 tmhtitr; /* High Temperature Immediate Threshold */
- u32 tmhtatr; /* High Temperature Average Threshold */
- u32 tmhtactr; /* High Temperature Average Crit Threshold */
- u8 res3[0x24];
- u32 ttcfgr; /* Temperature Configuration Register */
- u32 tscfgr; /* Sensor Configuration Register */
- u8 res4[0x78];
- struct qoriq_tmu_site_regs site[SITES_MAX];
- u8 res5[0x9f8];
- u32 ipbrr0; /* IP Block Revision Register 0 */
- u32 ipbrr1; /* IP Block Revision Register 1 */
- u8 res6[0x310];
- u32 ttrcr[4]; /* Temperature Range Control Register */
-};
+#define REGS_TMTMIR 0x008 /* Temperature measurement interval Register */
+#define TMTMIR_DEFAULT 0x0000000f
-struct qoriq_tmu_regs_v2 {
- u32 tmr; /* Mode Register */
- u32 tsr; /* Status Register */
- u32 tmsr; /* monitor site register */
- u32 tmtmir; /* Temperature measurement interval Register */
- u8 res0[0x10];
- u32 tier; /* Interrupt Enable Register */
- u32 tidr; /* Interrupt Detect Register */
- u8 res1[0x8];
- u32 tiiscr; /* interrupt immediate site capture register */
- u32 tiascr; /* interrupt average site capture register */
- u32 ticscr; /* Interrupt Critical Site Capture Register */
- u32 res2;
- u32 tmhtcr; /* monitor high temperature capture register */
- u32 tmltcr; /* monitor low temperature capture register */
- u32 tmrtrcr; /* monitor rising temperature rate capture register */
- u32 tmftrcr; /* monitor falling temperature rate capture register */
- u32 tmhtitr; /* High Temperature Immediate Threshold */
- u32 tmhtatr; /* High Temperature Average Threshold */
- u32 tmhtactr; /* High Temperature Average Crit Threshold */
- u32 res3;
- u32 tmltitr; /* monitor low temperature immediate threshold */
- u32 tmltatr; /* monitor low temperature average threshold register */
- u32 tmltactr; /* monitor low temperature average critical threshold */
- u32 res4;
- u32 tmrtrctr; /* monitor rising temperature rate critical threshold */
- u32 tmftrctr; /* monitor falling temperature rate critical threshold*/
- u8 res5[0x8];
- u32 ttcfgr; /* Temperature Configuration Register */
- u32 tscfgr; /* Sensor Configuration Register */
- u8 res6[0x78];
- struct qoriq_tmu_site_regs site[SITES_MAX];
- u8 res7[0x9f8];
- u32 ipbrr0; /* IP Block Revision Register 0 */
- u32 ipbrr1; /* IP Block Revision Register 1 */
- u8 res8[0x300];
- u32 teumr0;
- u32 teumr1;
- u32 teumr2;
- u32 res9;
- u32 ttrcr[4]; /* Temperature Range Control Register */
-};
+#define REGS_V2_TMSR 0x008 /* monitor site register */
+
+#define REGS_V2_TMTMIR 0x00c /* Temperature measurement interval Register */
+
+#define REGS_TIER 0x020 /* Interrupt Enable Register */
+#define TIER_DISABLE 0x0
+
+
+#define REGS_TTCFGR 0x080 /* Temperature Configuration Register */
+#define REGS_TSCFGR 0x084 /* Sensor Configuration Register */
+
+#define REGS_TRITSR(n) (0x100 + 16 * (n)) /* Immediate Temperature
+ * Site Register
+ */
+#define REGS_TTRnCR(n) (0xf10 + 4 * (n)) /* Temperature Range n
+ * Control Register
+ */
+#define REGS_IPBRR(n) (0xbf8 + 4 * (n)) /* IP Block Revision
+ * Register n
+ */
+#define REGS_V2_TEUMR(n) (0xf00 + 4 * (n))
/*
* Thermal zone data
@@ -113,10 +64,8 @@ struct qoriq_sensor {
struct qoriq_tmu_data {
int ver;
- struct qoriq_tmu_regs_v1 __iomem *regs;
- struct qoriq_tmu_regs_v2 __iomem *regs_v2;
+ struct regmap *regmap;
struct clk *clk;
- bool little_endian;
struct qoriq_sensor sensor[SITES_MAX];
};
@@ -125,29 +74,13 @@ static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s)
return container_of(s, struct qoriq_tmu_data, sensor[s->id]);
}
-static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
-{
- if (p->little_endian)
- iowrite32(val, addr);
- else
- iowrite32be(val, addr);
-}
-
-static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr)
-{
- if (p->little_endian)
- return ioread32(addr);
- else
- return ioread32be(addr);
-}
-
static int tmu_get_temp(void *p, int *temp)
{
struct qoriq_sensor *qsensor = p;
struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
u32 val;
- val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
+ regmap_read(qdata->regmap, REGS_TRITSR(qsensor->id), &val);
*temp = (val & 0xff) * 1000;
return 0;
@@ -189,12 +122,12 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev,
/* Enable monitoring */
if (sites != 0) {
if (qdata->ver == TMU_VER1) {
- tmu_write(qdata, sites | TMR_ME | TMR_ALPF,
- &qdata->regs->tmr);
+ regmap_write(qdata->regmap, REGS_TMR,
+ sites | TMR_ME | TMR_ALPF);
} else {
- tmu_write(qdata, sites, &qdata->regs_v2->tmsr);
- tmu_write(qdata, TMR_ME | TMR_ALPF_V2,
- &qdata->regs_v2->tmr);
+ regmap_write(qdata->regmap, REGS_V2_TMSR, sites);
+ regmap_write(qdata->regmap, REGS_TMR,
+ TMR_ME | TMR_ALPF_V2);
}
}
@@ -223,7 +156,7 @@ static int qoriq_tmu_calibration(struct device *dev,
/* Init temperature range registers */
for (i = 0; i < len; i++)
- tmu_write(data, range[i], &data->regs->ttrcr[i]);
+ regmap_write(data->regmap, REGS_TTRnCR(i), range[i]);
calibration = of_get_property(np, "fsl,tmu-calibration", &len);
if (calibration == NULL || len % 8) {
@@ -233,9 +166,9 @@ static int qoriq_tmu_calibration(struct device *dev,
for (i = 0; i < len; i += 8, calibration += 2) {
val = of_read_number(calibration, 1);
- tmu_write(data, val, &data->regs->ttcfgr);
+ regmap_write(data->regmap, REGS_TTCFGR, val);
val = of_read_number(calibration + 1, 1);
- tmu_write(data, val, &data->regs->tscfgr);
+ regmap_write(data->regmap, REGS_TSCFGR, val);
}
return 0;
@@ -244,20 +177,40 @@ static int qoriq_tmu_calibration(struct device *dev,
static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
{
/* Disable interrupt, using polling instead */
- tmu_write(data, TIER_DISABLE, &data->regs->tier);
+ regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
/* Set update_interval */
+
if (data->ver == TMU_VER1) {
- tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir);
+ regmap_write(data->regmap, REGS_TMTMIR, TMTMIR_DEFAULT);
} else {
- tmu_write(data, TMTMIR_DEFAULT, &data->regs_v2->tmtmir);
- tmu_write(data, TEUMR0_V2, &data->regs_v2->teumr0);
+ regmap_write(data->regmap, REGS_V2_TMTMIR, TMTMIR_DEFAULT);
+ regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
}
/* Disable monitoring */
- tmu_write(data, TMR_DISABLE, &data->regs->tmr);
+ regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
}
+static const struct regmap_range qoriq_yes_ranges[] = {
+ regmap_reg_range(REGS_TMR, REGS_TSCFGR),
+ regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
+ regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
+ regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
+ /* Read only registers below */
+ regmap_reg_range(REGS_TRITSR(0), REGS_TRITSR(15)),
+};
+
+static const struct regmap_access_table qoriq_wr_table = {
+ .yes_ranges = qoriq_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges) - 1,
+};
+
+static const struct regmap_access_table qoriq_rd_table = {
+ .yes_ranges = qoriq_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges),
+};
+
static int qoriq_tmu_probe(struct platform_device *pdev)
{
int ret;
@@ -265,18 +218,37 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
struct qoriq_tmu_data *data;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
+ const bool little_endian = of_property_read_bool(np, "little-endian");
+ const enum regmap_endian format_endian =
+ little_endian ? REGMAP_ENDIAN_LITTLE : REGMAP_ENDIAN_BIG;
+ const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .rd_table = &qoriq_rd_table,
+ .wr_table = &qoriq_wr_table,
+ .val_format_endian = format_endian,
+ .max_register = SZ_4K,
+ };
+ void __iomem *base;
data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
- data->little_endian = of_property_read_bool(np, "little-endian");
-
- data->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(data->regs)) {
+ base = devm_platform_ioremap_resource(pdev, 0);
+ ret = PTR_ERR_OR_ZERO(base);
+ if (ret) {
dev_err(dev, "Failed to get memory region\n");
- return PTR_ERR(data->regs);
+ return ret;
+ }
+
+ data->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
+ ret = PTR_ERR_OR_ZERO(data->regmap);
+ if (ret) {
+ dev_err(dev, "Failed to init regmap (%d)\n", ret);
+ return ret;
}
data->clk = devm_clk_get_optional(dev, NULL);
@@ -290,10 +262,12 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
}
/* version register offset at: 0xbf8 on both v1 and v2 */
- ver = tmu_read(data, &data->regs->ipbrr0);
+ ret = regmap_read(data->regmap, REGS_IPBRR(0), &ver);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to read IP block version\n");
+ return ret;
+ }
data->ver = (ver >> 8) & 0xff;
- if (data->ver == TMU_VER2)
- data->regs_v2 = (void __iomem *)data->regs;
qoriq_tmu_init_device(data); /* TMU initialization */
@@ -323,7 +297,7 @@ static int qoriq_tmu_remove(struct platform_device *pdev)
struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
/* Disable monitoring */
- tmu_write(data, TMR_DISABLE, &data->regs->tmr);
+ regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
clk_disable_unprepare(data->clk);
@@ -332,13 +306,12 @@ static int qoriq_tmu_remove(struct platform_device *pdev)
static int __maybe_unused qoriq_tmu_suspend(struct device *dev)
{
- u32 tmr;
struct qoriq_tmu_data *data = dev_get_drvdata(dev);
+ int ret;
- /* Disable monitoring */
- tmr = tmu_read(data, &data->regs->tmr);
- tmr &= ~TMR_ME;
- tmu_write(data, tmr, &data->regs->tmr);
+ ret = regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, 0);
+ if (ret)
+ return ret;
clk_disable_unprepare(data->clk);
@@ -347,7 +320,6 @@ static int __maybe_unused qoriq_tmu_suspend(struct device *dev)
static int __maybe_unused qoriq_tmu_resume(struct device *dev)
{
- u32 tmr;
int ret;
struct qoriq_tmu_data *data = dev_get_drvdata(dev);
@@ -356,11 +328,7 @@ static int __maybe_unused qoriq_tmu_resume(struct device *dev)
return ret;
/* Enable monitoring */
- tmr = tmu_read(data, &data->regs->tmr);
- tmr |= TMR_ME;
- tmu_write(data, tmr, &data->regs->tmr);
-
- return 0;
+ return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME);
}
static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
--
2.21.0
Struct thermal_zone_device reference stored as sensor's private data
isn't really used anywhere in the code. Drop it.
Signed-off-by: Andrey Smirnov <[email protected]>
Acked-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index dd47b31aeecc..2f2f5ffa8f26 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -110,7 +110,6 @@ struct qoriq_tmu_data;
* Thermal zone data
*/
struct qoriq_sensor {
- struct thermal_zone_device *tzd;
struct qoriq_tmu_data *qdata;
int id;
};
@@ -162,6 +161,9 @@ static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
int id, sites = 0;
for (id = 0; id < SITES_MAX; id++) {
+ struct thermal_zone_device *tzd;
+ int ret;
+
qdata->sensor[id] = devm_kzalloc(&pdev->dev,
sizeof(struct qoriq_sensor), GFP_KERNEL);
if (!qdata->sensor[id])
@@ -169,13 +171,16 @@ static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
qdata->sensor[id]->id = id;
qdata->sensor[id]->qdata = qdata;
- qdata->sensor[id]->tzd = devm_thermal_zone_of_sensor_register(
- &pdev->dev, id, qdata->sensor[id], &tmu_tz_ops);
- if (IS_ERR(qdata->sensor[id]->tzd)) {
- if (PTR_ERR(qdata->sensor[id]->tzd) == -ENODEV)
+
+ tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id,
+ qdata->sensor[id],
+ &tmu_tz_ops);
+ ret = PTR_ERR_OR_ZERO(tzd);
+ if (ret) {
+ if (ret == -ENODEV)
continue;
else
- return PTR_ERR(qdata->sensor[id]->tzd);
+ return ret;
}
if (qdata->ver == TMU_VER1)
--
2.21.0
Pass all necessary data to qoriq_tmu_register_tmu_zone() directly
instead of passing a platform device and then deriving it. This is
done as a first step to simplify resource deallocation code.
Signed-off-by: Andrey Smirnov <[email protected]>
Acked-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 9886daf8ac97..f024ac68e2ed 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -157,9 +157,9 @@ static const struct thermal_zone_of_device_ops tmu_tz_ops = {
.get_temp = tmu_get_temp,
};
-static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
+static int qoriq_tmu_register_tmu_zone(struct device *dev,
+ struct qoriq_tmu_data *qdata)
{
- struct qoriq_tmu_data *qdata = platform_get_drvdata(pdev);
int id, sites = 0;
for (id = 0; id < SITES_MAX; id++) {
@@ -169,7 +169,7 @@ static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
sensor->id = id;
- tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id,
+ tzd = devm_thermal_zone_of_sensor_register(dev, id,
sensor,
&tmu_tz_ops);
ret = PTR_ERR_OR_ZERO(tzd);
@@ -303,7 +303,7 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
if (ret < 0)
goto err;
- ret = qoriq_tmu_register_tmu_zone(pdev);
+ ret = qoriq_tmu_register_tmu_zone(dev, data);
if (ret < 0) {
dev_err(dev, "Failed to register sensors\n");
ret = -ENODEV;
--
2.21.0
We can simplify error cleanup code if instead of passing a "struct
platform_device *" to qoriq_tmu_calibration() and deriving a bunch of
pointers from it, we pass those pointers directly. This way we won't
be force to call platform_set_drvdata() as early in qoriq_tmu_probe()
and need to have "platform_set_drvdata(pdev, NULL);" in error path.
Signed-off-by: Andrey Smirnov <[email protected]>
Reviewed-by: Daniel Lezcano <[email protected]>
Tested-by: Lucas Stach <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Eduardo Valentin <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: Angus Ainslie (Purism) <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/thermal/qoriq_thermal.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index f024ac68e2ed..de8c9cd115aa 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -201,23 +201,23 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev,
return 0;
}
-static int qoriq_tmu_calibration(struct platform_device *pdev)
+static int qoriq_tmu_calibration(struct device *dev,
+ struct qoriq_tmu_data *data)
{
int i, val, len;
u32 range[4];
const u32 *calibration;
- struct device_node *np = pdev->dev.of_node;
- struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
+ struct device_node *np = dev->of_node;
len = of_property_count_u32_elems(np, "fsl,tmu-range");
if (len < 0 || len > 4) {
- dev_err(&pdev->dev, "invalid range data.\n");
+ dev_err(dev, "invalid range data.\n");
return len;
}
val = of_property_read_u32_array(np, "fsl,tmu-range", range, len);
if (val != 0) {
- dev_err(&pdev->dev, "failed to read range data.\n");
+ dev_err(dev, "failed to read range data.\n");
return val;
}
@@ -227,7 +227,7 @@ static int qoriq_tmu_calibration(struct platform_device *pdev)
calibration = of_get_property(np, "fsl,tmu-calibration", &len);
if (calibration == NULL || len % 8) {
- dev_err(&pdev->dev, "invalid calibration data.\n");
+ dev_err(dev, "invalid calibration data.\n");
return -ENODEV;
}
@@ -271,8 +271,6 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
- platform_set_drvdata(pdev, data);
-
data->little_endian = of_property_read_bool(np, "little-endian");
data->regs = devm_platform_ioremap_resource(pdev, 0);
@@ -299,7 +297,7 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
qoriq_tmu_init_device(data); /* TMU initialization */
- ret = qoriq_tmu_calibration(pdev); /* TMU calibration */
+ ret = qoriq_tmu_calibration(dev, data); /* TMU calibration */
if (ret < 0)
goto err;
@@ -310,11 +308,12 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
goto err;
}
+ platform_set_drvdata(pdev, data);
+
return 0;
err:
clk_disable_unprepare(data->clk);
- platform_set_drvdata(pdev, NULL);
return ret;
}
--
2.21.0
On 10/12/2019 17:41, Andrey Smirnov wrote:
> Everyone:
>
> This series contains patches adding support for HWMON integration, bug
> fixes and general improvements (hopefully) for TMU driver I made while
> working on it on i.MX8MQ.
>
> Feedback is welcome!
Applied, thanks!
-- Daniel
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
Hi Andrew,
I failed to apply your patch. Could you please rebase it to the latest code and send me the patch directly?
BR,
Andy
> -----Original Message-----
> From: Andrey Smirnov <[email protected]>
> Sent: 2019??12??11?? 0:42
> To: Daniel Lezcano <[email protected]>
> Cc: Andrey Smirnov <[email protected]>; Andy Tang
> <[email protected]>; Anson Huang <[email protected]>; Lucas Stach
> <[email protected]>; Chris Healy <[email protected]>; Eduardo
> Valentin <[email protected]>; Angus Ainslie <[email protected]>;
> dl-linux-imx <[email protected]>; [email protected];
> [email protected]
> Subject: [EXT] [PATCH v8 08/12] thermal: qoriq: Convert driver to use regmap
> API
>
> Caution: EXT Email
>
> Convert driver to use regmap API, drop custom LE/BE IO helpers and simplify
> bit manipulation using regmap_update_bits(). This also allows us to convert
> some register initialization to use loops and adds convenient debug access to
> TMU registers via debugfs.
>
> Signed-off-by: Andrey Smirnov <[email protected]>
> Reviewed-by: Daniel Lezcano <[email protected]>
> Tested-by: Lucas Stach <[email protected]>
> Cc: Chris Healy <[email protected]>
> Cc: Lucas Stach <[email protected]>
> Cc: Eduardo Valentin <[email protected]>
> Cc: Daniel Lezcano <[email protected]>
> Cc: Angus Ainslie (Purism) <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
>
> Yuantian, Anson:
>
> I don't have access to Layerscape HW that has v2 register layout, so if you
> could give this patch a try and verify that I got the 'qoriq_yes_ranges' right,
> I'd really appreciate it.
>
> Thanks,
> Andrey Smirnov
>
> drivers/thermal/qoriq_thermal.c | 228 ++++++++++++++------------------
> 1 file changed, 98 insertions(+), 130 deletions(-)
>
> diff --git a/drivers/thermal/qoriq_thermal.c
> b/drivers/thermal/qoriq_thermal.c index 11749c673b3b..6227c940b9b0
> 100644
> --- a/drivers/thermal/qoriq_thermal.c
> +++ b/drivers/thermal/qoriq_thermal.c
> @@ -9,6 +9,7 @@
> #include <linux/io.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> +#include <linux/regmap.h>
> #include <linux/thermal.h>
>
> #include "thermal_core.h"
> @@ -24,85 +25,35 @@
> #define TMU_VER1 0x1
> #define TMU_VER2 0x2
>
> -/*
> - * QorIQ TMU Registers
> - */
> -struct qoriq_tmu_site_regs {
> - u32 tritsr; /* Immediate Temperature Site Register
> */
> - u32 tratsr; /* Average Temperature Site Register */
> - u8 res0[0x8];
> -};
> +#define REGS_TMR 0x000 /* Mode Register */
> +#define TMR_DISABLE 0x0
> +#define TMR_ME 0x80000000
> +#define TMR_ALPF 0x0c000000
>
> -struct qoriq_tmu_regs_v1 {
> - u32 tmr; /* Mode Register */
> - u32 tsr; /* Status Register */
> - u32 tmtmir; /* Temperature measurement interval
> Register */
> - u8 res0[0x14];
> - u32 tier; /* Interrupt Enable Register */
> - u32 tidr; /* Interrupt Detect Register */
> - u32 tiscr; /* Interrupt Site Capture Register */
> - u32 ticscr; /* Interrupt Critical Site Capture Register
> */
> - u8 res1[0x10];
> - u32 tmhtcrh; /* High Temperature Capture Register
> */
> - u32 tmhtcrl; /* Low Temperature Capture Register */
> - u8 res2[0x8];
> - u32 tmhtitr; /* High Temperature Immediate
> Threshold */
> - u32 tmhtatr; /* High Temperature Average Threshold
> */
> - u32 tmhtactr; /* High Temperature Average Crit Threshold */
> - u8 res3[0x24];
> - u32 ttcfgr; /* Temperature Configuration Register
> */
> - u32 tscfgr; /* Sensor Configuration Register */
> - u8 res4[0x78];
> - struct qoriq_tmu_site_regs site[SITES_MAX];
> - u8 res5[0x9f8];
> - u32 ipbrr0; /* IP Block Revision Register 0 */
> - u32 ipbrr1; /* IP Block Revision Register 1 */
> - u8 res6[0x310];
> - u32 ttrcr[4]; /* Temperature Range Control Register */
> -};
> +#define REGS_TMTMIR 0x008 /* Temperature measurement
> interval Register */
> +#define TMTMIR_DEFAULT 0x0000000f
>
> -struct qoriq_tmu_regs_v2 {
> - u32 tmr; /* Mode Register */
> - u32 tsr; /* Status Register */
> - u32 tmsr; /* monitor site register */
> - u32 tmtmir; /* Temperature measurement interval
> Register */
> - u8 res0[0x10];
> - u32 tier; /* Interrupt Enable Register */
> - u32 tidr; /* Interrupt Detect Register */
> - u8 res1[0x8];
> - u32 tiiscr; /* interrupt immediate site capture
> register */
> - u32 tiascr; /* interrupt average site capture register
> */
> - u32 ticscr; /* Interrupt Critical Site Capture Register
> */
> - u32 res2;
> - u32 tmhtcr; /* monitor high temperature capture
> register */
> - u32 tmltcr; /* monitor low temperature capture
> register */
> - u32 tmrtrcr; /* monitor rising temperature rate capture
> register */
> - u32 tmftrcr; /* monitor falling temperature rate capture
> register */
> - u32 tmhtitr; /* High Temperature Immediate Threshold */
> - u32 tmhtatr; /* High Temperature Average Threshold */
> - u32 tmhtactr; /* High Temperature Average Crit Threshold */
> - u32 res3;
> - u32 tmltitr; /* monitor low temperature immediate threshold
> */
> - u32 tmltatr; /* monitor low temperature average threshold
> register */
> - u32 tmltactr; /* monitor low temperature average critical
> threshold */
> - u32 res4;
> - u32 tmrtrctr; /* monitor rising temperature rate critical
> threshold */
> - u32 tmftrctr; /* monitor falling temperature rate critical
> threshold*/
> - u8 res5[0x8];
> - u32 ttcfgr; /* Temperature Configuration Register */
> - u32 tscfgr; /* Sensor Configuration Register */
> - u8 res6[0x78];
> - struct qoriq_tmu_site_regs site[SITES_MAX];
> - u8 res7[0x9f8];
> - u32 ipbrr0; /* IP Block Revision Register 0 */
> - u32 ipbrr1; /* IP Block Revision Register 1 */
> - u8 res8[0x300];
> - u32 teumr0;
> - u32 teumr1;
> - u32 teumr2;
> - u32 res9;
> - u32 ttrcr[4]; /* Temperature Range Control Register */
> -};
> +#define REGS_V2_TMSR 0x008 /* monitor site register */
> +
> +#define REGS_V2_TMTMIR 0x00c /* Temperature measurement interval
> Register */
> +
> +#define REGS_TIER 0x020 /* Interrupt Enable Register */
> +#define TIER_DISABLE 0x0
> +
> +
> +#define REGS_TTCFGR 0x080 /* Temperature Configuration Register
> */
> +#define REGS_TSCFGR 0x084 /* Sensor Configuration Register */
> +
> +#define REGS_TRITSR(n) (0x100 + 16 * (n)) /* Immediate Temperature
> + * Site Register
> + */ #define
> REGS_TTRnCR(n)
> +(0xf10 + 4 * (n)) /* Temperature Range n
> + * Control Register
> + */
> +#define REGS_IPBRR(n) (0xbf8 + 4 * (n)) /* IP Block Revision
> + * Register n
> + */
> +#define REGS_V2_TEUMR(n) (0xf00 + 4 * (n))
>
> /*
> * Thermal zone data
> @@ -113,10 +64,8 @@ struct qoriq_sensor {
>
> struct qoriq_tmu_data {
> int ver;
> - struct qoriq_tmu_regs_v1 __iomem *regs;
> - struct qoriq_tmu_regs_v2 __iomem *regs_v2;
> + struct regmap *regmap;
> struct clk *clk;
> - bool little_endian;
> struct qoriq_sensor sensor[SITES_MAX];
> };
>
> @@ -125,29 +74,13 @@ static struct qoriq_tmu_data
> *qoriq_sensor_to_data(struct qoriq_sensor *s)
> return container_of(s, struct qoriq_tmu_data, sensor[s->id]); }
>
> -static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem
> *addr) -{
> - if (p->little_endian)
> - iowrite32(val, addr);
> - else
> - iowrite32be(val, addr);
> -}
> -
> -static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr) -{
> - if (p->little_endian)
> - return ioread32(addr);
> - else
> - return ioread32be(addr);
> -}
> -
> static int tmu_get_temp(void *p, int *temp) {
> struct qoriq_sensor *qsensor = p;
> struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
> u32 val;
>
> - val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
> + regmap_read(qdata->regmap, REGS_TRITSR(qsensor->id), &val);
> *temp = (val & 0xff) * 1000;
>
> return 0;
> @@ -189,12 +122,12 @@ static int qoriq_tmu_register_tmu_zone(struct
> device *dev,
> /* Enable monitoring */
> if (sites != 0) {
> if (qdata->ver == TMU_VER1) {
> - tmu_write(qdata, sites | TMR_ME | TMR_ALPF,
> - &qdata->regs->tmr);
> + regmap_write(qdata->regmap, REGS_TMR,
> + sites | TMR_ME | TMR_ALPF);
> } else {
> - tmu_write(qdata, sites,
> &qdata->regs_v2->tmsr);
> - tmu_write(qdata, TMR_ME | TMR_ALPF_V2,
> - &qdata->regs_v2->tmr);
> + regmap_write(qdata->regmap,
> REGS_V2_TMSR, sites);
> + regmap_write(qdata->regmap, REGS_TMR,
> + TMR_ME | TMR_ALPF_V2);
> }
> }
>
> @@ -223,7 +156,7 @@ static int qoriq_tmu_calibration(struct device *dev,
>
> /* Init temperature range registers */
> for (i = 0; i < len; i++)
> - tmu_write(data, range[i], &data->regs->ttrcr[i]);
> + regmap_write(data->regmap, REGS_TTRnCR(i), range[i]);
>
> calibration = of_get_property(np, "fsl,tmu-calibration", &len);
> if (calibration == NULL || len % 8) { @@ -233,9 +166,9 @@ static
> int qoriq_tmu_calibration(struct device *dev,
>
> for (i = 0; i < len; i += 8, calibration += 2) {
> val = of_read_number(calibration, 1);
> - tmu_write(data, val, &data->regs->ttcfgr);
> + regmap_write(data->regmap, REGS_TTCFGR, val);
> val = of_read_number(calibration + 1, 1);
> - tmu_write(data, val, &data->regs->tscfgr);
> + regmap_write(data->regmap, REGS_TSCFGR, val);
> }
>
> return 0;
> @@ -244,20 +177,40 @@ static int qoriq_tmu_calibration(struct device *dev,
> static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) {
> /* Disable interrupt, using polling instead */
> - tmu_write(data, TIER_DISABLE, &data->regs->tier);
> + regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
>
> /* Set update_interval */
> +
> if (data->ver == TMU_VER1) {
> - tmu_write(data, TMTMIR_DEFAULT,
> &data->regs->tmtmir);
> + regmap_write(data->regmap, REGS_TMTMIR,
> TMTMIR_DEFAULT);
> } else {
> - tmu_write(data, TMTMIR_DEFAULT,
> &data->regs_v2->tmtmir);
> - tmu_write(data, TEUMR0_V2, &data->regs_v2->teumr0);
> + regmap_write(data->regmap, REGS_V2_TMTMIR,
> TMTMIR_DEFAULT);
> + regmap_write(data->regmap, REGS_V2_TEUMR(0),
> TEUMR0_V2);
> }
>
> /* Disable monitoring */
> - tmu_write(data, TMR_DISABLE, &data->regs->tmr);
> + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
> }
>
> +static const struct regmap_range qoriq_yes_ranges[] = {
> + regmap_reg_range(REGS_TMR, REGS_TSCFGR),
> + regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
> + regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
> + regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
> + /* Read only registers below */
> + regmap_reg_range(REGS_TRITSR(0), REGS_TRITSR(15)), };
> +
> +static const struct regmap_access_table qoriq_wr_table = {
> + .yes_ranges = qoriq_yes_ranges,
> + .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges) - 1,
> +};
> +
> +static const struct regmap_access_table qoriq_rd_table = {
> + .yes_ranges = qoriq_yes_ranges,
> + .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges),
> +};
> +
> static int qoriq_tmu_probe(struct platform_device *pdev) {
> int ret;
> @@ -265,18 +218,37 @@ static int qoriq_tmu_probe(struct platform_device
> *pdev)
> struct qoriq_tmu_data *data;
> struct device_node *np = pdev->dev.of_node;
> struct device *dev = &pdev->dev;
> + const bool little_endian = of_property_read_bool(np,
> "little-endian");
> + const enum regmap_endian format_endian =
> + little_endian ? REGMAP_ENDIAN_LITTLE :
> REGMAP_ENDIAN_BIG;
> + const struct regmap_config regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .rd_table = &qoriq_rd_table,
> + .wr_table = &qoriq_wr_table,
> + .val_format_endian = format_endian,
> + .max_register = SZ_4K,
> + };
> + void __iomem *base;
>
> data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data),
> GFP_KERNEL);
> if (!data)
> return -ENOMEM;
>
> - data->little_endian = of_property_read_bool(np, "little-endian");
> -
> - data->regs = devm_platform_ioremap_resource(pdev, 0);
> - if (IS_ERR(data->regs)) {
> + base = devm_platform_ioremap_resource(pdev, 0);
> + ret = PTR_ERR_OR_ZERO(base);
> + if (ret) {
> dev_err(dev, "Failed to get memory region\n");
> - return PTR_ERR(data->regs);
> + return ret;
> + }
> +
> + data->regmap = devm_regmap_init_mmio(dev, base,
> ®map_config);
> + ret = PTR_ERR_OR_ZERO(data->regmap);
> + if (ret) {
> + dev_err(dev, "Failed to init regmap (%d)\n", ret);
> + return ret;
> }
>
> data->clk = devm_clk_get_optional(dev, NULL); @@ -290,10
> +262,12 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
> }
>
> /* version register offset at: 0xbf8 on both v1 and v2 */
> - ver = tmu_read(data, &data->regs->ipbrr0);
> + ret = regmap_read(data->regmap, REGS_IPBRR(0), &ver);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to read IP block version\n");
> + return ret;
> + }
> data->ver = (ver >> 8) & 0xff;
> - if (data->ver == TMU_VER2)
> - data->regs_v2 = (void __iomem *)data->regs;
>
> qoriq_tmu_init_device(data); /* TMU initialization */
>
> @@ -323,7 +297,7 @@ static int qoriq_tmu_remove(struct platform_device
> *pdev)
> struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
>
> /* Disable monitoring */
> - tmu_write(data, TMR_DISABLE, &data->regs->tmr);
> + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
>
> clk_disable_unprepare(data->clk);
>
> @@ -332,13 +306,12 @@ static int qoriq_tmu_remove(struct
> platform_device *pdev)
>
> static int __maybe_unused qoriq_tmu_suspend(struct device *dev) {
> - u32 tmr;
> struct qoriq_tmu_data *data = dev_get_drvdata(dev);
> + int ret;
>
> - /* Disable monitoring */
> - tmr = tmu_read(data, &data->regs->tmr);
> - tmr &= ~TMR_ME;
> - tmu_write(data, tmr, &data->regs->tmr);
> + ret = regmap_update_bits(data->regmap, REGS_TMR, TMR_ME,
> 0);
> + if (ret)
> + return ret;
>
> clk_disable_unprepare(data->clk);
>
> @@ -347,7 +320,6 @@ static int __maybe_unused
> qoriq_tmu_suspend(struct device *dev)
>
> static int __maybe_unused qoriq_tmu_resume(struct device *dev) {
> - u32 tmr;
> int ret;
> struct qoriq_tmu_data *data = dev_get_drvdata(dev);
>
> @@ -356,11 +328,7 @@ static int __maybe_unused
> qoriq_tmu_resume(struct device *dev)
> return ret;
>
> /* Enable monitoring */
> - tmr = tmu_read(data, &data->regs->tmr);
> - tmr |= TMR_ME;
> - tmu_write(data, tmr, &data->regs->tmr);
> -
> - return 0;
> + return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME,
> + TMR_ME);
> }
>
> static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
> --
> 2.21.0
On 13/12/2019 07:16, Andy Tang wrote:
> Hi Andrew,
>
> I failed to apply your patch. Could you please rebase it to the latest code and send me the patch directly?
Hi Andy,
I'm taking care of the series.
Thanks
-- Daniel
>> -----Original Message-----
>> From: Andrey Smirnov <[email protected]>
>> Sent: 2019??12??11?? 0:42
>> To: Daniel Lezcano <[email protected]>
>> Cc: Andrey Smirnov <[email protected]>; Andy Tang
>> <[email protected]>; Anson Huang <[email protected]>; Lucas Stach
>> <[email protected]>; Chris Healy <[email protected]>; Eduardo
>> Valentin <[email protected]>; Angus Ainslie <[email protected]>;
>> dl-linux-imx <[email protected]>; [email protected];
>> [email protected]
>> Subject: [EXT] [PATCH v8 08/12] thermal: qoriq: Convert driver to use regmap
>> API
>>
>> Caution: EXT Email
>>
>> Convert driver to use regmap API, drop custom LE/BE IO helpers and simplify
>> bit manipulation using regmap_update_bits(). This also allows us to convert
>> some register initialization to use loops and adds convenient debug access to
>> TMU registers via debugfs.
>>
>> Signed-off-by: Andrey Smirnov <[email protected]>
>> Reviewed-by: Daniel Lezcano <[email protected]>
>> Tested-by: Lucas Stach <[email protected]>
>> Cc: Chris Healy <[email protected]>
>> Cc: Lucas Stach <[email protected]>
>> Cc: Eduardo Valentin <[email protected]>
>> Cc: Daniel Lezcano <[email protected]>
>> Cc: Angus Ainslie (Purism) <[email protected]>
>> Cc: [email protected]
>> Cc: [email protected]
>> Cc: [email protected]
>> ---
>>
>> Yuantian, Anson:
>>
>> I don't have access to Layerscape HW that has v2 register layout, so if you
>> could give this patch a try and verify that I got the 'qoriq_yes_ranges' right,
>> I'd really appreciate it.
>>
>> Thanks,
>> Andrey Smirnov
>>
>> drivers/thermal/qoriq_thermal.c | 228 ++++++++++++++------------------
>> 1 file changed, 98 insertions(+), 130 deletions(-)
>>
>> diff --git a/drivers/thermal/qoriq_thermal.c
>> b/drivers/thermal/qoriq_thermal.c index 11749c673b3b..6227c940b9b0
>> 100644
>> --- a/drivers/thermal/qoriq_thermal.c
>> +++ b/drivers/thermal/qoriq_thermal.c
>> @@ -9,6 +9,7 @@
>> #include <linux/io.h>
>> #include <linux/of.h>
>> #include <linux/of_address.h>
>> +#include <linux/regmap.h>
>> #include <linux/thermal.h>
>>
>> #include "thermal_core.h"
>> @@ -24,85 +25,35 @@
>> #define TMU_VER1 0x1
>> #define TMU_VER2 0x2
>>
>> -/*
>> - * QorIQ TMU Registers
>> - */
>> -struct qoriq_tmu_site_regs {
>> - u32 tritsr; /* Immediate Temperature Site Register
>> */
>> - u32 tratsr; /* Average Temperature Site Register */
>> - u8 res0[0x8];
>> -};
>> +#define REGS_TMR 0x000 /* Mode Register */
>> +#define TMR_DISABLE 0x0
>> +#define TMR_ME 0x80000000
>> +#define TMR_ALPF 0x0c000000
>>
>> -struct qoriq_tmu_regs_v1 {
>> - u32 tmr; /* Mode Register */
>> - u32 tsr; /* Status Register */
>> - u32 tmtmir; /* Temperature measurement interval
>> Register */
>> - u8 res0[0x14];
>> - u32 tier; /* Interrupt Enable Register */
>> - u32 tidr; /* Interrupt Detect Register */
>> - u32 tiscr; /* Interrupt Site Capture Register */
>> - u32 ticscr; /* Interrupt Critical Site Capture Register
>> */
>> - u8 res1[0x10];
>> - u32 tmhtcrh; /* High Temperature Capture Register
>> */
>> - u32 tmhtcrl; /* Low Temperature Capture Register */
>> - u8 res2[0x8];
>> - u32 tmhtitr; /* High Temperature Immediate
>> Threshold */
>> - u32 tmhtatr; /* High Temperature Average Threshold
>> */
>> - u32 tmhtactr; /* High Temperature Average Crit Threshold */
>> - u8 res3[0x24];
>> - u32 ttcfgr; /* Temperature Configuration Register
>> */
>> - u32 tscfgr; /* Sensor Configuration Register */
>> - u8 res4[0x78];
>> - struct qoriq_tmu_site_regs site[SITES_MAX];
>> - u8 res5[0x9f8];
>> - u32 ipbrr0; /* IP Block Revision Register 0 */
>> - u32 ipbrr1; /* IP Block Revision Register 1 */
>> - u8 res6[0x310];
>> - u32 ttrcr[4]; /* Temperature Range Control Register */
>> -};
>> +#define REGS_TMTMIR 0x008 /* Temperature measurement
>> interval Register */
>> +#define TMTMIR_DEFAULT 0x0000000f
>>
>> -struct qoriq_tmu_regs_v2 {
>> - u32 tmr; /* Mode Register */
>> - u32 tsr; /* Status Register */
>> - u32 tmsr; /* monitor site register */
>> - u32 tmtmir; /* Temperature measurement interval
>> Register */
>> - u8 res0[0x10];
>> - u32 tier; /* Interrupt Enable Register */
>> - u32 tidr; /* Interrupt Detect Register */
>> - u8 res1[0x8];
>> - u32 tiiscr; /* interrupt immediate site capture
>> register */
>> - u32 tiascr; /* interrupt average site capture register
>> */
>> - u32 ticscr; /* Interrupt Critical Site Capture Register
>> */
>> - u32 res2;
>> - u32 tmhtcr; /* monitor high temperature capture
>> register */
>> - u32 tmltcr; /* monitor low temperature capture
>> register */
>> - u32 tmrtrcr; /* monitor rising temperature rate capture
>> register */
>> - u32 tmftrcr; /* monitor falling temperature rate capture
>> register */
>> - u32 tmhtitr; /* High Temperature Immediate Threshold */
>> - u32 tmhtatr; /* High Temperature Average Threshold */
>> - u32 tmhtactr; /* High Temperature Average Crit Threshold */
>> - u32 res3;
>> - u32 tmltitr; /* monitor low temperature immediate threshold
>> */
>> - u32 tmltatr; /* monitor low temperature average threshold
>> register */
>> - u32 tmltactr; /* monitor low temperature average critical
>> threshold */
>> - u32 res4;
>> - u32 tmrtrctr; /* monitor rising temperature rate critical
>> threshold */
>> - u32 tmftrctr; /* monitor falling temperature rate critical
>> threshold*/
>> - u8 res5[0x8];
>> - u32 ttcfgr; /* Temperature Configuration Register */
>> - u32 tscfgr; /* Sensor Configuration Register */
>> - u8 res6[0x78];
>> - struct qoriq_tmu_site_regs site[SITES_MAX];
>> - u8 res7[0x9f8];
>> - u32 ipbrr0; /* IP Block Revision Register 0 */
>> - u32 ipbrr1; /* IP Block Revision Register 1 */
>> - u8 res8[0x300];
>> - u32 teumr0;
>> - u32 teumr1;
>> - u32 teumr2;
>> - u32 res9;
>> - u32 ttrcr[4]; /* Temperature Range Control Register */
>> -};
>> +#define REGS_V2_TMSR 0x008 /* monitor site register */
>> +
>> +#define REGS_V2_TMTMIR 0x00c /* Temperature measurement interval
>> Register */
>> +
>> +#define REGS_TIER 0x020 /* Interrupt Enable Register */
>> +#define TIER_DISABLE 0x0
>> +
>> +
>> +#define REGS_TTCFGR 0x080 /* Temperature Configuration Register
>> */
>> +#define REGS_TSCFGR 0x084 /* Sensor Configuration Register */
>> +
>> +#define REGS_TRITSR(n) (0x100 + 16 * (n)) /* Immediate Temperature
>> + * Site Register
>> + */ #define
>> REGS_TTRnCR(n)
>> +(0xf10 + 4 * (n)) /* Temperature Range n
>> + * Control Register
>> + */
>> +#define REGS_IPBRR(n) (0xbf8 + 4 * (n)) /* IP Block Revision
>> + * Register n
>> + */
>> +#define REGS_V2_TEUMR(n) (0xf00 + 4 * (n))
>>
>> /*
>> * Thermal zone data
>> @@ -113,10 +64,8 @@ struct qoriq_sensor {
>>
>> struct qoriq_tmu_data {
>> int ver;
>> - struct qoriq_tmu_regs_v1 __iomem *regs;
>> - struct qoriq_tmu_regs_v2 __iomem *regs_v2;
>> + struct regmap *regmap;
>> struct clk *clk;
>> - bool little_endian;
>> struct qoriq_sensor sensor[SITES_MAX];
>> };
>>
>> @@ -125,29 +74,13 @@ static struct qoriq_tmu_data
>> *qoriq_sensor_to_data(struct qoriq_sensor *s)
>> return container_of(s, struct qoriq_tmu_data, sensor[s->id]); }
>>
>> -static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem
>> *addr) -{
>> - if (p->little_endian)
>> - iowrite32(val, addr);
>> - else
>> - iowrite32be(val, addr);
>> -}
>> -
>> -static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr) -{
>> - if (p->little_endian)
>> - return ioread32(addr);
>> - else
>> - return ioread32be(addr);
>> -}
>> -
>> static int tmu_get_temp(void *p, int *temp) {
>> struct qoriq_sensor *qsensor = p;
>> struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
>> u32 val;
>>
>> - val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
>> + regmap_read(qdata->regmap, REGS_TRITSR(qsensor->id), &val);
>> *temp = (val & 0xff) * 1000;
>>
>> return 0;
>> @@ -189,12 +122,12 @@ static int qoriq_tmu_register_tmu_zone(struct
>> device *dev,
>> /* Enable monitoring */
>> if (sites != 0) {
>> if (qdata->ver == TMU_VER1) {
>> - tmu_write(qdata, sites | TMR_ME | TMR_ALPF,
>> - &qdata->regs->tmr);
>> + regmap_write(qdata->regmap, REGS_TMR,
>> + sites | TMR_ME | TMR_ALPF);
>> } else {
>> - tmu_write(qdata, sites,
>> &qdata->regs_v2->tmsr);
>> - tmu_write(qdata, TMR_ME | TMR_ALPF_V2,
>> - &qdata->regs_v2->tmr);
>> + regmap_write(qdata->regmap,
>> REGS_V2_TMSR, sites);
>> + regmap_write(qdata->regmap, REGS_TMR,
>> + TMR_ME | TMR_ALPF_V2);
>> }
>> }
>>
>> @@ -223,7 +156,7 @@ static int qoriq_tmu_calibration(struct device *dev,
>>
>> /* Init temperature range registers */
>> for (i = 0; i < len; i++)
>> - tmu_write(data, range[i], &data->regs->ttrcr[i]);
>> + regmap_write(data->regmap, REGS_TTRnCR(i), range[i]);
>>
>> calibration = of_get_property(np, "fsl,tmu-calibration", &len);
>> if (calibration == NULL || len % 8) { @@ -233,9 +166,9 @@ static
>> int qoriq_tmu_calibration(struct device *dev,
>>
>> for (i = 0; i < len; i += 8, calibration += 2) {
>> val = of_read_number(calibration, 1);
>> - tmu_write(data, val, &data->regs->ttcfgr);
>> + regmap_write(data->regmap, REGS_TTCFGR, val);
>> val = of_read_number(calibration + 1, 1);
>> - tmu_write(data, val, &data->regs->tscfgr);
>> + regmap_write(data->regmap, REGS_TSCFGR, val);
>> }
>>
>> return 0;
>> @@ -244,20 +177,40 @@ static int qoriq_tmu_calibration(struct device *dev,
>> static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) {
>> /* Disable interrupt, using polling instead */
>> - tmu_write(data, TIER_DISABLE, &data->regs->tier);
>> + regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
>>
>> /* Set update_interval */
>> +
>> if (data->ver == TMU_VER1) {
>> - tmu_write(data, TMTMIR_DEFAULT,
>> &data->regs->tmtmir);
>> + regmap_write(data->regmap, REGS_TMTMIR,
>> TMTMIR_DEFAULT);
>> } else {
>> - tmu_write(data, TMTMIR_DEFAULT,
>> &data->regs_v2->tmtmir);
>> - tmu_write(data, TEUMR0_V2, &data->regs_v2->teumr0);
>> + regmap_write(data->regmap, REGS_V2_TMTMIR,
>> TMTMIR_DEFAULT);
>> + regmap_write(data->regmap, REGS_V2_TEUMR(0),
>> TEUMR0_V2);
>> }
>>
>> /* Disable monitoring */
>> - tmu_write(data, TMR_DISABLE, &data->regs->tmr);
>> + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
>> }
>>
>> +static const struct regmap_range qoriq_yes_ranges[] = {
>> + regmap_reg_range(REGS_TMR, REGS_TSCFGR),
>> + regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
>> + regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
>> + regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
>> + /* Read only registers below */
>> + regmap_reg_range(REGS_TRITSR(0), REGS_TRITSR(15)), };
>> +
>> +static const struct regmap_access_table qoriq_wr_table = {
>> + .yes_ranges = qoriq_yes_ranges,
>> + .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges) - 1,
>> +};
>> +
>> +static const struct regmap_access_table qoriq_rd_table = {
>> + .yes_ranges = qoriq_yes_ranges,
>> + .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges),
>> +};
>> +
>> static int qoriq_tmu_probe(struct platform_device *pdev) {
>> int ret;
>> @@ -265,18 +218,37 @@ static int qoriq_tmu_probe(struct platform_device
>> *pdev)
>> struct qoriq_tmu_data *data;
>> struct device_node *np = pdev->dev.of_node;
>> struct device *dev = &pdev->dev;
>> + const bool little_endian = of_property_read_bool(np,
>> "little-endian");
>> + const enum regmap_endian format_endian =
>> + little_endian ? REGMAP_ENDIAN_LITTLE :
>> REGMAP_ENDIAN_BIG;
>> + const struct regmap_config regmap_config = {
>> + .reg_bits = 32,
>> + .val_bits = 32,
>> + .reg_stride = 4,
>> + .rd_table = &qoriq_rd_table,
>> + .wr_table = &qoriq_wr_table,
>> + .val_format_endian = format_endian,
>> + .max_register = SZ_4K,
>> + };
>> + void __iomem *base;
>>
>> data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data),
>> GFP_KERNEL);
>> if (!data)
>> return -ENOMEM;
>>
>> - data->little_endian = of_property_read_bool(np, "little-endian");
>> -
>> - data->regs = devm_platform_ioremap_resource(pdev, 0);
>> - if (IS_ERR(data->regs)) {
>> + base = devm_platform_ioremap_resource(pdev, 0);
>> + ret = PTR_ERR_OR_ZERO(base);
>> + if (ret) {
>> dev_err(dev, "Failed to get memory region\n");
>> - return PTR_ERR(data->regs);
>> + return ret;
>> + }
>> +
>> + data->regmap = devm_regmap_init_mmio(dev, base,
>> ®map_config);
>> + ret = PTR_ERR_OR_ZERO(data->regmap);
>> + if (ret) {
>> + dev_err(dev, "Failed to init regmap (%d)\n", ret);
>> + return ret;
>> }
>>
>> data->clk = devm_clk_get_optional(dev, NULL); @@ -290,10
>> +262,12 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
>> }
>>
>> /* version register offset at: 0xbf8 on both v1 and v2 */
>> - ver = tmu_read(data, &data->regs->ipbrr0);
>> + ret = regmap_read(data->regmap, REGS_IPBRR(0), &ver);
>> + if (ret) {
>> + dev_err(&pdev->dev, "Failed to read IP block version\n");
>> + return ret;
>> + }
>> data->ver = (ver >> 8) & 0xff;
>> - if (data->ver == TMU_VER2)
>> - data->regs_v2 = (void __iomem *)data->regs;
>>
>> qoriq_tmu_init_device(data); /* TMU initialization */
>>
>> @@ -323,7 +297,7 @@ static int qoriq_tmu_remove(struct platform_device
>> *pdev)
>> struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
>>
>> /* Disable monitoring */
>> - tmu_write(data, TMR_DISABLE, &data->regs->tmr);
>> + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
>>
>> clk_disable_unprepare(data->clk);
>>
>> @@ -332,13 +306,12 @@ static int qoriq_tmu_remove(struct
>> platform_device *pdev)
>>
>> static int __maybe_unused qoriq_tmu_suspend(struct device *dev) {
>> - u32 tmr;
>> struct qoriq_tmu_data *data = dev_get_drvdata(dev);
>> + int ret;
>>
>> - /* Disable monitoring */
>> - tmr = tmu_read(data, &data->regs->tmr);
>> - tmr &= ~TMR_ME;
>> - tmu_write(data, tmr, &data->regs->tmr);
>> + ret = regmap_update_bits(data->regmap, REGS_TMR, TMR_ME,
>> 0);
>> + if (ret)
>> + return ret;
>>
>> clk_disable_unprepare(data->clk);
>>
>> @@ -347,7 +320,6 @@ static int __maybe_unused
>> qoriq_tmu_suspend(struct device *dev)
>>
>> static int __maybe_unused qoriq_tmu_resume(struct device *dev) {
>> - u32 tmr;
>> int ret;
>> struct qoriq_tmu_data *data = dev_get_drvdata(dev);
>>
>> @@ -356,11 +328,7 @@ static int __maybe_unused
>> qoriq_tmu_resume(struct device *dev)
>> return ret;
>>
>> /* Enable monitoring */
>> - tmr = tmu_read(data, &data->regs->tmr);
>> - tmr |= TMR_ME;
>> - tmu_write(data, tmr, &data->regs->tmr);
>> -
>> - return 0;
>> + return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME,
>> + TMR_ME);
>> }
>>
>> static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
>> --
>> 2.21.0
>
--
<http://www.linaro.org/> Linaro.org ?? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
> -----Original Message-----
> From: Daniel Lezcano <[email protected]>
> Sent: 2019??12??13?? 15:48
> To: Andy Tang <[email protected]>; Andrey Smirnov
> <[email protected]>
> Cc: Anson Huang <[email protected]>; Lucas Stach
> <[email protected]>; Chris Healy <[email protected]>; Eduardo
> Valentin <[email protected]>; Angus Ainslie <[email protected]>;
> dl-linux-imx <[email protected]>; [email protected];
> [email protected]
> Subject: Re: [EXT] [PATCH v8 08/12] thermal: qoriq: Convert driver to use
> regmap API
>
> Caution: EXT Email
>
> On 13/12/2019 07:16, Andy Tang wrote:
> > Hi Andrew,
> >
> > I failed to apply your patch. Could you please rebase it to the latest code
> and send me the patch directly?
>
> Hi Andy,
>
> I'm taking care of the series.
Thanks, I just want to verify it on the board since the author can't access the tmu v2 module.
BR,
Andy
>
> Thanks
>
> -- Daniel
>
>
> >> -----Original Message-----
> >> From: Andrey Smirnov <[email protected]>
> >> Sent: 2019??12??11?? 0:42
> >> To: Daniel Lezcano <[email protected]>
> >> Cc: Andrey Smirnov <[email protected]>; Andy Tang
> >> <[email protected]>; Anson Huang <[email protected]>; Lucas
> Stach
> >> <[email protected]>; Chris Healy <[email protected]>; Eduardo
> >> Valentin <[email protected]>; Angus Ainslie <[email protected]>;
> >> dl-linux-imx <[email protected]>; [email protected];
> >> [email protected]
> >> Subject: [EXT] [PATCH v8 08/12] thermal: qoriq: Convert driver to use
> >> regmap API
> >>
> >> Caution: EXT Email
> >>
> >> Convert driver to use regmap API, drop custom LE/BE IO helpers and
> >> simplify bit manipulation using regmap_update_bits(). This also
> >> allows us to convert some register initialization to use loops and
> >> adds convenient debug access to TMU registers via debugfs.
> >>
> >> Signed-off-by: Andrey Smirnov <[email protected]>
> >> Reviewed-by: Daniel Lezcano <[email protected]>
> >> Tested-by: Lucas Stach <[email protected]>
> >> Cc: Chris Healy <[email protected]>
> >> Cc: Lucas Stach <[email protected]>
> >> Cc: Eduardo Valentin <[email protected]>
> >> Cc: Daniel Lezcano <[email protected]>
> >> Cc: Angus Ainslie (Purism) <[email protected]>
> >> Cc: [email protected]
> >> Cc: [email protected]
> >> Cc: [email protected]
> >> ---
> >>
> >> Yuantian, Anson:
> >>
> >> I don't have access to Layerscape HW that has v2 register layout, so
> >> if you could give this patch a try and verify that I got the
> >> 'qoriq_yes_ranges' right, I'd really appreciate it.
> >>
> >> Thanks,
> >> Andrey Smirnov
> >>
> >> drivers/thermal/qoriq_thermal.c | 228
> >> ++++++++++++++------------------
> >> 1 file changed, 98 insertions(+), 130 deletions(-)
> >>
> >> diff --git a/drivers/thermal/qoriq_thermal.c
> >> b/drivers/thermal/qoriq_thermal.c index 11749c673b3b..6227c940b9b0
> >> 100644
> >> --- a/drivers/thermal/qoriq_thermal.c
> >> +++ b/drivers/thermal/qoriq_thermal.c
> >> @@ -9,6 +9,7 @@
> >> #include <linux/io.h>
> >> #include <linux/of.h>
> >> #include <linux/of_address.h>
> >> +#include <linux/regmap.h>
> >> #include <linux/thermal.h>
> >>
> >> #include "thermal_core.h"
> >> @@ -24,85 +25,35 @@
> >> #define TMU_VER1 0x1
> >> #define TMU_VER2 0x2
> >>
> >> -/*
> >> - * QorIQ TMU Registers
> >> - */
> >> -struct qoriq_tmu_site_regs {
> >> - u32 tritsr; /* Immediate Temperature Site
> Register
> >> */
> >> - u32 tratsr; /* Average Temperature Site Register
> */
> >> - u8 res0[0x8];
> >> -};
> >> +#define REGS_TMR 0x000 /* Mode Register */
> >> +#define TMR_DISABLE 0x0
> >> +#define TMR_ME 0x80000000
> >> +#define TMR_ALPF 0x0c000000
> >>
> >> -struct qoriq_tmu_regs_v1 {
> >> - u32 tmr; /* Mode Register */
> >> - u32 tsr; /* Status Register */
> >> - u32 tmtmir; /* Temperature measurement
> interval
> >> Register */
> >> - u8 res0[0x14];
> >> - u32 tier; /* Interrupt Enable Register */
> >> - u32 tidr; /* Interrupt Detect Register */
> >> - u32 tiscr; /* Interrupt Site Capture Register */
> >> - u32 ticscr; /* Interrupt Critical Site Capture
> Register
> >> */
> >> - u8 res1[0x10];
> >> - u32 tmhtcrh; /* High Temperature Capture
> Register
> >> */
> >> - u32 tmhtcrl; /* Low Temperature Capture
> Register */
> >> - u8 res2[0x8];
> >> - u32 tmhtitr; /* High Temperature Immediate
> >> Threshold */
> >> - u32 tmhtatr; /* High Temperature Average
> Threshold
> >> */
> >> - u32 tmhtactr; /* High Temperature Average Crit Threshold */
> >> - u8 res3[0x24];
> >> - u32 ttcfgr; /* Temperature Configuration
> Register
> >> */
> >> - u32 tscfgr; /* Sensor Configuration Register */
> >> - u8 res4[0x78];
> >> - struct qoriq_tmu_site_regs site[SITES_MAX];
> >> - u8 res5[0x9f8];
> >> - u32 ipbrr0; /* IP Block Revision Register 0 */
> >> - u32 ipbrr1; /* IP Block Revision Register 1 */
> >> - u8 res6[0x310];
> >> - u32 ttrcr[4]; /* Temperature Range Control
> Register */
> >> -};
> >> +#define REGS_TMTMIR 0x008 /* Temperature measurement
> >> interval Register */
> >> +#define TMTMIR_DEFAULT 0x0000000f
> >>
> >> -struct qoriq_tmu_regs_v2 {
> >> - u32 tmr; /* Mode Register */
> >> - u32 tsr; /* Status Register */
> >> - u32 tmsr; /* monitor site register */
> >> - u32 tmtmir; /* Temperature measurement
> interval
> >> Register */
> >> - u8 res0[0x10];
> >> - u32 tier; /* Interrupt Enable Register */
> >> - u32 tidr; /* Interrupt Detect Register */
> >> - u8 res1[0x8];
> >> - u32 tiiscr; /* interrupt immediate site capture
> >> register */
> >> - u32 tiascr; /* interrupt average site capture
> register
> >> */
> >> - u32 ticscr; /* Interrupt Critical Site Capture
> Register
> >> */
> >> - u32 res2;
> >> - u32 tmhtcr; /* monitor high temperature capture
> >> register */
> >> - u32 tmltcr; /* monitor low temperature capture
> >> register */
> >> - u32 tmrtrcr; /* monitor rising temperature rate capture
> >> register */
> >> - u32 tmftrcr; /* monitor falling temperature rate capture
> >> register */
> >> - u32 tmhtitr; /* High Temperature Immediate Threshold */
> >> - u32 tmhtatr; /* High Temperature Average Threshold */
> >> - u32 tmhtactr; /* High Temperature Average Crit Threshold */
> >> - u32 res3;
> >> - u32 tmltitr; /* monitor low temperature immediate
> threshold
> >> */
> >> - u32 tmltatr; /* monitor low temperature average threshold
> >> register */
> >> - u32 tmltactr; /* monitor low temperature average critical
> >> threshold */
> >> - u32 res4;
> >> - u32 tmrtrctr; /* monitor rising temperature rate critical
> >> threshold */
> >> - u32 tmftrctr; /* monitor falling temperature rate critical
> >> threshold*/
> >> - u8 res5[0x8];
> >> - u32 ttcfgr; /* Temperature Configuration Register */
> >> - u32 tscfgr; /* Sensor Configuration Register */
> >> - u8 res6[0x78];
> >> - struct qoriq_tmu_site_regs site[SITES_MAX];
> >> - u8 res7[0x9f8];
> >> - u32 ipbrr0; /* IP Block Revision Register 0 */
> >> - u32 ipbrr1; /* IP Block Revision Register 1 */
> >> - u8 res8[0x300];
> >> - u32 teumr0;
> >> - u32 teumr1;
> >> - u32 teumr2;
> >> - u32 res9;
> >> - u32 ttrcr[4]; /* Temperature Range Control Register */
> >> -};
> >> +#define REGS_V2_TMSR 0x008 /* monitor site register */
> >> +
> >> +#define REGS_V2_TMTMIR 0x00c /* Temperature measurement
> interval
> >> Register */
> >> +
> >> +#define REGS_TIER 0x020 /* Interrupt Enable Register */
> >> +#define TIER_DISABLE 0x0
> >> +
> >> +
> >> +#define REGS_TTCFGR 0x080 /* Temperature Configuration
> Register
> >> */
> >> +#define REGS_TSCFGR 0x084 /* Sensor Configuration Register */
> >> +
> >> +#define REGS_TRITSR(n) (0x100 + 16 * (n)) /* Immediate Temperature
> >> + * Site Register
> >> + */ #define
> >> REGS_TTRnCR(n)
> >> +(0xf10 + 4 * (n)) /* Temperature Range n
> >> + * Control Register
> >> + */
> >> +#define REGS_IPBRR(n) (0xbf8 + 4 * (n)) /* IP Block Revision
> >> + * Register
> n
> >> + */
> >> +#define REGS_V2_TEUMR(n) (0xf00 + 4 * (n))
> >>
> >> /*
> >> * Thermal zone data
> >> @@ -113,10 +64,8 @@ struct qoriq_sensor {
> >>
> >> struct qoriq_tmu_data {
> >> int ver;
> >> - struct qoriq_tmu_regs_v1 __iomem *regs;
> >> - struct qoriq_tmu_regs_v2 __iomem *regs_v2;
> >> + struct regmap *regmap;
> >> struct clk *clk;
> >> - bool little_endian;
> >> struct qoriq_sensor sensor[SITES_MAX];
> >> };
> >>
> >> @@ -125,29 +74,13 @@ static struct qoriq_tmu_data
> >> *qoriq_sensor_to_data(struct qoriq_sensor *s)
> >> return container_of(s, struct qoriq_tmu_data, sensor[s->id]);
> >> }
> >>
> >> -static void tmu_write(struct qoriq_tmu_data *p, u32 val, void
> >> __iomem
> >> *addr) -{
> >> - if (p->little_endian)
> >> - iowrite32(val, addr);
> >> - else
> >> - iowrite32be(val, addr);
> >> -}
> >> -
> >> -static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr) -{
> >> - if (p->little_endian)
> >> - return ioread32(addr);
> >> - else
> >> - return ioread32be(addr);
> >> -}
> >> -
> >> static int tmu_get_temp(void *p, int *temp) {
> >> struct qoriq_sensor *qsensor = p;
> >> struct qoriq_tmu_data *qdata =
> qoriq_sensor_to_data(qsensor);
> >> u32 val;
> >>
> >> - val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
> >> + regmap_read(qdata->regmap, REGS_TRITSR(qsensor->id),
> &val);
> >> *temp = (val & 0xff) * 1000;
> >>
> >> return 0;
> >> @@ -189,12 +122,12 @@ static int qoriq_tmu_register_tmu_zone(struct
> >> device *dev,
> >> /* Enable monitoring */
> >> if (sites != 0) {
> >> if (qdata->ver == TMU_VER1) {
> >> - tmu_write(qdata, sites | TMR_ME |
> TMR_ALPF,
> >> - &qdata->regs->tmr);
> >> + regmap_write(qdata->regmap, REGS_TMR,
> >> + sites | TMR_ME |
> TMR_ALPF);
> >> } else {
> >> - tmu_write(qdata, sites,
> >> &qdata->regs_v2->tmsr);
> >> - tmu_write(qdata, TMR_ME | TMR_ALPF_V2,
> >> - &qdata->regs_v2->tmr);
> >> + regmap_write(qdata->regmap,
> >> REGS_V2_TMSR, sites);
> >> + regmap_write(qdata->regmap, REGS_TMR,
> >> + TMR_ME | TMR_ALPF_V2);
> >> }
> >> }
> >>
> >> @@ -223,7 +156,7 @@ static int qoriq_tmu_calibration(struct device
> >> *dev,
> >>
> >> /* Init temperature range registers */
> >> for (i = 0; i < len; i++)
> >> - tmu_write(data, range[i], &data->regs->ttrcr[i]);
> >> + regmap_write(data->regmap, REGS_TTRnCR(i),
> range[i]);
> >>
> >> calibration = of_get_property(np, "fsl,tmu-calibration", &len);
> >> if (calibration == NULL || len % 8) { @@ -233,9 +166,9 @@
> >> static int qoriq_tmu_calibration(struct device *dev,
> >>
> >> for (i = 0; i < len; i += 8, calibration += 2) {
> >> val = of_read_number(calibration, 1);
> >> - tmu_write(data, val, &data->regs->ttcfgr);
> >> + regmap_write(data->regmap, REGS_TTCFGR, val);
> >> val = of_read_number(calibration + 1, 1);
> >> - tmu_write(data, val, &data->regs->tscfgr);
> >> + regmap_write(data->regmap, REGS_TSCFGR, val);
> >> }
> >>
> >> return 0;
> >> @@ -244,20 +177,40 @@ static int qoriq_tmu_calibration(struct device
> >> *dev, static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) {
> >> /* Disable interrupt, using polling instead */
> >> - tmu_write(data, TIER_DISABLE, &data->regs->tier);
> >> + regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
> >>
> >> /* Set update_interval */
> >> +
> >> if (data->ver == TMU_VER1) {
> >> - tmu_write(data, TMTMIR_DEFAULT,
> >> &data->regs->tmtmir);
> >> + regmap_write(data->regmap, REGS_TMTMIR,
> >> TMTMIR_DEFAULT);
> >> } else {
> >> - tmu_write(data, TMTMIR_DEFAULT,
> >> &data->regs_v2->tmtmir);
> >> - tmu_write(data, TEUMR0_V2,
> &data->regs_v2->teumr0);
> >> + regmap_write(data->regmap, REGS_V2_TMTMIR,
> >> TMTMIR_DEFAULT);
> >> + regmap_write(data->regmap, REGS_V2_TEUMR(0),
> >> TEUMR0_V2);
> >> }
> >>
> >> /* Disable monitoring */
> >> - tmu_write(data, TMR_DISABLE, &data->regs->tmr);
> >> + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
> >> }
> >>
> >> +static const struct regmap_range qoriq_yes_ranges[] = {
> >> + regmap_reg_range(REGS_TMR, REGS_TSCFGR),
> >> + regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
> >> + regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
> >> + regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
> >> + /* Read only registers below */
> >> + regmap_reg_range(REGS_TRITSR(0), REGS_TRITSR(15)), };
> >> +
> >> +static const struct regmap_access_table qoriq_wr_table = {
> >> + .yes_ranges = qoriq_yes_ranges,
> >> + .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges) - 1,
> >> +};
> >> +
> >> +static const struct regmap_access_table qoriq_rd_table = {
> >> + .yes_ranges = qoriq_yes_ranges,
> >> + .n_yes_ranges = ARRAY_SIZE(qoriq_yes_ranges),
> >> +};
> >> +
> >> static int qoriq_tmu_probe(struct platform_device *pdev) {
> >> int ret;
> >> @@ -265,18 +218,37 @@ static int qoriq_tmu_probe(struct
> >> platform_device
> >> *pdev)
> >> struct qoriq_tmu_data *data;
> >> struct device_node *np = pdev->dev.of_node;
> >> struct device *dev = &pdev->dev;
> >> + const bool little_endian = of_property_read_bool(np,
> >> "little-endian");
> >> + const enum regmap_endian format_endian =
> >> + little_endian ? REGMAP_ENDIAN_LITTLE :
> >> REGMAP_ENDIAN_BIG;
> >> + const struct regmap_config regmap_config = {
> >> + .reg_bits = 32,
> >> + .val_bits = 32,
> >> + .reg_stride = 4,
> >> + .rd_table = &qoriq_rd_table,
> >> + .wr_table = &qoriq_wr_table,
> >> + .val_format_endian = format_endian,
> >> + .max_register = SZ_4K,
> >> + };
> >> + void __iomem *base;
> >>
> >> data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data),
> >> GFP_KERNEL);
> >> if (!data)
> >> return -ENOMEM;
> >>
> >> - data->little_endian = of_property_read_bool(np, "little-endian");
> >> -
> >> - data->regs = devm_platform_ioremap_resource(pdev, 0);
> >> - if (IS_ERR(data->regs)) {
> >> + base = devm_platform_ioremap_resource(pdev, 0);
> >> + ret = PTR_ERR_OR_ZERO(base);
> >> + if (ret) {
> >> dev_err(dev, "Failed to get memory region\n");
> >> - return PTR_ERR(data->regs);
> >> + return ret;
> >> + }
> >> +
> >> + data->regmap = devm_regmap_init_mmio(dev, base,
> >> ®map_config);
> >> + ret = PTR_ERR_OR_ZERO(data->regmap);
> >> + if (ret) {
> >> + dev_err(dev, "Failed to init regmap (%d)\n", ret);
> >> + return ret;
> >> }
> >>
> >> data->clk = devm_clk_get_optional(dev, NULL); @@ -290,10
> >> +262,12 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
> >> }
> >>
> >> /* version register offset at: 0xbf8 on both v1 and v2 */
> >> - ver = tmu_read(data, &data->regs->ipbrr0);
> >> + ret = regmap_read(data->regmap, REGS_IPBRR(0), &ver);
> >> + if (ret) {
> >> + dev_err(&pdev->dev, "Failed to read IP block
> version\n");
> >> + return ret;
> >> + }
> >> data->ver = (ver >> 8) & 0xff;
> >> - if (data->ver == TMU_VER2)
> >> - data->regs_v2 = (void __iomem *)data->regs;
> >>
> >> qoriq_tmu_init_device(data); /* TMU initialization */
> >>
> >> @@ -323,7 +297,7 @@ static int qoriq_tmu_remove(struct
> >> platform_device
> >> *pdev)
> >> struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
> >>
> >> /* Disable monitoring */
> >> - tmu_write(data, TMR_DISABLE, &data->regs->tmr);
> >> + regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
> >>
> >> clk_disable_unprepare(data->clk);
> >>
> >> @@ -332,13 +306,12 @@ static int qoriq_tmu_remove(struct
> >> platform_device *pdev)
> >>
> >> static int __maybe_unused qoriq_tmu_suspend(struct device *dev) {
> >> - u32 tmr;
> >> struct qoriq_tmu_data *data = dev_get_drvdata(dev);
> >> + int ret;
> >>
> >> - /* Disable monitoring */
> >> - tmr = tmu_read(data, &data->regs->tmr);
> >> - tmr &= ~TMR_ME;
> >> - tmu_write(data, tmr, &data->regs->tmr);
> >> + ret = regmap_update_bits(data->regmap, REGS_TMR,
> TMR_ME,
> >> 0);
> >> + if (ret)
> >> + return ret;
> >>
> >> clk_disable_unprepare(data->clk);
> >>
> >> @@ -347,7 +320,6 @@ static int __maybe_unused
> >> qoriq_tmu_suspend(struct device *dev)
> >>
> >> static int __maybe_unused qoriq_tmu_resume(struct device *dev) {
> >> - u32 tmr;
> >> int ret;
> >> struct qoriq_tmu_data *data = dev_get_drvdata(dev);
> >>
> >> @@ -356,11 +328,7 @@ static int __maybe_unused
> >> qoriq_tmu_resume(struct device *dev)
> >> return ret;
> >>
> >> /* Enable monitoring */
> >> - tmr = tmu_read(data, &data->regs->tmr);
> >> - tmr |= TMR_ME;
> >> - tmu_write(data, tmr, &data->regs->tmr);
> >> -
> >> - return 0;
> >> + return regmap_update_bits(data->regmap, REGS_TMR,
> TMR_ME,
> >> + TMR_ME);
> >> }
> >>
> >> static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
> >> --
> >> 2.21.0
> >
>
>
> --
>
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.
> linaro.org%2F&data=02%7C01%7Candy.tang%40nxp.com%7Cc8504714
> 5f15471a47f308d77fa0c37a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0
> %7C0%7C637118200760390874&sdata=OZc2lZ%2B8UXPghJzpPdKvwlP
> 0loBLkJWeFi0Ffq0rsiw%3D&reserved=0> Linaro.org ?? Open source
> software for ARM SoCs
>
> Follow Linaro:
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.
> facebook.com%2Fpages%2FLinaro&data=02%7C01%7Candy.tang%40nx
> p.com%7Cc85047145f15471a47f308d77fa0c37a%7C686ea1d3bc2b4c6fa92cd
> 99c5c301635%7C0%7C0%7C637118200760390874&sdata=oplTFz7vaO
> nnfQpVPY%2Fjc%2B6mRf%2B%2Fhb1EXB5D29eB9eY%3D&reserved=0>
> Facebook |
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Ftwitte
> r.com%2F%23!%2Flinaroorg&data=02%7C01%7Candy.tang%40nxp.com
> %7Cc85047145f15471a47f308d77fa0c37a%7C686ea1d3bc2b4c6fa92cd99c5c
> 301635%7C0%7C0%7C637118200760390874&sdata=oMmBJEGN2ynpg
> SwRrfYd4VrKFOt8ytFQRS1k%2Fl33IPc%3D&reserved=0> Twitter |
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.
> linaro.org%2Flinaro-blog%2F&data=02%7C01%7Candy.tang%40nxp.co
> m%7Cc85047145f15471a47f308d77fa0c37a%7C686ea1d3bc2b4c6fa92cd99c
> 5c301635%7C0%7C0%7C637118200760390874&sdata=885EiSd31rVjAN
> B2lSa8%2FSxzpE9DcpFAOSRKDoof2TU%3D&reserved=0> Blog