olpc_battery.c revision 5619d0ba97cd336a100121cf8f2968c4b1f6c848
1fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse/* 2fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * Battery driver for One Laptop Per Child board. 3fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * 4690e85a3957291f4cfe0cac22d97994ec7e5ee45David Woodhouse * Copyright © 2006-2010 David Woodhouse <dwmw2@infradead.org> 5fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * 6fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * This program is free software; you can redistribute it and/or modify 7fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * it under the terms of the GNU General Public License version 2 as 8fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * published by the Free Software Foundation. 9fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse */ 10fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 1104a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon#include <linux/kernel.h> 12fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <linux/module.h> 13144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon#include <linux/types.h> 14fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <linux/err.h> 15144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon#include <linux/device.h> 16fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <linux/platform_device.h> 17fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <linux/power_supply.h> 18fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <linux/jiffies.h> 19fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <linux/sched.h> 20fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#include <asm/olpc.h> 21fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 22fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 23fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */ 24fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_CURRENT 0x11 /* int16_t, *15.625/120, mA */ 2575d8807962fc7529b4946e9ec92cae197be5a967Andres Salomon#define EC_BAT_ACR 0x12 /* int16_t, *6250/15, µAh */ 26fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_TEMP 0x13 /* uint16_t, *100/256, °C */ 27fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_AMB_TEMP 0x14 /* uint16_t, *100/256, °C */ 28fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_STATUS 0x15 /* uint8_t, bitmask */ 29fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_SOC 0x16 /* uint8_t, percentage */ 30fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_SERIAL 0x17 /* uint8_t[6] */ 31fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_EEPROM 0x18 /* uint8_t adr as input, uint8_t output */ 32fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define EC_BAT_ERRCODE 0x1f /* uint8_t, bitmask */ 33fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 34fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_PRESENT 0x01 35fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_FULL 0x02 36fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_LOW 0x04 37fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_DESTROY 0x08 38fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_AC 0x10 39fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_CHARGING 0x20 40fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_STAT_DISCHARGING 0x40 418f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon#define BAT_STAT_TRICKLE 0x80 42fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 43fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_INFOFAIL 0x02 44fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_OVERVOLTAGE 0x04 45fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_OVERTEMP 0x05 46fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_GAUGESTOP 0x06 47fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_OUT_OF_CONTROL 0x07 48fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_ID_FAIL 0x09 49fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ERR_ACR_FAIL 0x10 50fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 51fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse#define BAT_ADDR_MFR_TYPE 0x5F 52fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 53fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse/********************************************************************* 54fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * Power 55fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse *********************************************************************/ 56fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 57fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic int olpc_ac_get_prop(struct power_supply *psy, 58fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse enum power_supply_property psp, 59fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse union power_supply_propval *val) 60fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 61fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse int ret = 0; 62fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse uint8_t status; 63fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 64fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse switch (psp) { 65fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_ONLINE: 66fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1); 67fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 68fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 69fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 70fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse val->intval = !!(status & BAT_STAT_AC); 71fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 72fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse default: 73fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = -EINVAL; 74fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 75fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 76fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 77fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 78fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 79fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic enum power_supply_property olpc_ac_props[] = { 80fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_ONLINE, 81fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse}; 82fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 83fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic struct power_supply olpc_ac = { 84fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .name = "olpc-ac", 85fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .type = POWER_SUPPLY_TYPE_MAINS, 86fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .properties = olpc_ac_props, 87fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .num_properties = ARRAY_SIZE(olpc_ac_props), 88fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .get_property = olpc_ac_get_prop, 89fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse}; 90fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 911ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhousestatic char bat_serial[17]; /* Ick */ 921ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse 93b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomonstatic int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte) 94b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon{ 95b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (olpc_platform_info.ecver > 0x44) { 968f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon if (ec_byte & (BAT_STAT_CHARGING | BAT_STAT_TRICKLE)) 97b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_CHARGING; 98b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon else if (ec_byte & BAT_STAT_DISCHARGING) 99b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 100b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon else if (ec_byte & BAT_STAT_FULL) 101b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_FULL; 102b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon else /* er,... */ 103b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 104b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon } else { 105b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon /* Older EC didn't report charge/discharge bits */ 106b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */ 107b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 108b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon else if (ec_byte & BAT_STAT_FULL) 109b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_FULL; 110b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon else /* Not _necessarily_ true but EC doesn't tell all yet */ 111b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_STATUS_CHARGING; 112b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon } 113b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 114b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return 0; 115b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon} 116b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 117b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomonstatic int olpc_bat_get_health(union power_supply_propval *val) 118b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon{ 119b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon uint8_t ec_byte; 120b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon int ret; 121b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 122b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1); 123b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (ret) 124b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 125b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 126b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon switch (ec_byte) { 127b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case 0: 128b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_HEALTH_GOOD; 129b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 130b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 131b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case BAT_ERR_OVERTEMP: 132b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 133b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 134b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 135b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case BAT_ERR_OVERVOLTAGE: 136b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 137b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 138b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 139b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case BAT_ERR_INFOFAIL: 140b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case BAT_ERR_OUT_OF_CONTROL: 141b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case BAT_ERR_ID_FAIL: 142b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case BAT_ERR_ACR_FAIL: 143b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 144b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 145b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 146b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon default: 147b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon /* Eep. We don't know this failure code */ 148b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = -EIO; 149b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon } 150b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 151b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 152b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon} 153b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 154b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomonstatic int olpc_bat_get_mfr(union power_supply_propval *val) 155b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon{ 156b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon uint8_t ec_byte; 157b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon int ret; 158b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 159b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ec_byte = BAT_ADDR_MFR_TYPE; 160b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); 161b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (ret) 162b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 163b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 164b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon switch (ec_byte >> 4) { 165b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case 1: 166b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->strval = "Gold Peak"; 167b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 168b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case 2: 169b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->strval = "BYD"; 170b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 171b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon default: 172b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->strval = "Unknown"; 173b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 174b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon } 175b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 176b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 177b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon} 178b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 179b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomonstatic int olpc_bat_get_tech(union power_supply_propval *val) 180b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon{ 181b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon uint8_t ec_byte; 182b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon int ret; 183b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 184b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ec_byte = BAT_ADDR_MFR_TYPE; 185b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); 186b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (ret) 187b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 188b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 189b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon switch (ec_byte & 0xf) { 190b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case 1: 191b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH; 192b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 193b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon case 2: 194b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe; 195b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 196b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon default: 197b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 198b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 199b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon } 200b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 201b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 202b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon} 203b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon 204b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbestatic int olpc_bat_get_charge_full_design(union power_supply_propval *val) 205b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe{ 206b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe uint8_t ec_byte; 207b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe union power_supply_propval tech; 208b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe int ret, mfr; 209b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 210b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe ret = olpc_bat_get_tech(&tech); 211b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe if (ret) 212b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return ret; 213b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 214b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe ec_byte = BAT_ADDR_MFR_TYPE; 215b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); 216b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe if (ret) 217b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return ret; 218b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 219b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe mfr = ec_byte >> 4; 220b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 221b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe switch (tech.intval) { 222b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case POWER_SUPPLY_TECHNOLOGY_NiMH: 223b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe switch (mfr) { 224b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case 1: /* Gold Peak */ 225b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe val->intval = 3000000*.8; 226b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 227b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe default: 228b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return -EIO; 229b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe } 230b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 231b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 232b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case POWER_SUPPLY_TECHNOLOGY_LiFe: 233b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe switch (mfr) { 234b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case 1: /* Gold Peak */ 235b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe val->intval = 2800000; 236b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 237b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case 2: /* BYD */ 238b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe val->intval = 3100000; 239b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 240b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe default: 241b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return -EIO; 242b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe } 243b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 244b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 245b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe default: 246b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return -EIO; 247b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe } 248b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 249b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return ret; 250b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe} 251b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe 25220fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbestatic int olpc_bat_get_charge_now(union power_supply_propval *val) 25320fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe{ 25420fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe uint8_t soc; 25520fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe union power_supply_propval full; 25620fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe int ret; 25720fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe 25820fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &soc, 1); 25920fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe if (ret) 26020fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe return ret; 26120fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe 26220fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe ret = olpc_bat_get_charge_full_design(&full); 26320fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe if (ret) 26420fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe return ret; 26520fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe 26620fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe val->intval = soc * (full.intval / 100); 26720fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe return 0; 26820fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe} 26920fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe 2705619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smithstatic int olpc_bat_get_voltage_max_design(union power_supply_propval *val) 2715619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith{ 2725619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith uint8_t ec_byte; 2735619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith union power_supply_propval tech; 2745619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith int mfr; 2755619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith int ret; 2765619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 2775619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith ret = olpc_bat_get_tech(&tech); 2785619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith if (ret) 2795619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return ret; 2805619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 2815619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith ec_byte = BAT_ADDR_MFR_TYPE; 2825619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); 2835619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith if (ret) 2845619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return ret; 2855619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 2865619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith mfr = ec_byte >> 4; 2875619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 2885619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith switch (tech.intval) { 2895619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith case POWER_SUPPLY_TECHNOLOGY_NiMH: 2905619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith switch (mfr) { 2915619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith case 1: /* Gold Peak */ 2925619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith val->intval = 6000000; 2935619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith break; 2945619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith default: 2955619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return -EIO; 2965619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith } 2975619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith break; 2985619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 2995619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith case POWER_SUPPLY_TECHNOLOGY_LiFe: 3005619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith switch (mfr) { 3015619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith case 1: /* Gold Peak */ 3025619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith val->intval = 6400000; 3035619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith break; 3045619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith case 2: /* BYD */ 3055619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith val->intval = 6500000; 3065619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith break; 3075619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith default: 3085619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return -EIO; 3095619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith } 3105619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith break; 3115619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 3125619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith default: 3135619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return -EIO; 3145619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith } 3155619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 3165619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return ret; 3175619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith} 3185619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith 319fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse/********************************************************************* 320fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * Battery properties 321fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse *********************************************************************/ 322fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic int olpc_bat_get_property(struct power_supply *psy, 323fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse enum power_supply_property psp, 324fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse union power_supply_propval *val) 325fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 326fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse int ret = 0; 3278e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison __be16 ec_word; 328fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse uint8_t ec_byte; 3298e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison __be64 ser_buf; 330fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 331fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1); 332fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 333fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 334fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 335fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse /* Theoretically there's a race here -- the battery could be 336fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse removed immediately after we check whether it's present, and 337fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse then we query for some other property of the now-absent battery. 338fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse It doesn't matter though -- the EC will return the last-known 339fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse information, and it's as if we just ran that _little_ bit faster 340fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse and managed to read it out before the battery went away. */ 3418f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon if (!(ec_byte & (BAT_STAT_PRESENT | BAT_STAT_TRICKLE)) && 3428f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon psp != POWER_SUPPLY_PROP_PRESENT) 343fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return -ENODEV; 344fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 345fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse switch (psp) { 346fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_STATUS: 347b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_status(val, ec_byte); 348b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (ret) 349b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 350b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 351ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon case POWER_SUPPLY_PROP_CHARGE_TYPE: 352ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon if (ec_byte & BAT_STAT_TRICKLE) 353ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 354ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon else if (ec_byte & BAT_STAT_CHARGING) 355ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 356ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon else 357ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 358ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon break; 359fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_PRESENT: 3608f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon val->intval = !!(ec_byte & (BAT_STAT_PRESENT | 3618f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon BAT_STAT_TRICKLE)); 362fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 363fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 364fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_HEALTH: 365fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ec_byte & BAT_STAT_DESTROY) 366fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse val->intval = POWER_SUPPLY_HEALTH_DEAD; 367fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse else { 368b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_health(val); 369fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 370fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 371fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 372fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 373fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 374fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_MANUFACTURER: 375b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_mfr(val); 376fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 377fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 378fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 379fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_TECHNOLOGY: 380b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_tech(val); 381fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 382fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 383fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 384fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_VOLTAGE_AVG: 38522fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe case POWER_SUPPLY_PROP_VOLTAGE_NOW: 386fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2); 387fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 388fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 389fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 3907cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32; 391fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 392fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_CURRENT_AVG: 39322fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe case POWER_SUPPLY_PROP_CURRENT_NOW: 394fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); 395fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 396fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 397fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 3987cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120; 399fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 400fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_CAPACITY: 401fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1); 402fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 403fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 404fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse val->intval = ec_byte; 405fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 406b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 407b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon if (ec_byte & BAT_STAT_FULL) 408b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 409b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon else if (ec_byte & BAT_STAT_LOW) 410b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 411b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon else 412b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 413b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon break; 414b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 415b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe ret = olpc_bat_get_charge_full_design(val); 416b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe if (ret) 417b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return ret; 418b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 41920fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe case POWER_SUPPLY_PROP_CHARGE_NOW: 42020fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe ret = olpc_bat_get_charge_now(val); 42120fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe if (ret) 42220fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe return ret; 42320fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe break; 424fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_TEMP: 425fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); 426fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 427fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 4288e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison 4297cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256; 430fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 431fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_TEMP_AMBIENT: 432fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2); 433fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 434fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 435fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 4368e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison val->intval = (int)be16_to_cpu(ec_word) * 100 / 256; 437fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 4388e552c36d90c03d2cabf5373788998966751b609Andres Salomon case POWER_SUPPLY_PROP_CHARGE_COUNTER: 4398e552c36d90c03d2cabf5373788998966751b609Andres Salomon ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2); 4408e552c36d90c03d2cabf5373788998966751b609Andres Salomon if (ret) 4418e552c36d90c03d2cabf5373788998966751b609Andres Salomon return ret; 4428e552c36d90c03d2cabf5373788998966751b609Andres Salomon 4437cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15; 4448e552c36d90c03d2cabf5373788998966751b609Andres Salomon break; 4451ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse case POWER_SUPPLY_PROP_SERIAL_NUMBER: 4461ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8); 4471ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse if (ret) 4481ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse return ret; 4491ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse 4501ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf)); 4511ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse val->strval = bat_serial; 4521ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse break; 4535619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 4545619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith ret = olpc_bat_get_voltage_max_design(val); 4555619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith if (ret) 4565619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith return ret; 4575619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith break; 458fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse default: 459fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = -EINVAL; 460fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 461fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 462fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 463fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 464fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 465fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 466c566d299f91bdb622046126dbcb040f9e52572baDaniel Drakestatic enum power_supply_property olpc_xo1_bat_props[] = { 467fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_STATUS, 468ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon POWER_SUPPLY_PROP_CHARGE_TYPE, 469fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_PRESENT, 470fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_HEALTH, 471fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_TECHNOLOGY, 472fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_VOLTAGE_AVG, 47322fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe POWER_SUPPLY_PROP_VOLTAGE_NOW, 474fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_CURRENT_AVG, 47522fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe POWER_SUPPLY_PROP_CURRENT_NOW, 476fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_CAPACITY, 477b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon POWER_SUPPLY_PROP_CAPACITY_LEVEL, 478b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 47920fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe POWER_SUPPLY_PROP_CHARGE_NOW, 480fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_TEMP, 481fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_TEMP_AMBIENT, 482fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_MANUFACTURER, 4831ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse POWER_SUPPLY_PROP_SERIAL_NUMBER, 4848e552c36d90c03d2cabf5373788998966751b609Andres Salomon POWER_SUPPLY_PROP_CHARGE_COUNTER, 4855619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 486fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse}; 487fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 488c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake/* XO-1.5 does not have ambient temperature property */ 489c566d299f91bdb622046126dbcb040f9e52572baDaniel Drakestatic enum power_supply_property olpc_xo15_bat_props[] = { 490c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_STATUS, 491c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CHARGE_TYPE, 492c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_PRESENT, 493c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_HEALTH, 494c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_TECHNOLOGY, 495c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_VOLTAGE_AVG, 496bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_VOLTAGE_NOW, 497c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CURRENT_AVG, 498bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_CURRENT_NOW, 499c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CAPACITY, 500c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CAPACITY_LEVEL, 501bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 502bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_CHARGE_NOW, 503c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_TEMP, 504c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_MANUFACTURER, 505c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_SERIAL_NUMBER, 506c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CHARGE_COUNTER, 5075619d0ba97cd336a100121cf8f2968c4b1f6c848Richard A. Smith POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 508c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake}; 509c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake 510d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon/* EEPROM reading goes completely around the power_supply API, sadly */ 511d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 512d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon#define EEPROM_START 0x20 513d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon#define EEPROM_END 0x80 514d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon#define EEPROM_SIZE (EEPROM_END - EEPROM_START) 515d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 5162c3c8bea608866d8bd9dcf92657d57fdcac011c5Chris Wrightstatic ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj, 517d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon struct bin_attribute *attr, char *buf, loff_t off, size_t count) 518d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon{ 519d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon uint8_t ec_byte; 52004a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon int ret; 52104a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon int i; 522d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 523d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (off >= EEPROM_SIZE) 524d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon return 0; 525d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (off + count > EEPROM_SIZE) 526d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon count = EEPROM_SIZE - off; 527d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 52804a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon for (i = 0; i < count; i++) { 52904a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon ec_byte = EEPROM_START + off + i; 53004a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1); 531d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (ret) { 53204a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon pr_err("olpc-battery: " 53304a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon "EC_BAT_EEPROM cmd @ 0x%x failed - %d!\n", 53404a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon ec_byte, ret); 535d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon return -EIO; 536d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon } 537d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon } 538d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 539d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon return count; 540d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon} 541d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 542d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomonstatic struct bin_attribute olpc_bat_eeprom = { 543d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .attr = { 544d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .name = "eeprom", 545d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .mode = S_IRUGO, 546d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon }, 547d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .size = 0, 548d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .read = olpc_bat_eeprom_read, 549d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon}; 550d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 551144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon/* Allow userspace to see the specific error value pulled from the EC */ 552144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 553144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomonstatic ssize_t olpc_bat_error_read(struct device *dev, 554144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon struct device_attribute *attr, char *buf) 555144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon{ 556144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon uint8_t ec_byte; 557144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon ssize_t ret; 558144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 559144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1); 560144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon if (ret < 0) 561144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon return ret; 562144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 563144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon return sprintf(buf, "%d\n", ec_byte); 564144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon} 565144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 566144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomonstatic struct device_attribute olpc_bat_error = { 567144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .attr = { 568144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .name = "error", 569144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .mode = S_IRUGO, 570144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon }, 571144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .show = olpc_bat_error_read, 572144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon}; 573144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 574fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse/********************************************************************* 575fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * Initialisation 576fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse *********************************************************************/ 577fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 578fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic struct power_supply olpc_bat = { 579c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .name = "olpc-battery", 580fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .get_property = olpc_bat_get_property, 581fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .use_for_apm = 1, 582fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse}; 583fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 584cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drakestatic int olpc_battery_suspend(struct platform_device *pdev, 585cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake pm_message_t state) 586cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake{ 587cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake if (device_may_wakeup(olpc_ac.dev)) 588cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR); 589cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake else 590cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR); 591cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 592cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake if (device_may_wakeup(olpc_bat.dev)) 593cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC 594cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake | EC_SCI_SRC_BATERR); 595cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake else 596cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_clear(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC 597cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake | EC_SCI_SRC_BATERR); 598cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 599cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake return 0; 600cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake} 601cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 602c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic int __devinit olpc_battery_probe(struct platform_device *pdev) 603fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 604c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake int ret; 605fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse uint8_t status; 606fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 607484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon /* 608484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon * We've seen a number of EC protocol changes; this driver requires 609484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon * the latest EC protocol, supported by 0x44 and above. 610484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon */ 611484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon if (olpc_platform_info.ecver < 0x44) { 612484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon printk(KERN_NOTICE "OLPC EC version 0x%02x too old for " 613484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon "battery driver.\n", olpc_platform_info.ecver); 614fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return -ENXIO; 615fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 616fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 617fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1); 618fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 619fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 620fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 621fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse /* Ignore the status. It doesn't actually matter */ 622fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 623c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake ret = power_supply_register(&pdev->dev, &olpc_ac); 624fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 625c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake return ret; 626fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 627c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */ 628c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.properties = olpc_xo15_bat_props; 629c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props); 630c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake } else { /* XO-1 */ 631c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.properties = olpc_xo1_bat_props; 632c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props); 633c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake } 634fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 635c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake ret = power_supply_register(&pdev->dev, &olpc_bat); 636fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 637fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse goto battery_failed; 638fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 639d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon ret = device_create_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 640d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (ret) 641d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon goto eeprom_failed; 642d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 643144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon ret = device_create_file(olpc_bat.dev, &olpc_bat_error); 644144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon if (ret) 645144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon goto error_failed; 646144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 647cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake if (olpc_ec_wakeup_available()) { 648cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake device_set_wakeup_capable(olpc_ac.dev, true); 649cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake device_set_wakeup_capable(olpc_bat.dev, true); 650cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake } 651cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 652c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake return 0; 653fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 654144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomonerror_failed: 655144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 656d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomoneeprom_failed: 657d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon power_supply_unregister(&olpc_bat); 658fb972873a767220333ffb509de8d9131336e212cDavid Woodhousebattery_failed: 659fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse power_supply_unregister(&olpc_ac); 660fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 661fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 662fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 663c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic int __devexit olpc_battery_remove(struct platform_device *pdev) 664fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 665144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon device_remove_file(olpc_bat.dev, &olpc_bat_error); 666d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 667fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse power_supply_unregister(&olpc_bat); 668fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse power_supply_unregister(&olpc_ac); 669c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake return 0; 670fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 671fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 672c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic const struct of_device_id olpc_battery_ids[] __devinitconst = { 673c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake { .compatible = "olpc,xo1-battery" }, 674c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake {} 675c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake}; 676c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel DrakeMODULE_DEVICE_TABLE(of, olpc_battery_ids); 677c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake 6785519d00e6a5d99a163484722ef7cea8bff47bc58Anton Vorontsovstatic struct platform_driver olpc_battery_driver = { 679c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .driver = { 680c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .name = "olpc-battery", 681c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .owner = THIS_MODULE, 682c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .of_match_table = olpc_battery_ids, 683c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake }, 684c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .probe = olpc_battery_probe, 685c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .remove = __devexit_p(olpc_battery_remove), 686cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake .suspend = olpc_battery_suspend, 687c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake}; 688c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake 689300bac7fb85a20b2704dc3645419057992f78565Axel Linmodule_platform_driver(olpc_battery_driver); 690fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 691fb972873a767220333ffb509de8d9131336e212cDavid WoodhouseMODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 692fb972873a767220333ffb509de8d9131336e212cDavid WoodhouseMODULE_LICENSE("GPL"); 693fb972873a767220333ffb509de8d9131336e212cDavid WoodhouseMODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine"); 694