aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpio-samsung.c25
-rw-r--r--drivers/hwmon/Kconfig8
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/vexpress.c229
4 files changed, 250 insertions, 13 deletions
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 88f41e51565..01f7fe95559 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -42,12 +42,6 @@
42#include <plat/gpio-fns.h> 42#include <plat/gpio-fns.h>
43#include <plat/pm.h> 43#include <plat/pm.h>
44 44
45#ifndef DEBUG_GPIO
46#define gpio_dbg(x...) do { } while (0)
47#else
48#define gpio_dbg(x...) printk(KERN_DEBUG x)
49#endif
50
51int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip, 45int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
52 unsigned int off, samsung_gpio_pull_t pull) 46 unsigned int off, samsung_gpio_pull_t pull)
53{ 47{
@@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
596 unsigned long con; 590 unsigned long con;
597 591
598 con = __raw_readl(base + GPIOCON_OFF); 592 con = __raw_readl(base + GPIOCON_OFF);
599 con &= ~(0xf << con_4bit_shift(offset)); 593 if (ourchip->bitmap_gpio_int & BIT(offset))
594 con |= 0xf << con_4bit_shift(offset);
595 else
596 con &= ~(0xf << con_4bit_shift(offset));
600 __raw_writel(con, base + GPIOCON_OFF); 597 __raw_writel(con, base + GPIOCON_OFF);
601 598
602 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con); 599 pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
603 600
604 return 0; 601 return 0;
605} 602}
@@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
627 __raw_writel(con, base + GPIOCON_OFF); 624 __raw_writel(con, base + GPIOCON_OFF);
628 __raw_writel(dat, base + GPIODAT_OFF); 625 __raw_writel(dat, base + GPIODAT_OFF);
629 626
630 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); 627 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
631 628
632 return 0; 629 return 0;
633} 630}
@@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
671 con &= ~(0xf << con_4bit_shift(offset)); 668 con &= ~(0xf << con_4bit_shift(offset));
672 __raw_writel(con, regcon); 669 __raw_writel(con, regcon);
673 670
674 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con); 671 pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
675 672
676 return 0; 673 return 0;
677} 674}
@@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
706 __raw_writel(con, regcon); 703 __raw_writel(con, regcon);
707 __raw_writel(dat, base + GPIODAT_OFF); 704 __raw_writel(dat, base + GPIODAT_OFF);
708 705
709 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); 706 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
710 707
711 return 0; 708 return 0;
712} 709}
@@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
926#ifdef CONFIG_PM 923#ifdef CONFIG_PM
927 if (chip->pm != NULL) { 924 if (chip->pm != NULL) {
928 if (!chip->pm->save || !chip->pm->resume) 925 if (!chip->pm->save || !chip->pm->resume)
929 printk(KERN_ERR "gpio: %s has missing PM functions\n", 926 pr_err("gpio: %s has missing PM functions\n",
930 gc->label); 927 gc->label);
931 } else 928 } else
932 printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); 929 pr_err("gpio: %s has no PM function\n", gc->label);
933#endif 930#endif
934 931
935 /* gpiochip_add() prints own failure message on error. */ 932 /* gpiochip_add() prints own failure message on error. */
@@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip
1081 if ((base != NULL) && (chip->base == NULL)) 1078 if ((base != NULL) && (chip->base == NULL))
1082 chip->base = base + ((i) * 0x20); 1079 chip->base = base + ((i) * 0x20);
1083 1080
1081 chip->bitmap_gpio_int = 0;
1082
1084 samsung_gpiolib_add(chip); 1083 samsung_gpiolib_add(chip);
1085 } 1084 }
1086} 1085}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4800d4c2a7b..32f238f3cae 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1208,6 +1208,14 @@ config SENSORS_TWL4030_MADC
1208 This driver can also be built as a module. If so it will be called 1208 This driver can also be built as a module. If so it will be called
1209 twl4030-madc-hwmon. 1209 twl4030-madc-hwmon.
1210 1210
1211config SENSORS_VEXPRESS
1212 tristate "Versatile Express"
1213 depends on VEXPRESS_CONFIG
1214 help
1215 This driver provides support for hardware sensors available on
1216 the ARM Ltd's Versatile Express platform. It can provide wide
1217 range of information like temperature, power, energy.
1218
1211config SENSORS_VIA_CPUTEMP 1219config SENSORS_VIA_CPUTEMP
1212 tristate "VIA CPU temperature sensor" 1220 tristate "VIA CPU temperature sensor"
1213 depends on X86 1221 depends on X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index a930f0997d2..5da287443f6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -122,6 +122,7 @@ obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
122obj-$(CONFIG_SENSORS_TMP401) += tmp401.o 122obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
123obj-$(CONFIG_SENSORS_TMP421) += tmp421.o 123obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
124obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o 124obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
125obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o
125obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o 126obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
126obj-$(CONFIG_SENSORS_VIA686A) += via686a.o 127obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
127obj-$(CONFIG_SENSORS_VT1211) += vt1211.o 128obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
new file mode 100644
index 00000000000..59fd1268e58
--- /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");