mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
rk3288:tsadc:support rockchip hwmon tsadc
This commit is contained in:
@@ -1044,6 +1044,18 @@
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tsadc: tsadc@ff280000{
|
||||
compatible = "rockchip,tsadc";
|
||||
reg = <0xff280000 0x100>;
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#io-channel-cells = <1>;
|
||||
io-channel-ranges;
|
||||
clock-frequency = <50000>;
|
||||
clocks = <&clk_tsadc>, <&clk_gates7 2>;
|
||||
clock-names = "tsadc", "pclk_tsadc";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -315,6 +315,7 @@ CONFIG_DEBUG_GPIO=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_BATTERY_BQ24296=y
|
||||
CONFIG_BATTERY_BQ27320=y
|
||||
CONFIG_SENSORS_ROCKCHIP_TSADC=y
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_MFD_RK808=y
|
||||
CONFIG_REGULATOR=y
|
||||
|
||||
@@ -1020,6 +1020,15 @@ config SENSORS_SHT21
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called sht21.
|
||||
|
||||
config SENSORS_ROCKCHIP_TSADC
|
||||
tristate "ROCKCHIP built-in TSADC"
|
||||
help
|
||||
If you say yes here you get support for the on-board TSADCs of
|
||||
the ROCKCHIP RK3288 and other series of SoC
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rockchip-hwmon.
|
||||
|
||||
config SENSORS_S3C
|
||||
tristate "Samsung built-in ADC"
|
||||
depends on S3C_ADC
|
||||
|
||||
@@ -113,6 +113,7 @@ obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
|
||||
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
|
||||
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
|
||||
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
|
||||
obj-$(CONFIG_SENSORS_ROCKCHIP_TSADC) += rockchip-hwmon.o rockchip_tsadc.o
|
||||
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
|
||||
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
|
||||
|
||||
77
drivers/hwmon/hwmon-rockchip.h
Executable file
77
drivers/hwmon/hwmon-rockchip.h
Executable file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson 2010 - 2013
|
||||
* License terms: GNU General Public License v2
|
||||
* Author: Martin Persson <martin.persson@stericsson.com>
|
||||
* Hongbo Zhang <hongbo.zhang@linaro.com>
|
||||
*/
|
||||
|
||||
#ifndef _ROCKCHIP_H
|
||||
#define _ROCKCHIP_H
|
||||
|
||||
#define NUM_SENSORS 5
|
||||
|
||||
struct rockchip_temp;
|
||||
|
||||
/*
|
||||
* struct rockchip_temp_ops - rockchip chip specific ops
|
||||
* @read_sensor: reads gpadc output
|
||||
* @irq_handler: irq handler
|
||||
* @show_name: hwmon device name
|
||||
* @show_label: hwmon attribute label
|
||||
* @is_visible: is attribute visible
|
||||
*/
|
||||
struct rockchip_temp_ops {
|
||||
int (*read_sensor)(int);
|
||||
int (*irq_handler)(int, struct rockchip_temp *);
|
||||
ssize_t (*show_name)(struct device *,
|
||||
struct device_attribute *, char *);
|
||||
ssize_t (*show_label) (struct device *,
|
||||
struct device_attribute *, char *);
|
||||
int (*is_visible)(struct attribute *, int);
|
||||
};
|
||||
|
||||
/*
|
||||
* struct rockchip_temp - representation of temp mon device
|
||||
* @pdev: platform device
|
||||
* @hwmon_dev: hwmon device
|
||||
* @ops: rockchip chip specific ops
|
||||
* @gpadc_addr: gpadc channel address
|
||||
* @min: sensor temperature min value
|
||||
* @max: sensor temperature max value
|
||||
* @max_hyst: sensor temperature hysteresis value for max limit
|
||||
* @min_alarm: sensor temperature min alarm
|
||||
* @max_alarm: sensor temperature max alarm
|
||||
* @work: delayed work scheduled to monitor temperature periodically
|
||||
* @work_active: True if work is active
|
||||
* @lock: mutex
|
||||
* @monitored_sensors: number of monitored sensors
|
||||
* @plat_data: private usage, usually points to platform specific data
|
||||
*/
|
||||
struct rockchip_temp {
|
||||
struct platform_device *pdev;
|
||||
struct device *hwmon_dev;
|
||||
struct rockchip_temp_ops ops;
|
||||
u8 tsadc_addr[NUM_SENSORS];
|
||||
unsigned long min[NUM_SENSORS];
|
||||
unsigned long max[NUM_SENSORS];
|
||||
unsigned long max_hyst[NUM_SENSORS];
|
||||
bool min_alarm[NUM_SENSORS];
|
||||
bool max_alarm[NUM_SENSORS];
|
||||
struct delayed_work work;
|
||||
bool work_active;
|
||||
struct mutex lock;
|
||||
int monitored_sensors;
|
||||
void *plat_data;
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
struct resource *ioarea;
|
||||
struct tsadc_host *tsadc;
|
||||
struct work_struct auto_ht_irq_work;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct workqueue_struct *tsadc_workqueue;
|
||||
};
|
||||
|
||||
int rockchip_hwmon_init(struct rockchip_temp *data);
|
||||
|
||||
#endif /* _ROCKCHIP_H */
|
||||
453
drivers/hwmon/rockchip-hwmon.c
Executable file
453
drivers/hwmon/rockchip-hwmon.c
Executable file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright (C) rockchip 2014
|
||||
* Author:zhangqing <zhangqing@rock-chips.com>
|
||||
*
|
||||
* License Terms: GNU General Public License v2
|
||||
*
|
||||
* rockchip tsadc does not provide auto tsADC, so to monitor the required temperatures,
|
||||
* a periodic work is used. It is more important to not wake up the CPU than
|
||||
* to perform this job, hence the use of a deferred delay.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include "hwmon-rockchip.h"
|
||||
|
||||
|
||||
#define DEFAULT_MONITOR_DELAY HZ
|
||||
#define DEFAULT_MAX_TEMP 130
|
||||
|
||||
static inline void schedule_monitor(struct rockchip_temp *data)
|
||||
{
|
||||
data->work_active = true;
|
||||
schedule_delayed_work(&data->work, DEFAULT_MONITOR_DELAY);
|
||||
}
|
||||
|
||||
static void threshold_updated(struct rockchip_temp *data)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < data->monitored_sensors; i++)
|
||||
if (data->max[i] != 0 || data->min[i] != 0) {
|
||||
schedule_monitor(data);
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(&data->pdev->dev, "No active thresholds.\n");
|
||||
cancel_delayed_work_sync(&data->work);
|
||||
data->work_active = false;
|
||||
}
|
||||
|
||||
static void tsadc_monitor(struct work_struct *work)
|
||||
{
|
||||
int temp,i, ret;
|
||||
char alarm_node[30];
|
||||
bool updated_min_alarm, updated_max_alarm;
|
||||
struct rockchip_temp *data;
|
||||
|
||||
data = container_of(work, struct rockchip_temp, work.work);
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
for (i = 0; i < data->monitored_sensors; i++) {
|
||||
/* Thresholds are considered inactive if set to 0 */
|
||||
if (data->max[i] == 0 && data->min[i] == 0)
|
||||
continue;
|
||||
|
||||
if (data->max[i] < data->min[i])
|
||||
continue;
|
||||
|
||||
temp = data->ops.read_sensor(data->tsadc_addr[i]);
|
||||
if (temp == 150) {
|
||||
dev_err(&data->pdev->dev, "TSADC read failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
updated_min_alarm = false;
|
||||
updated_max_alarm = false;
|
||||
|
||||
if (data->min[i] != 0) {
|
||||
if (temp < data->min[i]) {
|
||||
if (data->min_alarm[i] == false) {
|
||||
data->min_alarm[i] = true;
|
||||
updated_min_alarm = true;
|
||||
}
|
||||
} else {
|
||||
if (data->min_alarm[i] == true) {
|
||||
data->min_alarm[i] = false;
|
||||
updated_min_alarm = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data->max[i] != 0) {
|
||||
if (temp > data->max[i]) {
|
||||
if (data->max_alarm[i] == false) {
|
||||
data->max_alarm[i] = true;
|
||||
updated_max_alarm = true;
|
||||
}
|
||||
} else if (temp < data->max[i] - data->max_hyst[i]) {
|
||||
if (data->max_alarm[i] == true) {
|
||||
data->max_alarm[i] = false;
|
||||
updated_max_alarm = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updated_min_alarm) {
|
||||
ret = sprintf(alarm_node, "temp%d_min_alarm", i + 1);
|
||||
sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node);
|
||||
}
|
||||
if (updated_max_alarm) {
|
||||
ret = sprintf(alarm_node, "temp%d_max_alarm", i + 1);
|
||||
sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node);
|
||||
}
|
||||
}
|
||||
|
||||
schedule_monitor(data);
|
||||
mutex_unlock(&data->lock);
|
||||
}
|
||||
|
||||
/* HWMON sysfs interfaces */
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
/* Show chip name */
|
||||
return data->ops.show_name(dev, devattr, buf);
|
||||
}
|
||||
|
||||
static ssize_t show_label(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
/* Show each sensor label */
|
||||
return data->ops.show_label(dev, devattr, buf);
|
||||
}
|
||||
|
||||
static ssize_t show_input(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
int temp;
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
u8 tsadc_addr = data->tsadc_addr[attr->index];
|
||||
|
||||
temp = data->ops.read_sensor(tsadc_addr);
|
||||
|
||||
return sprintf(buf, "%d\n", temp);
|
||||
}
|
||||
|
||||
/* Set functions (RW nodes) */
|
||||
static ssize_t set_min(struct device *dev, struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned long val;
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
int res = kstrtol(buf, 10, &val);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
val = clamp_val(val, 0, DEFAULT_MAX_TEMP);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->min[attr->index] = val;
|
||||
threshold_updated(data);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned long val;
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
int res = kstrtol(buf, 10, &val);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
val = clamp_val(val, 0, DEFAULT_MAX_TEMP);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->max[attr->index] = val;
|
||||
threshold_updated(data);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t set_max_hyst(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned long val;
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
int res = kstrtoul(buf, 10, &val);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
val = clamp_val(val, 0, DEFAULT_MAX_TEMP);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->max_hyst[attr->index] = val;
|
||||
threshold_updated(data);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Show functions (RO nodes) */
|
||||
static ssize_t show_min(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
return sprintf(buf, "%ld\n", data->min[attr->index]);
|
||||
}
|
||||
|
||||
static ssize_t show_max(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
return sprintf(buf, "%ld\n", data->max[attr->index]);
|
||||
}
|
||||
|
||||
static ssize_t show_max_hyst(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
return sprintf(buf, "%ld\n", data->max_hyst[attr->index]);
|
||||
}
|
||||
|
||||
static ssize_t show_min_alarm(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
return sprintf(buf, "%d\n", data->min_alarm[attr->index]);
|
||||
}
|
||||
|
||||
static ssize_t show_max_alarm(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
return sprintf(buf, "%d\n", data->max_alarm[attr->index]);
|
||||
}
|
||||
|
||||
static umode_t rockchip_attrs_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct rockchip_temp *data = dev_get_drvdata(dev);
|
||||
|
||||
if (data->ops.is_visible)
|
||||
return data->ops.is_visible(attr, n);
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
/* Chip name, required by hwmon */
|
||||
static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
|
||||
|
||||
/* GPADC - SENSOR0 */
|
||||
static SENSOR_DEVICE_ATTR(temp0_label, S_IRUGO, show_label, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp0_input, S_IRUGO, show_input, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp0_min, S_IWUSR | S_IRUGO, show_min, set_min, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp0_max, S_IWUSR | S_IRUGO, show_max, set_max, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp0_max_hyst, S_IWUSR | S_IRUGO,
|
||||
show_max_hyst, set_max_hyst, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp0_min_alarm, S_IRUGO, show_min_alarm, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp0_max_alarm, S_IRUGO, show_max_alarm, NULL, 0);
|
||||
|
||||
/* GPADC - SENSOR1 */
|
||||
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
|
||||
show_max_hyst, set_max_hyst, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 1);
|
||||
|
||||
/* GPADC - SENSOR2 */
|
||||
static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IWUSR | S_IRUGO,
|
||||
show_max_hyst, set_max_hyst, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_min_alarm, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_max_alarm, NULL, 2);
|
||||
|
||||
/* GPADC - SENSOR3 */
|
||||
static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_label, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IWUSR | S_IRUGO,
|
||||
show_max_hyst, set_max_hyst, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_min_alarm, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_max_alarm, NULL, 3);
|
||||
|
||||
|
||||
struct attribute *rockchip_temp_attributes[] = {
|
||||
&sensor_dev_attr_name.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp0_label.dev_attr.attr,
|
||||
&sensor_dev_attr_temp0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp0_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp0_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp0_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp0_min_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp0_max_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp1_label.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp2_label.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp3_label.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
|
||||
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group rockchip_temp_group = {
|
||||
.attrs = rockchip_temp_attributes,
|
||||
.is_visible = rockchip_attrs_visible,
|
||||
};
|
||||
|
||||
static int rockchip_temp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_temp *data;
|
||||
int err;
|
||||
printk("%s,line=%d\n", __func__,__LINE__);
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->pdev = pdev;
|
||||
mutex_init(&data->lock);
|
||||
|
||||
/* Chip specific initialization */
|
||||
err = rockchip_hwmon_init(data);
|
||||
if (err < 0 || !data->ops.read_sensor || !data->ops.show_name ||
|
||||
!data->ops.show_label)
|
||||
return err;
|
||||
|
||||
INIT_DEFERRABLE_WORK(&data->work, tsadc_monitor);
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &rockchip_temp_group);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
data->hwmon_dev = hwmon_device_register(&pdev->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
|
||||
goto exit_sysfs_group;
|
||||
}
|
||||
return 0;
|
||||
|
||||
exit_sysfs_group:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &rockchip_temp_group);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rockchip_temp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_temp *data = platform_get_drvdata(pdev);
|
||||
|
||||
cancel_delayed_work_sync(&data->work);
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &rockchip_temp_group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_temp_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct rockchip_temp *data = platform_get_drvdata(pdev);
|
||||
|
||||
if (data->work_active)
|
||||
cancel_delayed_work_sync(&data->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_temp_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_temp *data = platform_get_drvdata(pdev);
|
||||
|
||||
if (data->work_active)
|
||||
schedule_monitor(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id rockchip_temp_match[] = {
|
||||
{ .compatible = "rockchip,tsadc" },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver rockchip_temp_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "tsadc",
|
||||
.of_match_table = of_match_ptr(rockchip_temp_match),
|
||||
},
|
||||
.suspend = rockchip_temp_suspend,
|
||||
.resume = rockchip_temp_resume,
|
||||
.probe = rockchip_temp_probe,
|
||||
.remove = rockchip_temp_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(rockchip_temp_driver);
|
||||
|
||||
MODULE_AUTHOR("<rockchip>");
|
||||
MODULE_DESCRIPTION("rockchip temperature driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
469
drivers/hwmon/rockchip_tsadc.c
Executable file
469
drivers/hwmon/rockchip_tsadc.c
Executable file
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson 2010 - 2013
|
||||
* Author: Martin Persson <martin.persson@stericsson.com>
|
||||
* Hongbo Zhang <hongbo.zhang@linaro.org>
|
||||
* License Terms: GNU General Public License v2
|
||||
*
|
||||
* When the AB8500 thermal warning temperature is reached (threshold cannot
|
||||
* be changed by SW), an interrupt is set, and if no further action is taken
|
||||
* within a certain time frame, pm_power off will be called.
|
||||
*
|
||||
* When AB8500 thermal shutdown temperature is reached a hardware shutdown of
|
||||
* the AB8500 will occur.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include <linux/timer.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "hwmon-rockchip.h"
|
||||
|
||||
|
||||
#define DEFAULT_POWER_OFF_DELAY (HZ * 10)
|
||||
/* Number of monitored sensors should not greater than NUM_SENSORS */
|
||||
#define NUM_MONITORED_SENSORS 4
|
||||
|
||||
#define TSADC_USER_CON 0x00
|
||||
#define TSADC_AUTO_CON 0x04
|
||||
|
||||
#define TSADC_CTRL_CH(ch) ((ch) << 0)
|
||||
#define TSADC_CTRL_POWER_UP (1 << 3)
|
||||
#define TSADC_CTRL_START (1 << 4)
|
||||
|
||||
#define TSADC_STAS_BUSY (1 << 12)
|
||||
#define TSADC_STAS_BUSY_MASK (1 << 12)
|
||||
#define TSADC_AUTO_STAS_BUSY (1 << 16)
|
||||
#define TSADC_AUTO_STAS_BUSY_MASK (1 << 16)
|
||||
#define TSADC_SAMPLE_DLY_SEL (1 << 17)
|
||||
#define TSADC_SAMPLE_DLY_SEL_MASK (1 << 17)
|
||||
|
||||
#define TSADC_INT_EN 0x08
|
||||
#define TSADC_INT_PD 0x0c
|
||||
|
||||
#define TSADC_DATA0 0x20
|
||||
#define TSADC_DATA1 0x24
|
||||
#define TSADC_DATA2 0x28
|
||||
#define TSADC_DATA3 0x2c
|
||||
#define TSADC_DATA_MASK 0xfff
|
||||
|
||||
#define TSADC_COMP0_INT 0x30
|
||||
#define TSADC_COMP1_INT 0x34
|
||||
#define TSADC_COMP2_INT 0x38
|
||||
#define TSADC_COMP3_INT 0x3c
|
||||
|
||||
#define TSADC_COMP0_SHUT 0x40
|
||||
#define TSADC_COMP1_SHUT 0x44
|
||||
#define TSADC_COMP2_SHUT 0x48
|
||||
#define TSADC_COMP3_SHUT 0x4c
|
||||
|
||||
#define TSADC_HIGHT_INT_DEBOUNCE 0x60
|
||||
#define TSADC_HIGHT_TSHUT_DEBOUNCE 0x64
|
||||
#define TSADC_HIGHT_INT_DEBOUNCE_TIME 0x03
|
||||
#define TSADC_HIGHT_TSHUT_DEBOUNCE_TIME 0x03
|
||||
|
||||
#define TSADC_AUTO_PERIOD 0x68
|
||||
#define TSADC_AUTO_PERIOD_HT 0x6c
|
||||
#define TSADC_AUTO_PERIOD_TIME 0x10
|
||||
#define TSADC_AUTO_PERIOD_HT_TIME 0x10
|
||||
|
||||
#define TSADC_AUTO_EVENT_NAME "tsadc"
|
||||
|
||||
#define TSADC_COMP_INT_DATA 80
|
||||
#define TSADC_COMP_INT_DATA_MASK 0xfff
|
||||
#define TSADC_COMP_SHUT_DATA 100
|
||||
#define TSADC_COMP_SHUT_DATA_MASK 0xfff
|
||||
#define TSADC_HIGH_TEMP_TO_SHUTDOWN 0 // 1: set gpio0_a0 output 0 ; 0:reset cpu
|
||||
#define TSADC_TEMP_INT_EN 1
|
||||
#define TSADC_TEMP_SHUT_EN 1
|
||||
|
||||
struct rockchip_tsadc_temp {
|
||||
struct delayed_work power_off_work;
|
||||
struct rockchip_temp *rockchip_data;
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
int irq;
|
||||
struct resource *ioarea;
|
||||
struct tsadc_host *tsadc;
|
||||
struct work_struct auto_ht_irq_work;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct workqueue_struct *tsadc_workqueue;
|
||||
};
|
||||
struct tsadc_table
|
||||
{
|
||||
int code;
|
||||
int temp;
|
||||
};
|
||||
|
||||
static const struct tsadc_table table[] =
|
||||
{
|
||||
{TSADC_DATA_MASK, -40},
|
||||
|
||||
{3800, -40},
|
||||
{3792, -35},
|
||||
{3783, -30},
|
||||
{3774, -25},
|
||||
{3765, -20},
|
||||
{3756, -15},
|
||||
{3747, -10},
|
||||
{3737, -5},
|
||||
{3728, 0},
|
||||
{3718, 5},
|
||||
|
||||
{3708, 10},
|
||||
{3698, 15},
|
||||
{3688, 20},
|
||||
{3678, 25},
|
||||
{3667, 30},
|
||||
{3656, 35},
|
||||
{3645, 40},
|
||||
{3634, 45},
|
||||
{3623, 50},
|
||||
{3611, 55},
|
||||
|
||||
{3600, 60},
|
||||
{3588, 65},
|
||||
{3575, 70},
|
||||
{3563, 75},
|
||||
{3550, 80},
|
||||
{3537, 85},
|
||||
{3524, 90},
|
||||
{3510, 95},
|
||||
{3496, 100},
|
||||
{3482, 105},
|
||||
|
||||
{3467, 110},
|
||||
{3452, 115},
|
||||
{3437, 120},
|
||||
{3421, 125},
|
||||
|
||||
{0, 125},
|
||||
};
|
||||
|
||||
static struct rockchip_tsadc_temp *g_dev;
|
||||
|
||||
static DEFINE_MUTEX(tsadc_mutex);
|
||||
|
||||
static u32 tsadc_readl(u32 offset)
|
||||
{
|
||||
return readl_relaxed(g_dev->regs + offset);
|
||||
}
|
||||
|
||||
static void tsadc_writel(u32 val, u32 offset)
|
||||
{
|
||||
writel_relaxed(val, g_dev->regs + offset);
|
||||
}
|
||||
|
||||
void rockchip_tsadc_auto_ht_work(struct work_struct *work)
|
||||
{
|
||||
int ret,val;
|
||||
|
||||
// printk("%s,line=%d\n", __func__,__LINE__);
|
||||
|
||||
mutex_lock(&tsadc_mutex);
|
||||
|
||||
val = tsadc_readl(TSADC_INT_PD);
|
||||
tsadc_writel(val &(~ (1 <<8) ), TSADC_INT_PD);
|
||||
ret = tsadc_readl(TSADC_INT_PD);
|
||||
tsadc_writel(ret | 0xff, TSADC_INT_PD); //clr irq status
|
||||
if ((val & 0x0f) != 0){
|
||||
printk("rockchip tsadc is over temp . %s,line=%d\n", __func__,__LINE__);
|
||||
pm_power_off(); //power_off
|
||||
}
|
||||
mutex_unlock(&tsadc_mutex);
|
||||
}
|
||||
|
||||
static irqreturn_t rockchip_tsadc_auto_ht_interrupt(int irq, void *data)
|
||||
{
|
||||
struct rockchip_tsadc_temp *dev = data;
|
||||
|
||||
printk("%s,line=%d\n", __func__,__LINE__);
|
||||
|
||||
queue_work(dev->workqueue, &dev->auto_ht_irq_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rockchip_tsadc_set_cmpn_int_vale( int chn, int temp)
|
||||
{
|
||||
u32 code = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
|
||||
if (temp <= table[i].temp && temp > table[i -1].temp) {
|
||||
code = table[i].code;
|
||||
}
|
||||
}
|
||||
tsadc_writel((code & TSADC_COMP_INT_DATA_MASK), (TSADC_COMP0_INT + chn*4));
|
||||
|
||||
}
|
||||
|
||||
static void rockchip_tsadc_set_cmpn_shut_vale( int chn, int temp)
|
||||
{
|
||||
u32 code=0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
|
||||
if (temp <= table[i].temp && temp > table[i -1].temp) {
|
||||
code = table[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
tsadc_writel((code & TSADC_COMP_SHUT_DATA_MASK), (TSADC_COMP0_SHUT + chn*4));
|
||||
}
|
||||
|
||||
static void rockchip_tsadc_set_auto_int_en( int chn, int ht_int_en,int tshut_en)
|
||||
{
|
||||
u32 ret;
|
||||
tsadc_writel(0, TSADC_INT_EN);
|
||||
if (ht_int_en){
|
||||
ret = tsadc_readl(TSADC_INT_EN);
|
||||
tsadc_writel( ret | (1 << chn), TSADC_INT_EN);
|
||||
}
|
||||
if (tshut_en){
|
||||
ret = tsadc_readl(TSADC_INT_EN);
|
||||
#ifdef TSADC_HIGH_TEMP_TO_SHUTDOWN
|
||||
tsadc_writel( ret | (1 << (chn + 4)), TSADC_INT_EN);
|
||||
#else
|
||||
tsadc_writel( ret | (1 << (chn + 8)), TSADC_INT_EN);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
static void rockchip_tsadc_auto_mode_set( int chn, int int_temp, int shut_temp,int int_en, int shut_en)
|
||||
{
|
||||
|
||||
u32 ret;
|
||||
|
||||
if (!g_dev || chn > 1)
|
||||
return;
|
||||
|
||||
mutex_lock(&tsadc_mutex);
|
||||
|
||||
clk_enable(g_dev->pclk);
|
||||
clk_enable(g_dev->clk);
|
||||
|
||||
msleep(10);
|
||||
tsadc_writel(0, TSADC_AUTO_CON);
|
||||
tsadc_writel( 1 << (4+chn), TSADC_AUTO_CON);
|
||||
msleep(10);
|
||||
if ((tsadc_readl(TSADC_AUTO_CON) & TSADC_AUTO_STAS_BUSY_MASK) != TSADC_AUTO_STAS_BUSY) {
|
||||
rockchip_tsadc_set_cmpn_int_vale(chn,int_temp);
|
||||
rockchip_tsadc_set_cmpn_shut_vale(chn,shut_temp),
|
||||
|
||||
// tsadc_writel(TSADC_AUTO_PERIOD_TIME, TSADC_AUTO_PERIOD);
|
||||
// tsadc_writel(TSADC_AUTO_PERIOD_HT_TIME, TSADC_AUTO_PERIOD_HT);
|
||||
|
||||
// tsadc_writel(TSADC_HIGHT_INT_DEBOUNCE_TIME, TSADC_HIGHT_INT_DEBOUNCE);
|
||||
// tsadc_writel(TSADC_HIGHT_TSHUT_DEBOUNCE_TIME, TSADC_HIGHT_TSHUT_DEBOUNCE);
|
||||
|
||||
rockchip_tsadc_set_auto_int_en(chn,int_en,shut_en);
|
||||
}
|
||||
|
||||
msleep(10);
|
||||
|
||||
ret = tsadc_readl(TSADC_AUTO_CON);
|
||||
tsadc_writel(ret | (1 <<0) , TSADC_AUTO_CON);
|
||||
|
||||
mutex_unlock(&tsadc_mutex);
|
||||
|
||||
}
|
||||
|
||||
int rockchip_tsadc_set_auto_temp(int chn)
|
||||
{
|
||||
rockchip_tsadc_auto_mode_set(chn, TSADC_COMP_INT_DATA,TSADC_COMP_SHUT_DATA,TSADC_TEMP_INT_EN,TSADC_TEMP_SHUT_EN);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_tsadc_set_auto_temp);
|
||||
|
||||
static void rockchip_tsadc_get(int chn, int *temp, int *code)
|
||||
{
|
||||
*temp = 0;
|
||||
*code = 0;
|
||||
|
||||
if (!g_dev || chn > 4){
|
||||
*temp = 150;
|
||||
return ;
|
||||
}
|
||||
|
||||
mutex_lock(&tsadc_mutex);
|
||||
|
||||
clk_enable(g_dev->pclk);
|
||||
clk_enable(g_dev->clk);
|
||||
|
||||
msleep(10);
|
||||
tsadc_writel(0, TSADC_USER_CON);
|
||||
tsadc_writel(TSADC_CTRL_POWER_UP | TSADC_CTRL_CH(chn), TSADC_USER_CON);
|
||||
msleep(20);
|
||||
if ((tsadc_readl(TSADC_USER_CON) & TSADC_STAS_BUSY_MASK) != TSADC_STAS_BUSY) {
|
||||
int i;
|
||||
*code = tsadc_readl((TSADC_DATA0 + chn*4)) & TSADC_DATA_MASK;
|
||||
for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
|
||||
if ((*code) <= table[i].code && (*code) > table[i + 1].code) {
|
||||
*temp = table[i].temp + (table[i + 1].temp - table[i].temp) * (table[i].code - (*code)) / (table[i].code - table[i + 1].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tsadc_writel(0, TSADC_USER_CON);
|
||||
|
||||
clk_disable(g_dev->clk);
|
||||
clk_disable(g_dev->pclk);
|
||||
|
||||
mutex_unlock(&tsadc_mutex);
|
||||
}
|
||||
|
||||
int rockchip_tsadc_get_temp(int chn)
|
||||
{
|
||||
int temp, code;
|
||||
|
||||
rockchip_tsadc_get(chn, &temp, &code);
|
||||
return temp;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_tsadc_get_temp);
|
||||
|
||||
static ssize_t rockchip_show_name(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "rockchip-tsadc\n");
|
||||
}
|
||||
|
||||
static ssize_t rockchip_show_label(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
char *label;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
int index = attr->index;
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
label = "tsadc0";
|
||||
break;
|
||||
case 1:
|
||||
label = "tsadc1";
|
||||
break;
|
||||
case 2:
|
||||
label = "tsadc2";
|
||||
break;
|
||||
case 3:
|
||||
label = "tsadc3";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", label);
|
||||
}
|
||||
|
||||
|
||||
int rockchip_hwmon_init(struct rockchip_temp *data)
|
||||
{
|
||||
struct rockchip_tsadc_temp *rockchip_tsadc_data;
|
||||
struct resource *res;
|
||||
struct device_node *np = data->pdev->dev.of_node;
|
||||
int ret,irq;
|
||||
u32 rate;
|
||||
|
||||
rockchip_tsadc_data = devm_kzalloc(&data->pdev->dev, sizeof(*rockchip_tsadc_data),
|
||||
GFP_KERNEL);
|
||||
if (!rockchip_tsadc_data)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(data->pdev, IORESOURCE_MEM, 0);
|
||||
rockchip_tsadc_data->regs = devm_request_and_ioremap(&data->pdev->dev, res);
|
||||
if (!rockchip_tsadc_data->regs) {
|
||||
dev_err(&data->pdev->dev, "cannot map IO\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
//irq request
|
||||
irq = platform_get_irq(data->pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&data->pdev->dev, "no irq resource?\n");
|
||||
return -EPERM;
|
||||
}
|
||||
rockchip_tsadc_data->irq = irq;
|
||||
ret = request_threaded_irq(rockchip_tsadc_data->irq, NULL, rockchip_tsadc_auto_ht_interrupt, IRQF_ONESHOT, TSADC_AUTO_EVENT_NAME, rockchip_tsadc_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->pdev->dev, "failed to attach tsadc irq\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
rockchip_tsadc_data->workqueue = create_singlethread_workqueue("rockchip_tsadc");
|
||||
INIT_WORK(&rockchip_tsadc_data->auto_ht_irq_work, rockchip_tsadc_auto_ht_work);
|
||||
|
||||
//clk enable
|
||||
rockchip_tsadc_data->clk = devm_clk_get(&data->pdev->dev, "tsadc");
|
||||
if (IS_ERR(rockchip_tsadc_data->clk)) {
|
||||
dev_err(&data->pdev->dev, "failed to get tsadc clock\n");
|
||||
ret = PTR_ERR(rockchip_tsadc_data->clk);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if(of_property_read_u32(np, "clock-frequency", &rate)) {
|
||||
dev_err(&data->pdev->dev, "Missing clock-frequency property in the DT.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(rockchip_tsadc_data->clk, rate);
|
||||
if(ret < 0) {
|
||||
dev_err(&data->pdev->dev, "failed to set adc clk\n");
|
||||
return -EPERM;
|
||||
}
|
||||
clk_prepare_enable(rockchip_tsadc_data->clk);
|
||||
|
||||
rockchip_tsadc_data->pclk = devm_clk_get(&data->pdev->dev, "pclk_tsadc");
|
||||
if (IS_ERR(rockchip_tsadc_data->pclk)) {
|
||||
dev_err(&data->pdev->dev, "failed to get tsadc pclk\n");
|
||||
ret = PTR_ERR(rockchip_tsadc_data->pclk);
|
||||
return -EPERM;
|
||||
}
|
||||
clk_prepare_enable(rockchip_tsadc_data->pclk);
|
||||
|
||||
platform_set_drvdata(data->pdev, rockchip_tsadc_data);
|
||||
g_dev = rockchip_tsadc_data;
|
||||
data->plat_data = rockchip_tsadc_data;
|
||||
|
||||
data->monitored_sensors = NUM_MONITORED_SENSORS;
|
||||
data->ops.read_sensor = rockchip_tsadc_get_temp;
|
||||
data->ops.show_name = rockchip_show_name;
|
||||
data->ops.show_label = rockchip_show_label;
|
||||
data->ops.is_visible = NULL;
|
||||
|
||||
// rockchip_tsadc_set_auto_temp(0);
|
||||
|
||||
dev_info(&data->pdev->dev, "initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_hwmon_init);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for TSADC");
|
||||
MODULE_AUTHOR("zhangqing, zhangqing@rock-chips.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
Reference in New Issue
Block a user