aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-10-26 09:29:40 -0400
committerArnd Bergmann <arnd@arndb.de>2012-10-26 09:29:40 -0400
commit9628d859750e1b0b1181ed96c64d341f1d5b6cee (patch)
tree0a6a48608ed45ab68f1a56f80f392db4746a7e18
parent6f0c0580b70c89094b3422ba81118c7b959c7556 (diff)
parent790440bc90fa800ff2a4b8b5046227a2ca32c1b1 (diff)
Merge branch 'vexpress-drivers' of git://git.linaro.org/people/pawelmoll/linux into next/drivers
Versatile Express changes from Pawel Moll <pawel.moll@arm.com>: * 'vexpress-drivers' of git://git.linaro.org/people/pawelmoll/linux: ARM: vexpress: Reset driver hwmon: Versatile Express hwmon driver Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--Documentation/devicetree/bindings/hwmon/vexpress.txt23
-rw-r--r--Documentation/hwmon/vexpress34
-rw-r--r--arch/arm/mach-vexpress/reset.c141
-rw-r--r--drivers/hwmon/Kconfig8
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/vexpress.c229
6 files changed, 436 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/vexpress.txt b/Documentation/devicetree/bindings/hwmon/vexpress.txt
new file mode 100644
index 000000000000..9c27ed694bbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/vexpress.txt
@@ -0,0 +1,23 @@
1Versatile Express hwmon sensors
2-------------------------------
3
4Requires node properties:
5- "compatible" value : one of
6 "arm,vexpress-volt"
7 "arm,vexpress-amp"
8 "arm,vexpress-temp"
9 "arm,vexpress-power"
10 "arm,vexpress-energy"
11- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
12 (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
13 for more details)
14
15Optional node properties:
16- label : string describing the monitored value
17
18Example:
19 energy@0 {
20 compatible = "arm,vexpress-energy";
21 arm,vexpress-sysreg,func = <13 0>;
22 label = "A15 Jcore";
23 };
diff --git a/Documentation/hwmon/vexpress b/Documentation/hwmon/vexpress
new file mode 100644
index 000000000000..557d6d5ad90d
--- /dev/null
+++ b/Documentation/hwmon/vexpress
@@ -0,0 +1,34 @@
1Kernel driver vexpress
2======================
3
4Supported systems:
5 * ARM Ltd. Versatile Express platform
6 Prefix: 'vexpress'
7 Datasheets:
8 * "Hardware Description" sections of the Technical Reference Manuals
9 for the Versatile Express boards:
10 http://infocenter.arm.com/help/topic/com.arm.doc.subset.boards.express/index.html
11 * Section "4.4.14. System Configuration registers" of the V2M-P1 TRM:
12 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0447-/index.html
13
14Author: Pawel Moll
15
16Description
17-----------
18
19Versatile Express platform (http://www.arm.com/versatileexpress/) is a
20reference & prototyping system for ARM Ltd. processors. It can be set up
21from a wide range of boards, each of them containing (apart of the main
22chip/FPGA) a number of microcontrollers responsible for platform
23configuration and control. Theses microcontrollers can also monitor the
24board and its environment by a number of internal and external sensors,
25providing information about power lines voltages and currents, board
26temperature and power usage. Some of them also calculate consumed energy
27and provide a cumulative use counter.
28
29The configuration devices are _not_ memory mapped and must be accessed
30via a custom interface, abstracted by the "vexpress_config" API.
31
32As these devices are non-discoverable, they must be described in a Device
33Tree passed to the kernel. Details of the DT binding for them can be found
34in Documentation/devicetree/bindings/hwmon/vexpress.txt.
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c
new file mode 100644
index 000000000000..465923aa3819
--- /dev/null
+++ b/arch/arm/mach-vexpress/reset.c
@@ -0,0 +1,141 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2012 ARM Limited
12 */
13
14#include <linux/jiffies.h>
15#include <linux/of.h>
16#include <linux/of_device.h>
17#include <linux/platform_device.h>
18#include <linux/stat.h>
19#include <linux/vexpress.h>
20
21static void vexpress_reset_do(struct device *dev, const char *what)
22{
23 int err = -ENOENT;
24 struct vexpress_config_func *func =
25 vexpress_config_func_get_by_dev(dev);
26
27 if (func) {
28 unsigned long timeout;
29
30 err = vexpress_config_write(func, 0, 0);
31
32 timeout = jiffies + HZ;
33 while (time_before(jiffies, timeout))
34 cpu_relax();
35 }
36
37 dev_emerg(dev, "Unable to %s (%d)\n", what, err);
38}
39
40static struct device *vexpress_power_off_device;
41
42void vexpress_power_off(void)
43{
44 vexpress_reset_do(vexpress_power_off_device, "power off");
45}
46
47static struct device *vexpress_restart_device;
48
49void vexpress_restart(char str, const char *cmd)
50{
51 vexpress_reset_do(vexpress_restart_device, "restart");
52}
53
54static ssize_t vexpress_reset_active_show(struct device *dev,
55 struct device_attribute *attr, char *buf)
56{
57 return sprintf(buf, "%d\n", vexpress_restart_device == dev);
58}
59
60static ssize_t vexpress_reset_active_store(struct device *dev,
61 struct device_attribute *attr, const char *buf, size_t count)
62{
63 long value;
64 int err = kstrtol(buf, 0, &value);
65
66 if (!err && value)
67 vexpress_restart_device = dev;
68
69 return err ? err : count;
70}
71
72DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
73 vexpress_reset_active_store);
74
75
76enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
77
78static struct of_device_id vexpress_reset_of_match[] = {
79 {
80 .compatible = "arm,vexpress-reset",
81 .data = (void *)FUNC_RESET,
82 }, {
83 .compatible = "arm,vexpress-shutdown",
84 .data = (void *)FUNC_SHUTDOWN
85 }, {
86 .compatible = "arm,vexpress-reboot",
87 .data = (void *)FUNC_REBOOT
88 },
89 {}
90};
91
92static int vexpress_reset_probe(struct platform_device *pdev)
93{
94 enum vexpress_reset_func func;
95 const struct of_device_id *match =
96 of_match_device(vexpress_reset_of_match, &pdev->dev);
97
98 if (match)
99 func = (enum vexpress_reset_func)match->data;
100 else
101 func = pdev->id_entry->driver_data;
102
103 switch (func) {
104 case FUNC_SHUTDOWN:
105 vexpress_power_off_device = &pdev->dev;
106 break;
107 case FUNC_RESET:
108 if (!vexpress_restart_device)
109 vexpress_restart_device = &pdev->dev;
110 device_create_file(&pdev->dev, &dev_attr_active);
111 break;
112 case FUNC_REBOOT:
113 vexpress_restart_device = &pdev->dev;
114 device_create_file(&pdev->dev, &dev_attr_active);
115 break;
116 };
117
118 return 0;
119}
120
121static const struct platform_device_id vexpress_reset_id_table[] = {
122 { .name = "vexpress-reset", .driver_data = FUNC_RESET, },
123 { .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
124 { .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
125 {}
126};
127
128static struct platform_driver vexpress_reset_driver = {
129 .probe = vexpress_reset_probe,
130 .driver = {
131 .name = "vexpress-reset",
132 .of_match_table = vexpress_reset_of_match,
133 },
134 .id_table = vexpress_reset_id_table,
135};
136
137static int __init vexpress_reset_init(void)
138{
139 return platform_driver_register(&vexpress_reset_driver);
140}
141device_initcall(vexpress_reset_init);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c4633de64465..db213fe958a5 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1197,6 +1197,14 @@ config SENSORS_TWL4030_MADC
1197 This driver can also be built as a module. If so it will be called 1197 This driver can also be built as a module. If so it will be called
1198 twl4030-madc-hwmon. 1198 twl4030-madc-hwmon.
1199 1199
1200config SENSORS_VEXPRESS
1201 tristate "Versatile Express"
1202 depends on VEXPRESS_CONFIG
1203 help
1204 This driver provides support for hardware sensors available on
1205 the ARM Ltd's Versatile Express platform. It can provide wide
1206 range of information like temperature, power, energy.
1207
1200config SENSORS_VIA_CPUTEMP 1208config SENSORS_VIA_CPUTEMP
1201 tristate "VIA CPU temperature sensor" 1209 tristate "VIA CPU temperature sensor"
1202 depends on X86 1210 depends on X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 8d5fcb5e8e9f..aac8b7c619d6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -121,6 +121,7 @@ obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
121obj-$(CONFIG_SENSORS_TMP401) += tmp401.o 121obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
122obj-$(CONFIG_SENSORS_TMP421) += tmp421.o 122obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
123obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o 123obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
124obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o
124obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o 125obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
125obj-$(CONFIG_SENSORS_VIA686A) += via686a.o 126obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
126obj-$(CONFIG_SENSORS_VT1211) += vt1211.o 127obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
new file mode 100644
index 000000000000..59fd1268e58a
--- /dev/null
+++ b/drivers/hwmon/vexpress.c
@@ -0,0 +1,229 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2012 ARM Limited
12 */
13
14#define DRVNAME "vexpress-hwmon"
15#define pr_fmt(fmt) DRVNAME ": " fmt
16
17#include <linux/device.h>
18#include <linux/err.h>
19#include <linux/hwmon.h>
20#include <linux/hwmon-sysfs.h>
21#include <linux/module.h>
22#include <linux/of_device.h>
23#include <linux/platform_device.h>
24#include <linux/vexpress.h>
25
26struct vexpress_hwmon_data {
27 struct device *hwmon_dev;
28 struct vexpress_config_func *func;
29};
30
31static ssize_t vexpress_hwmon_name_show(struct device *dev,
32 struct device_attribute *dev_attr, char *buffer)
33{
34 const char *compatible = of_get_property(dev->of_node, "compatible",
35 NULL);
36
37 return sprintf(buffer, "%s\n", compatible);
38}
39
40static ssize_t vexpress_hwmon_label_show(struct device *dev,
41 struct device_attribute *dev_attr, char *buffer)
42{
43 const char *label = of_get_property(dev->of_node, "label", NULL);
44
45 if (!label)
46 return -ENOENT;
47
48 return snprintf(buffer, PAGE_SIZE, "%s\n", label);
49}
50
51static ssize_t vexpress_hwmon_u32_show(struct device *dev,
52 struct device_attribute *dev_attr, char *buffer)
53{
54 struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
55 int err;
56 u32 value;
57
58 err = vexpress_config_read(data->func, 0, &value);
59 if (err)
60 return err;
61
62 return snprintf(buffer, PAGE_SIZE, "%u\n", value /
63 to_sensor_dev_attr(dev_attr)->index);
64}
65
66static ssize_t vexpress_hwmon_u64_show(struct device *dev,
67 struct device_attribute *dev_attr, char *buffer)
68{
69 struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
70 int err;
71 u32 value_hi, value_lo;
72
73 err = vexpress_config_read(data->func, 0, &value_lo);
74 if (err)
75 return err;
76
77 err = vexpress_config_read(data->func, 1, &value_hi);
78 if (err)
79 return err;
80
81 return snprintf(buffer, PAGE_SIZE, "%llu\n",
82 div_u64(((u64)value_hi << 32) | value_lo,
83 to_sensor_dev_attr(dev_attr)->index));
84}
85
86static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL);
87
88#define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \
89struct attribute *vexpress_hwmon_attrs_##_name[] = { \
90 &dev_attr_name.attr, \
91 &dev_attr_##_label_attr.attr, \
92 &sensor_dev_attr_##_input_attr.dev_attr.attr, \
93 NULL \
94}
95
96#if !defined(CONFIG_REGULATOR_VEXPRESS)
97static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
98static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
99 NULL, 1000);
100static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input);
101static struct attribute_group vexpress_hwmon_group_volt = {
102 .attrs = vexpress_hwmon_attrs_volt,
103};
104#endif
105
106static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
107static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
108 NULL, 1000);
109static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input);
110static struct attribute_group vexpress_hwmon_group_amp = {
111 .attrs = vexpress_hwmon_attrs_amp,
112};
113
114static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
115static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
116 NULL, 1000);
117static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input);
118static struct attribute_group vexpress_hwmon_group_temp = {
119 .attrs = vexpress_hwmon_attrs_temp,
120};
121
122static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
123static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
124 NULL, 1);
125static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input);
126static struct attribute_group vexpress_hwmon_group_power = {
127 .attrs = vexpress_hwmon_attrs_power,
128};
129
130static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
131static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
132 NULL, 1);
133static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input);
134static struct attribute_group vexpress_hwmon_group_energy = {
135 .attrs = vexpress_hwmon_attrs_energy,
136};
137
138static struct of_device_id vexpress_hwmon_of_match[] = {
139#if !defined(CONFIG_REGULATOR_VEXPRESS)
140 {
141 .compatible = "arm,vexpress-volt",
142 .data = &vexpress_hwmon_group_volt,
143 },
144#endif
145 {
146 .compatible = "arm,vexpress-amp",
147 .data = &vexpress_hwmon_group_amp,
148 }, {
149 .compatible = "arm,vexpress-temp",
150 .data = &vexpress_hwmon_group_temp,
151 }, {
152 .compatible = "arm,vexpress-power",
153 .data = &vexpress_hwmon_group_power,
154 }, {
155 .compatible = "arm,vexpress-energy",
156 .data = &vexpress_hwmon_group_energy,
157 },
158 {}
159};
160MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
161
162static int vexpress_hwmon_probe(struct platform_device *pdev)
163{
164 int err;
165 const struct of_device_id *match;
166 struct vexpress_hwmon_data *data;
167
168 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
169 if (!data)
170 return -ENOMEM;
171 platform_set_drvdata(pdev, data);
172
173 match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
174 if (!match)
175 return -ENODEV;
176
177 data->func = vexpress_config_func_get_by_dev(&pdev->dev);
178 if (!data->func)
179 return -ENODEV;
180
181 err = sysfs_create_group(&pdev->dev.kobj, match->data);
182 if (err)
183 goto error;
184
185 data->hwmon_dev = hwmon_device_register(&pdev->dev);
186 if (IS_ERR(data->hwmon_dev)) {
187 err = PTR_ERR(data->hwmon_dev);
188 goto error;
189 }
190
191 return 0;
192
193error:
194 sysfs_remove_group(&pdev->dev.kobj, match->data);
195 vexpress_config_func_put(data->func);
196 return err;
197}
198
199static int __devexit vexpress_hwmon_remove(struct platform_device *pdev)
200{
201 struct vexpress_hwmon_data *data = platform_get_drvdata(pdev);
202 const struct of_device_id *match;
203
204 hwmon_device_unregister(data->hwmon_dev);
205
206 match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
207 sysfs_remove_group(&pdev->dev.kobj, match->data);
208
209 vexpress_config_func_put(data->func);
210
211 return 0;
212}
213
214static struct platform_driver vexpress_hwmon_driver = {
215 .probe = vexpress_hwmon_probe,
216 .remove = __devexit_p(vexpress_hwmon_remove),
217 .driver = {
218 .name = DRVNAME,
219 .owner = THIS_MODULE,
220 .of_match_table = vexpress_hwmon_of_match,
221 },
222};
223
224module_platform_driver(vexpress_hwmon_driver);
225
226MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
227MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
228MODULE_LICENSE("GPL");
229MODULE_ALIAS("platform:vexpress-hwmon");