aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/olpc_battery.c191
1 files changed, 118 insertions, 73 deletions
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index f8dc2b18bb49..d5fe6f0c9de0 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -86,6 +86,117 @@ static struct power_supply olpc_ac = {
86 86
87static char bat_serial[17]; /* Ick */ 87static char bat_serial[17]; /* Ick */
88 88
89static int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte)
90{
91 if (olpc_platform_info.ecver > 0x44) {
92 if (ec_byte & BAT_STAT_CHARGING)
93 val->intval = POWER_SUPPLY_STATUS_CHARGING;
94 else if (ec_byte & BAT_STAT_DISCHARGING)
95 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
96 else if (ec_byte & BAT_STAT_FULL)
97 val->intval = POWER_SUPPLY_STATUS_FULL;
98 else /* er,... */
99 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
100 } else {
101 /* Older EC didn't report charge/discharge bits */
102 if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
103 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
104 else if (ec_byte & BAT_STAT_FULL)
105 val->intval = POWER_SUPPLY_STATUS_FULL;
106 else /* Not _necessarily_ true but EC doesn't tell all yet */
107 val->intval = POWER_SUPPLY_STATUS_CHARGING;
108 }
109
110 return 0;
111}
112
113static int olpc_bat_get_health(union power_supply_propval *val)
114{
115 uint8_t ec_byte;
116 int ret;
117
118 ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1);
119 if (ret)
120 return ret;
121
122 switch (ec_byte) {
123 case 0:
124 val->intval = POWER_SUPPLY_HEALTH_GOOD;
125 break;
126
127 case BAT_ERR_OVERTEMP:
128 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
129 break;
130
131 case BAT_ERR_OVERVOLTAGE:
132 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
133 break;
134
135 case BAT_ERR_INFOFAIL:
136 case BAT_ERR_OUT_OF_CONTROL:
137 case BAT_ERR_ID_FAIL:
138 case BAT_ERR_ACR_FAIL:
139 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
140 break;
141
142 default:
143 /* Eep. We don't know this failure code */
144 ret = -EIO;
145 }
146
147 return ret;
148}
149
150static int olpc_bat_get_mfr(union power_supply_propval *val)
151{
152 uint8_t ec_byte;
153 int ret;
154
155 ec_byte = BAT_ADDR_MFR_TYPE;
156 ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
157 if (ret)
158 return ret;
159
160 switch (ec_byte >> 4) {
161 case 1:
162 val->strval = "Gold Peak";
163 break;
164 case 2:
165 val->strval = "BYD";
166 break;
167 default:
168 val->strval = "Unknown";
169 break;
170 }
171
172 return ret;
173}
174
175static int olpc_bat_get_tech(union power_supply_propval *val)
176{
177 uint8_t ec_byte;
178 int ret;
179
180 ec_byte = BAT_ADDR_MFR_TYPE;
181 ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
182 if (ret)
183 return ret;
184
185 switch (ec_byte & 0xf) {
186 case 1:
187 val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
188 break;
189 case 2:
190 val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
191 break;
192 default:
193 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
194 break;
195 }
196
197 return ret;
198}
199
89/********************************************************************* 200/*********************************************************************
90 * Battery properties 201 * Battery properties
91 *********************************************************************/ 202 *********************************************************************/
@@ -113,25 +224,10 @@ static int olpc_bat_get_property(struct power_supply *psy,
113 224
114 switch (psp) { 225 switch (psp) {
115 case POWER_SUPPLY_PROP_STATUS: 226 case POWER_SUPPLY_PROP_STATUS:
116 if (olpc_platform_info.ecver > 0x44) { 227 ret = olpc_bat_get_status(val, ec_byte);
117 if (ec_byte & BAT_STAT_CHARGING) 228 if (ret)
118 val->intval = POWER_SUPPLY_STATUS_CHARGING; 229 return ret;
119 else if (ec_byte & BAT_STAT_DISCHARGING) 230 break;
120 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
121 else if (ec_byte & BAT_STAT_FULL)
122 val->intval = POWER_SUPPLY_STATUS_FULL;
123 else /* er,... */
124 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
125 } else {
126 /* Older EC didn't report charge/discharge bits */
127 if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
128 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
129 else if (ec_byte & BAT_STAT_FULL)
130 val->intval = POWER_SUPPLY_STATUS_FULL;
131 else /* Not _necessarily_ true but EC doesn't tell all yet */
132 val->intval = POWER_SUPPLY_STATUS_CHARGING;
133 break;
134 }
135 case POWER_SUPPLY_PROP_PRESENT: 231 case POWER_SUPPLY_PROP_PRESENT:
136 val->intval = !!(ec_byte & BAT_STAT_PRESENT); 232 val->intval = !!(ec_byte & BAT_STAT_PRESENT);
137 break; 233 break;
@@ -140,72 +236,21 @@ static int olpc_bat_get_property(struct power_supply *psy,
140 if (ec_byte & BAT_STAT_DESTROY) 236 if (ec_byte & BAT_STAT_DESTROY)
141 val->intval = POWER_SUPPLY_HEALTH_DEAD; 237 val->intval = POWER_SUPPLY_HEALTH_DEAD;
142 else { 238 else {
143 ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1); 239 ret = olpc_bat_get_health(val);
144 if (ret) 240 if (ret)
145 return ret; 241 return ret;
146
147 switch (ec_byte) {
148 case 0:
149 val->intval = POWER_SUPPLY_HEALTH_GOOD;
150 break;
151
152 case BAT_ERR_OVERTEMP:
153 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
154 break;
155
156 case BAT_ERR_OVERVOLTAGE:
157 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
158 break;
159
160 case BAT_ERR_INFOFAIL:
161 case BAT_ERR_OUT_OF_CONTROL:
162 case BAT_ERR_ID_FAIL:
163 case BAT_ERR_ACR_FAIL:
164 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
165 break;
166
167 default:
168 /* Eep. We don't know this failure code */
169 return -EIO;
170 }
171 } 242 }
172 break; 243 break;
173 244
174 case POWER_SUPPLY_PROP_MANUFACTURER: 245 case POWER_SUPPLY_PROP_MANUFACTURER:
175 ec_byte = BAT_ADDR_MFR_TYPE; 246 ret = olpc_bat_get_mfr(val);
176 ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
177 if (ret) 247 if (ret)
178 return ret; 248 return ret;
179
180 switch (ec_byte >> 4) {
181 case 1:
182 val->strval = "Gold Peak";
183 break;
184 case 2:
185 val->strval = "BYD";
186 break;
187 default:
188 val->strval = "Unknown";
189 break;
190 }
191 break; 249 break;
192 case POWER_SUPPLY_PROP_TECHNOLOGY: 250 case POWER_SUPPLY_PROP_TECHNOLOGY:
193 ec_byte = BAT_ADDR_MFR_TYPE; 251 ret = olpc_bat_get_tech(val);
194 ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
195 if (ret) 252 if (ret)
196 return ret; 253 return ret;
197
198 switch (ec_byte & 0xf) {
199 case 1:
200 val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
201 break;
202 case 2:
203 val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
204 break;
205 default:
206 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
207 break;
208 }
209 break; 254 break;
210 case POWER_SUPPLY_PROP_VOLTAGE_AVG: 255 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
211 ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2); 256 ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2);