1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
--- a/drivers/power/twl4030_bci_battery.c 2010-01-16 13:48:46.745838675 -0800
+++ b/drivers/power/twl4030_bci_battery.c 2010-01-16 13:41:47.317595764 -0800
@@ -598,11 +598,31 @@
static int twl4030battery_voltage(void)
{
int volt = read_bci_val(T2_BATTERY_VOLT);
-
return (volt * VOLT_STEP_SIZE) / VOLT_PSR_R;
}
/*
+ * Get latest battery voltage (using MADC)
+ *
+ * When the BCI is not charging, the BCI voltage registers are not
+ * updated and are 'frozen' but the data can be read through the
+ * MADC.
+ */
+static int twl4030battery_voltage_madc(void)
+{
+ struct twl4030_madc_request req;
+
+ req.channels = (1 << 12);
+ req.do_avg = 0;
+ req.method = TWL4030_MADC_SW1;
+ req.active = 0;
+ req.func_cb = NULL;
+ twl4030_madc_conversion(&req);
+
+ return (((int) req.rbuf[12]) * VOLT_STEP_SIZE) / VOLT_PSR_R;
+}
+
+/*
* Return the battery current
* Or < 0 on failure.
*/
@@ -840,21 +860,21 @@
static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
{
- di->temp_C = twl4030battery_temperature(di);
- di->voltage_uV = twl4030battery_voltage();
- di->current_uA = twl4030battery_current();
+ if(di->charge_status != POWER_SUPPLY_STATUS_DISCHARGING) {
+ di->temp_C = twl4030battery_temperature(di);
+ di->voltage_uV = twl4030battery_voltage();
+ di->current_uA = twl4030battery_current();
+ }
}
static void
twl4030_bci_battery_update_status(struct twl4030_bci_device_info *di)
{
- twl4030_bci_battery_read_status(di);
- di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
-
if (power_supply_am_i_supplied(&di->bat))
di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
else
di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ twl4030_bci_battery_read_status(di);
}
static void twl4030_bci_battery_work(struct work_struct *work)
@@ -960,7 +980,15 @@
return count;
}
+
+static ssize_t
+show_voltage(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", twl4030battery_voltage_madc());
+}
+
static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
+static DEVICE_ATTR(voltage_now_madc, S_IRUGO, show_voltage, NULL);
static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
@@ -998,10 +1026,23 @@
switch (psp) {
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = di->voltage_uV;
+ {
+ /* Get latest data from MADC -- not done periodically by
+ worker as this is more expensive, so only do it when we
+ are actually asked for the data... */
+ if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)
+ val->intval = twl4030battery_voltage_madc();
+ else
+ val->intval = di->voltage_uV;
+
break;
+ }
case POWER_SUPPLY_PROP_CURRENT_NOW:
- val->intval = di->current_uA;
+ /* FIXME: Get from MADC */
+ if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)
+ val->intval = 0;
+ else
+ val->intval = di->current_uA;
break;
case POWER_SUPPLY_PROP_TEMP:
val->intval = di->temp_C;
@@ -1016,6 +1057,12 @@
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CAPACITY:
+ /* Get latest data from MADC -- not done periodically by
+ worker as this is more expensive, so only do it when we
+ are actually asked for the data... */
+ if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)
+ di->voltage_uV = twl4030battery_voltage_madc();
+
/*
* need to get the correct percentage value per the
* battery characteristics. Approx values for now.
@@ -1145,6 +1192,7 @@
}
}
+ ret = device_create_file(di->bat.dev, &dev_attr_voltage_now_madc);
ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
if (ret) {
dev_err(&pdev->dev, "failed to create sysfs entries\n");
|