1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
From d1066d775e67c33cc93178475c4485c5ef0a83c9 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <wahrenst@gmx.net>
Date: Sat, 18 May 2019 12:26:11 +0200
Subject: [PATCH] thermal: brcmstb_thermal: Add BCM2838 support
The BCM2838 has an AVS TMON hardware block. This adds the necessary
support to the brcmstb_thermal driver ( no trip handling ).
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/thermal/broadcom/Kconfig | 2 +-
drivers/thermal/broadcom/brcmstb_thermal.c | 61 +++++++++++++++++++---
2 files changed, 54 insertions(+), 9 deletions(-)
--- a/drivers/thermal/broadcom/Kconfig
+++ b/drivers/thermal/broadcom/Kconfig
@@ -9,7 +9,7 @@ config BCM2835_THERMAL
config BRCMSTB_THERMAL
tristate "Broadcom STB AVS TMON thermal driver"
- depends on ARCH_BRCMSTB || COMPILE_TEST
+ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
help
Enable this driver if you have a Broadcom STB SoC and would like
thermal framework support.
--- a/drivers/thermal/broadcom/brcmstb_thermal.c
+++ b/drivers/thermal/broadcom/brcmstb_thermal.c
@@ -10,6 +10,7 @@
#define pr_fmt(fmt) DRV_NAME ": " fmt
#include <linux/bitops.h>
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
@@ -22,9 +23,6 @@
#include <linux/thermal.h>
#define AVS_TMON_STATUS 0x00
- #define AVS_TMON_STATUS_valid_msk BIT(11)
- #define AVS_TMON_STATUS_data_msk GENMASK(10, 1)
- #define AVS_TMON_STATUS_data_shift 1
#define AVS_TMON_EN_OVERTEMP_RESET 0x04
#define AVS_TMON_EN_OVERTEMP_RESET_msk BIT(0)
@@ -102,10 +100,19 @@ static struct avs_tmon_trip avs_tmon_tri
},
};
+struct brcmstb_thermal_of_data {
+ const struct thermal_zone_of_device_ops *of_ops;
+ u32 status_valid_mask;
+ u32 status_data_mask;
+ u32 status_data_shift;
+};
+
struct brcmstb_thermal_priv {
void __iomem *tmon_base;
struct device *dev;
struct thermal_zone_device *thermal;
+ struct clk *clk;
+ const struct brcmstb_thermal_of_data *socdata;
};
/* Convert a HW code to a temperature reading (millidegree celsius) */
@@ -142,17 +149,18 @@ static inline u32 avs_tmon_temp_to_code(
static int brcmstb_get_temp(void *data, int *temp)
{
struct brcmstb_thermal_priv *priv = data;
+ const struct brcmstb_thermal_of_data *socdata = priv->socdata;
u32 val;
long t;
val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS);
- if (!(val & AVS_TMON_STATUS_valid_msk)) {
+ if (!(val & socdata->status_valid_mask)) {
dev_err(priv->dev, "reading not valid\n");
return -EIO;
}
- val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift;
+ val = (val & socdata->status_data_mask) >> socdata->status_data_shift;
t = avs_tmon_code_to_temp(priv->thermal, val);
if (t < 0)
@@ -277,13 +285,34 @@ static int brcmstb_set_trips(void *data,
return 0;
}
-static const struct thermal_zone_of_device_ops of_ops = {
+static const struct thermal_zone_of_device_ops bcm7445_thermal_of_ops = {
.get_temp = brcmstb_get_temp,
.set_trips = brcmstb_set_trips,
};
+static const struct thermal_zone_of_device_ops bcm2838_thermal_of_ops = {
+ .get_temp = brcmstb_get_temp,
+};
+
+static const struct brcmstb_thermal_of_data bcm7445_thermal_of_data = {
+ .of_ops = &bcm7445_thermal_of_ops,
+ .status_valid_mask = BIT(11),
+ .status_data_mask = GENMASK(10, 1),
+ .status_data_shift = 1,
+};
+
+static const struct brcmstb_thermal_of_data bcm2838_thermal_of_data = {
+ .of_ops = &bcm2838_thermal_of_ops,
+ .status_valid_mask = BIT(10),
+ .status_data_mask = GENMASK(9, 0),
+ .status_data_shift = 0,
+};
+
static const struct of_device_id brcmstb_thermal_id_table[] = {
- { .compatible = "brcm,avs-tmon" },
+ { .compatible = "brcm,avs-tmon",
+ .data = &bcm7445_thermal_of_data },
+ { .compatible = "brcm,avs-tmon-bcm2838",
+ .data = &bcm2838_thermal_of_data },
{},
};
MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table);
@@ -304,11 +333,27 @@ static int brcmstb_thermal_probe(struct
if (IS_ERR(priv->tmon_base))
return PTR_ERR(priv->tmon_base);
+ priv->socdata = of_device_get_match_data(&pdev->dev);
+ if (!priv->socdata) {
+ dev_err(&pdev->dev, "no device match found\n");
+ return -ENODEV;
+ }
+
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (!IS_ERR(priv->clk)) {
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+ }
+
priv->dev = &pdev->dev;
platform_set_drvdata(pdev, priv);
thermal = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, priv,
- &of_ops);
+ priv->socdata->of_ops);
if (IS_ERR(thermal)) {
ret = PTR_ERR(thermal);
dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
|