summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/ab8500.c107
-rw-r--r--drivers/power/ab8500_btemp.c28
2 files changed, 107 insertions, 28 deletions
diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c
index 1cfab4948e4..7469ffaa6cb 100644
--- a/drivers/hwmon/ab8500.c
+++ b/drivers/hwmon/ab8500.c
@@ -38,6 +38,7 @@
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/mfd/ab8500/gpadc.h>
+#include <linux/mfd/ab8500/bm.h>
#include <linux/pm.h>
/*
@@ -50,13 +51,17 @@
#define NUM_SENSORS 5
-/* The driver monitors GPADC - ADC_AUX1 and ADC_AUX2 */
-#define NUM_MONITORED_SENSORS 2
+/*
+ * The driver monitors GPADC - ADC_AUX1, ADC_AUX2, BTEMP_BALL
+ * and BAT_CTRL.
+ */
+#define NUM_MONITORED_SENSORS 4
struct ab8500_temp {
struct platform_device *pdev;
struct device *hwmon_dev;
struct ab8500_gpadc *gpadc;
+ struct ab8500_btemp *btemp;
u8 gpadc_addr[NUM_SENSORS];
unsigned long min[NUM_SENSORS];
unsigned long max[NUM_SENSORS];
@@ -131,10 +136,21 @@ static void gpadc_monitor(struct work_struct *work)
&& data->min[i] == 0)
continue;
- val = ab8500_gpadc_convert(data->gpadc, data->gpadc_addr[i]);
- if (val < 0) {
- dev_err(&data->pdev->dev, "GPADC read failed\n");
- continue;
+ /*
+ * Special treatment for the BAT_CTRL node, since this
+ * temperature measurement is more complex than just
+ * an ADC readout
+ */
+ if (data->gpadc_addr[i] == BAT_CTRL) {
+ val = ab8500_btemp_get_batctrl_temp(data->btemp);
+ } else {
+ val = ab8500_gpadc_convert(data->gpadc,
+ data->gpadc_addr[i]);
+ if (val < 0) {
+ dev_err(&data->pdev->dev,
+ "GPADC read failed\n");
+ continue;
+ }
}
mutex_lock(&data->lock);
@@ -322,11 +338,11 @@ static ssize_t show_label(struct device *dev,
name = "bat_temp";
break;
case 4:
- name = "ab8500";
- break;
- case 5:
name = "bat_ctrl";
break;
+ case 5:
+ name = "ab8500";
+ break;
default:
return -EINVAL;
}
@@ -342,9 +358,18 @@ static ssize_t show_input(struct device *dev,
/* hwmon attr index starts at 1, thus "attr->index-1" below */
u8 gpadc_addr = data->gpadc_addr[attr->index - 1];
- val = ab8500_gpadc_convert(data->gpadc, gpadc_addr);
- if (val < 0)
- dev_err(&data->pdev->dev, "GPADC read failed\n");
+ /*
+ * Special treatment for the BAT_CTRL node, since this
+ * temperature measurement is more complex than just
+ * an ADC readout
+ */
+ if (gpadc_addr == BAT_CTRL) {
+ val = ab8500_btemp_get_batctrl_temp(data->btemp);
+ } else {
+ val = ab8500_gpadc_convert(data->gpadc, gpadc_addr);
+ if (val < 0)
+ dev_err(&data->pdev->dev, "GPADC read failed\n");
+ }
return sprintf(buf, "%d\n", val);
}
@@ -546,15 +571,31 @@ static SENSOR_DEVICE_ATTR(temp2_max_hyst_alarm, S_IRUGO,
/* GPADC - BTEMP_BALL */
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);
+static SENSOR_DEVICE_ATTR(temp3_max_hyst_alarm, S_IRUGO,
+ show_max_hyst_alarm, NULL, 3);
-/* AB8500 */
+/* GPADC - BAT_CTRL */
static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO,
- show_crit_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_min, set_min, 4);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_max, set_max, 4);
+static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IWUSR | S_IRUGO,
+ show_max_hyst, set_max_hyst, 4);
+static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_min_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp4_max_hyst_alarm, S_IRUGO,
+ show_max_hyst_alarm, NULL, 4);
-/* GPADC - BAT_CTRL */
+/* AB8500 */
static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_label, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO,
+ show_crit_alarm, NULL, 5);
static struct attribute *ab8500_temp_attributes[] = {
&sensor_dev_attr_temp_power_off_delay.dev_attr.attr,
@@ -581,12 +622,24 @@ static struct attribute *ab8500_temp_attributes[] = {
/* GPADC - BTEMP_BALL */
&sensor_dev_attr_temp3_label.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
- /* AB8500 */
- &sensor_dev_attr_temp4_label.dev_attr.attr,
- &sensor_dev_attr_temp4_crit_alarm.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,
+ &sensor_dev_attr_temp3_max_hyst_alarm.dev_attr.attr,
/* GPADC - BAT_CTRL */
+ &sensor_dev_attr_temp4_label.dev_attr.attr,
+ &sensor_dev_attr_temp4_input.dev_attr.attr,
+ &sensor_dev_attr_temp4_min.dev_attr.attr,
+ &sensor_dev_attr_temp4_max.dev_attr.attr,
+ &sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp4_max_hyst_alarm.dev_attr.attr,
+ /* AB8500 */
&sensor_dev_attr_temp5_label.dev_attr.attr,
- &sensor_dev_attr_temp5_input.dev_attr.attr,
+ &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
NULL
};
@@ -605,9 +658,9 @@ static irqreturn_t ab8500_temp_irq_handler(int irq, void *irq_data)
* used for AB8500 thermal warning from HW.
*/
mutex_lock(&data->lock);
- data->crit_alarm[3] = 1;
+ data->crit_alarm[4] = 1;
mutex_unlock(&data->lock);
- sysfs_notify(&pdev->dev.kobj, NULL, "temp4_crit_alarm");
+ sysfs_notify(&pdev->dev.kobj, NULL, "temp5_crit_alarm");
dev_info(&pdev->dev, "AB8500 thermal warning, power off in %lu s\n",
data->power_off_delay);
delay_in_jiffies = msecs_to_jiffies(data->power_off_delay);
@@ -645,6 +698,7 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev)
goto exit;
data->gpadc = ab8500_gpadc_get();
+ data->btemp = ab8500_btemp_get();
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -665,21 +719,18 @@ static int __devinit ab8500_temp_probe(struct platform_device *pdev)
* GPADC - ADC_AUX2, connected to NTC R2150 near DB8500 on HREF
* Hence, temp#_min/max/max_hyst refer to millivolts and not
* millidegrees
+ * This is not the case for BAT_CTRL where millidegrees is used
*
* HREF HW does not support reading AB8500 temperature. BUT an
* AB8500 IRQ will be launched if die crit temp limit is reached.
*
- * Also:
- * Battery temperature (BatTemp and BatCtrl) thresholds will
- * not be exposed via hwmon.
- *
* Make sure indexes correspond to the attribute indexes
* used when calling SENSOR_DEVICE_ATRR
*/
data->gpadc_addr[0] = ADC_AUX1;
data->gpadc_addr[1] = ADC_AUX2;
data->gpadc_addr[2] = BTEMP_BALL;
- data->gpadc_addr[4] = BAT_CTRL;
+ data->gpadc_addr[3] = BAT_CTRL;
mutex_init(&data->lock);
data->pdev = pdev;
data->power_off_delay = DEFAULT_POWER_OFF_DELAY;
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index b8053d577ab..336384c882f 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -67,6 +67,7 @@ struct ab8500_btemp_ranges {
/**
* struct ab8500_btemp - ab8500 BTEMP device information
* @dev: Pointer to the structure device
+ * @node: List of AB8500 BTEMPs, hence prepared for reentrance
* @chip_id: Chip-Id of the AB8500
* @curr_source: What current source we use, in uA
* @bat_temp: Battery temperature in degree Celcius
@@ -83,6 +84,7 @@ struct ab8500_btemp_ranges {
*/
struct ab8500_btemp {
struct device *dev;
+ struct list_head node;
u8 chip_id;
int curr_source;
int bat_temp;
@@ -106,6 +108,20 @@ static enum power_supply_property ab8500_btemp_props[] = {
POWER_SUPPLY_PROP_TEMP,
};
+static LIST_HEAD(ab8500_btemp_list);
+
+/**
+ * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP
+ * (i.e. the first BTEMP in the instance list)
+ */
+struct ab8500_btemp *ab8500_btemp_get(void)
+{
+ struct ab8500_btemp *btemp;
+ btemp = list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node);
+
+ return btemp;
+}
+
/**
* ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
* @di: pointer to the ab8500_btemp structure
@@ -723,6 +739,17 @@ static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
}
/**
+ * ab8500_btemp_get_batctrl_temp() - get the temperature
+ * @btemp: pointer to the btemp structure
+ *
+ * Returns the batctrl temperature in millidegrees
+ */
+int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
+{
+ return btemp->bat_temp * 1000;
+}
+
+/**
* ab8500_btemp_get_property() - get the btemp properties
* @psy: pointer to the power_supply structure
* @psp: pointer to the power_supply_property structure
@@ -1032,6 +1059,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
/* Kick off periodic temperature measurements */
ab8500_btemp_periodic(di, true);
+ list_add_tail(&di->node, &ab8500_btemp_list);
return ret;