aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2015-04-22 18:17:30 +0100
committerJon Medhurst <tixy@linaro.org>2015-04-22 18:17:30 +0100
commit9a5e38d6ac13ac05aad9dd215c68bcce54fa1f7c (patch)
tree47b6d20abc46ad4f0a4b55ba061d80fa52410ebb /drivers
parentc63a5aa52b242bb92440b0bc546e7097b40eed4a (diff)
parentdeb7033a0bfb9568ee455b154bcedd0669b2162e (diff)
Merge branch 'lsk-3.10-armlt-juno-misc' into integration-lsk-3.10-juno-android-new
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clocksource/arm_arch_timer.c7
-rw-r--r--drivers/hwmon/Kconfig8
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/v2m-juno.c388
4 files changed, 402 insertions, 2 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 67bbbd8ae507..31a704cca182 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -668,11 +668,13 @@ CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init);
static void __init arch_timer_mem_init(struct device_node *np)
{
struct device_node *frame, *best_frame = NULL;
- void __iomem *cntctlbase, *base;
+ /*void __iomem *cntctlbase;*/
+ void __iomem *base;
unsigned int irq;
u32 cnttidr;
arch_timers_present |= ARCH_MEM_TIMER;
+ /*
cntctlbase = of_iomap(np, 0);
if (!cntctlbase) {
pr_err("arch_timer: Can't find CNTCTLBase\n");
@@ -681,7 +683,8 @@ static void __init arch_timer_mem_init(struct device_node *np)
cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
iounmap(cntctlbase);
-
+ */
+ cnttidr = 0x1;
/*
* Try to find a virtual capable frame. Otherwise fall back to a
* physical capable frame.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f25f29835b3e..1d465264a05f 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1296,6 +1296,14 @@ config SENSORS_TWL4030_MADC
This driver can also be built as a module. If so it will be called
twl4030-madc-hwmon.
+config SENSORS_V2M_JUNO
+ tristate "V2M Juno"
+ depends on VEXPRESS_CONFIG
+ help
+ This driver provides support for hardware sensors available on
+ the ARM Ltd's V2M Juno platform. It can provide wide
+ range of information like current, voltage, power, energy.
+
config SENSORS_VEXPRESS
tristate "Versatile Express"
depends on VEXPRESS_CONFIG
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index d17d3e64f9f4..72e23b5cdf1c 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -130,6 +130,7 @@ obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
+obj-$(CONFIG_SENSORS_V2M_JUNO) += v2m-juno.o
obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o
obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
diff --git a/drivers/hwmon/v2m-juno.c b/drivers/hwmon/v2m-juno.c
new file mode 100644
index 000000000000..1ce2b728779a
--- /dev/null
+++ b/drivers/hwmon/v2m-juno.c
@@ -0,0 +1,388 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2014 ARM Limited
+ */
+
+#define DRVNAME "v2m-juno-hwmon"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+struct v2m_juno_hwmon_type {
+ const char *name;
+ const struct attribute_group *attr_groups;
+};
+
+static void __iomem *base;
+
+struct v2m_juno_hwmon_dev {
+ struct v2m_juno_hwmon_type *type;
+ struct device *hwmon_dev;
+ const char *name;
+ u32 offset;
+ u32 mult;
+ u32 div;
+};
+
+static ssize_t v2m_juno_hwmon_name_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ struct v2m_juno_hwmon_dev *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buffer, "%s\n", hdev->name);
+}
+
+static ssize_t v2m_juno_hwmon_u32_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ struct v2m_juno_hwmon_dev *hdev = dev_get_drvdata(dev);
+ u64 value;
+
+ value = readl(base + hdev->offset);
+ value *= hdev->mult;
+ return snprintf(buffer, PAGE_SIZE, "%llu\n", value / hdev->div);
+}
+
+static ssize_t v2m_juno_hwmon_u64_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ struct v2m_juno_hwmon_dev *hdev = dev_get_drvdata(dev);
+ u64 value;
+
+ value = readq(base + hdev->offset);
+ value *= hdev->mult;
+ return snprintf(buffer, PAGE_SIZE, "%llu\n", value / hdev->div);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, v2m_juno_hwmon_name_show, NULL);
+
+#define JUNO_HWMON_ATTRS(_name, _input_attr) \
+struct attribute *v2m_juno_hwmon_attrs_##_name[] = { \
+ &dev_attr_name.attr, \
+ &sensor_dev_attr_##_input_attr.dev_attr.attr, \
+ NULL \
+}
+
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, v2m_juno_hwmon_u32_show,
+ NULL, 1);
+static JUNO_HWMON_ATTRS(volt, in1_input);
+static struct attribute_group v2m_juno_hwmon_group_volt = {
+ .attrs = v2m_juno_hwmon_attrs_volt,
+};
+static struct v2m_juno_hwmon_type v2m_juno_hwmon_volt = {
+ .name = "v2m_juno_volt",
+ .attr_groups = &v2m_juno_hwmon_group_volt,
+};
+#endif
+
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, v2m_juno_hwmon_u32_show,
+ NULL, 1);
+static JUNO_HWMON_ATTRS(amp, curr1_input);
+static struct attribute_group v2m_juno_hwmon_group_amp = {
+ .attrs = v2m_juno_hwmon_attrs_amp,
+};
+static struct v2m_juno_hwmon_type v2m_juno_hwmon_amp = {
+ .name = "v2m_juno_amp",
+ .attr_groups = &v2m_juno_hwmon_group_amp,
+};
+
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, v2m_juno_hwmon_u32_show,
+ NULL, 1);
+static JUNO_HWMON_ATTRS(power, power1_input);
+static struct attribute_group v2m_juno_hwmon_group_power = {
+ .attrs = v2m_juno_hwmon_attrs_power,
+};
+static struct v2m_juno_hwmon_type v2m_juno_hwmon_power = {
+ .name = "v2m_juno_power",
+ .attr_groups = &v2m_juno_hwmon_group_power,
+};
+
+static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, v2m_juno_hwmon_u64_show,
+ NULL, 1);
+static JUNO_HWMON_ATTRS(energy, energy1_input);
+static struct attribute_group v2m_juno_hwmon_group_energy = {
+ .attrs = v2m_juno_hwmon_attrs_energy,
+};
+static struct v2m_juno_hwmon_type v2m_juno_hwmon_energy = {
+ .name = "v2m_juno_energy",
+ .attr_groups = &v2m_juno_hwmon_group_energy,
+};
+
+/* current adc channels */
+#define SYS_ADC_CH0_PM1_SYS 0xd0
+#define SYS_ADC_CH1_PM2_A57 0xd4
+#define SYS_ADC_CH2_PM3_A53 0xd8
+#define SYS_ADC_CH3_PM4_GPU 0xdc
+
+/* voltage adc channels */
+#define SYS_ADC_CH4_VSYS 0xe0
+#define SYS_ADC_CH5_VA57 0xe4
+#define SYS_ADC_CH6_VA53 0xe8
+#define SYS_ADC_CH7_VGPU 0xec
+
+/* power adc channels */
+#define SYS_EN_CH04_SYS 0xf0
+#define SYS_EN_CH15_A57 0xf4
+#define SYS_EN_CH26_A53 0xf8
+#define SYS_EN_CH37_GPU 0xfc
+
+/* energy adc channels */
+#define SYS_ENM_CH0_L_SYS 0x100
+#define SYS_ENM_CH0_H_SYS 0x104
+#define SYS_ENM_CH1_L_A57 0x108
+#define SYS_ENM_CH1_H_A57 0x10c
+#define SYS_ENM_CH0_L_A53 0x110
+#define SYS_ENM_CH0_H_A53 0x114
+#define SYS_ENM_CH0_L_GPU 0x118
+#define SYS_ENM_CH0_H_GPU 0x11c
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_curr_sys = {
+ .type = &v2m_juno_hwmon_amp,
+ .offset = SYS_ADC_CH0_PM1_SYS,
+ .name = "sys_curr",
+ .mult = 1000,
+ .div = 761
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_curr_a57 = {
+ .type = &v2m_juno_hwmon_amp,
+ .offset = SYS_ADC_CH1_PM2_A57,
+ .name = "a57_curr",
+ .mult = 1000,
+ .div = 381,
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_curr_a53 = {
+ .type = &v2m_juno_hwmon_amp,
+ .offset = SYS_ADC_CH2_PM3_A53,
+ .name = "a53_curr",
+ .mult = 1000,
+ .div = 761
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_curr_gpu = {
+ .type = &v2m_juno_hwmon_amp,
+ .offset = SYS_ADC_CH3_PM4_GPU,
+ .name = "gpu_curr",
+ .mult = 1000,
+ .div = 381
+};
+
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_volt_sys = {
+ .type = &v2m_juno_hwmon_volt,
+ .offset = SYS_ADC_CH4_VSYS,
+ .name = "sys_volt",
+ .mult = 1000,
+ .div = 1622
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_volt_a57 = {
+ .type = &v2m_juno_hwmon_volt,
+ .offset = SYS_ADC_CH5_VA57,
+ .name = "a57_volt",
+ .mult = 1000,
+ .div = 1622
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_volt_a53 = {
+ .type = &v2m_juno_hwmon_volt,
+ .offset = SYS_ADC_CH6_VA53,
+ .name = "a53_volt",
+ .mult = 1000,
+ .div = 1622
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_volt_gpu = {
+ .type = &v2m_juno_hwmon_volt,
+ .offset = SYS_ADC_CH7_VGPU,
+ .name = "gpu_volt",
+ .mult = 1000,
+ .div = 1622
+};
+#endif
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_power_sys = {
+ .type = &v2m_juno_hwmon_power,
+ .offset = SYS_EN_CH04_SYS,
+ .name = "sys_power",
+ .mult = 1000,
+ .div = 1234803
+
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_power_a57 = {
+ .type = &v2m_juno_hwmon_power,
+ .offset = SYS_EN_CH15_A57,
+ .name = "a57_power",
+ .mult = 1000,
+ .div = 617402
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_power_a53 = {
+ .type = &v2m_juno_hwmon_power,
+ .offset = SYS_EN_CH26_A53,
+ .name = "a53_power",
+ .mult = 1000,
+ .div = 1234803,
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_power_gpu = {
+ .type = &v2m_juno_hwmon_power,
+ .offset = SYS_EN_CH37_GPU,
+ .mult = 1000,
+ .name = "gpu_power",
+ .div = 617402
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_energy_sys = {
+ .type = &v2m_juno_hwmon_energy,
+ .offset = SYS_ENM_CH0_L_SYS,
+ .name = "sys_energy",
+ .mult = 100,
+ .div = 1234803,
+};
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_energy_a57 = {
+ .type = &v2m_juno_hwmon_energy,
+ .offset = SYS_ENM_CH1_L_A57,
+ .name = "a57_energy",
+ .mult = 100,
+ .div = 617402
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_energy_a53 = {
+ .type = &v2m_juno_hwmon_energy,
+ .offset = SYS_ENM_CH0_L_A53,
+ .name = "a53_energy",
+ .mult = 100,
+ .div = 1234803,
+};
+
+struct v2m_juno_hwmon_dev v2m_juno_hwmon_energy_gpu = {
+ .type = &v2m_juno_hwmon_energy,
+ .offset = SYS_ENM_CH0_L_GPU,
+ .name = "gpu_energy",
+ .mult = 100,
+ .div = 617402
+};
+
+static struct v2m_juno_hwmon_dev *v2m_juno_hwmon_devices[] = {
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+ &v2m_juno_hwmon_volt_sys,
+ &v2m_juno_hwmon_volt_a57,
+ &v2m_juno_hwmon_volt_a53,
+ &v2m_juno_hwmon_volt_gpu,
+#endif
+ &v2m_juno_hwmon_energy_sys,
+ &v2m_juno_hwmon_energy_a57,
+ &v2m_juno_hwmon_energy_a53,
+ &v2m_juno_hwmon_energy_gpu,
+ &v2m_juno_hwmon_power_sys,
+ &v2m_juno_hwmon_power_a57,
+ &v2m_juno_hwmon_power_a53,
+ &v2m_juno_hwmon_power_gpu,
+ &v2m_juno_hwmon_curr_sys,
+ &v2m_juno_hwmon_curr_a57,
+ &v2m_juno_hwmon_curr_a53,
+ &v2m_juno_hwmon_curr_gpu,
+};
+
+static struct of_device_id v2m_juno_hwmon_of_match[] = {
+ {
+ .compatible = "arm,v2m-juno-meters",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, v2m_juno_hwmon_of_match);
+
+static int v2m_juno_hwmon_probe(struct platform_device *pdev)
+{
+ int i, err;
+ const struct of_device_id *match;
+ struct v2m_juno_hwmon_dev *dev;
+ struct resource *mem;
+
+ match = of_match_device(v2m_juno_hwmon_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, mem);
+
+ for (i = 0; i < ARRAY_SIZE(v2m_juno_hwmon_devices); i++) {
+ dev = v2m_juno_hwmon_devices[i];
+ dev->hwmon_dev = hwmon_device_register(&pdev->dev);
+
+ if (IS_ERR(dev->hwmon_dev)) {
+ err = PTR_ERR(dev->hwmon_dev);
+ goto error;
+ }
+ err = sysfs_create_group(&dev->hwmon_dev->kobj,
+ dev->type->attr_groups);
+ if (err)
+ goto error_sysfs;
+
+ dev_set_drvdata(dev->hwmon_dev, dev);
+ }
+
+ return 0;
+
+error:
+ while (--i >= 0) {
+ dev = v2m_juno_hwmon_devices[i];
+ sysfs_remove_group(&dev->hwmon_dev->kobj,
+ dev->type->attr_groups);
+error_sysfs:
+ hwmon_device_unregister(dev->hwmon_dev);
+ }
+
+ return err;
+}
+
+static int v2m_juno_hwmon_remove(struct platform_device *pdev)
+{
+ int i;
+ struct v2m_juno_hwmon_dev *dev;
+
+ for (i = 0; i < ARRAY_SIZE(v2m_juno_hwmon_devices); i++) {
+ dev = v2m_juno_hwmon_devices[i];
+ hwmon_device_unregister(dev->hwmon_dev);
+ sysfs_remove_group(&dev->hwmon_dev->kobj,
+ dev->type->attr_groups);
+ }
+
+ return 0;
+}
+
+static struct platform_driver v2m_juno_hwmon_driver = {
+ .probe = v2m_juno_hwmon_probe,
+ .remove = v2m_juno_hwmon_remove,
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = v2m_juno_hwmon_of_match,
+ },
+};
+
+module_platform_driver(v2m_juno_hwmon_driver);
+
+MODULE_AUTHOR("Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>");
+MODULE_DESCRIPTION("V2M Juno hwmon sensors driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:v2m-juno-hwmon");